diff --git a/Gopkg.lock b/Gopkg.lock index fa269a0c..354b08d7 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -11,17 +11,18 @@ "logging/internal", "monitoring/apiv3" ] - revision = "20d4028b8a750c2aca76bf9fefa8ed2d0109b573" - version = "v0.19.0" + revision = "4b98a6370e36d7a85192e7bad08a4ebd82eac2a8" + version = "v0.20.0" [[projects]] + branch = "master" name = "code.cloudfoundry.org/copilot" packages = [ ".", "api", "testhelpers" ] - revision = "ac2922c9b5cfb46d70befdc91612343e6e382811" + revision = "feb69363fff010ea48e1dacd38ca859528cfa0d4" [[projects]] name = "github.com/Azure/go-autorest" @@ -132,6 +133,7 @@ "aws/session", "aws/signer/v4", "awstesting/unit", + "internal/sdkio", "internal/sdkrand", "internal/shareddefaults", "private/protocol", @@ -141,14 +143,14 @@ "private/protocol/xml/xmlutil", "service/sts" ] - revision = "9a79087b1148376f4dd860c188c948479e2def3b" - version = "v1.13.7" + revision = "4b5324816e154564ef4e490842c2e40560971f75" + version = "v1.13.24" [[projects]] branch = "master" name = "github.com/beorn7/perks" packages = ["quantile"] - revision = "4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9" + revision = "3a771d992973f24aa725d07868b467d1ddfceafb" [[projects]] name = "github.com/cactus/go-statsd-client" @@ -215,8 +217,8 @@ [[projects]] name = "github.com/dgrijalva/jwt-go" packages = ["."] - revision = "dbeaa9332f19a944acb5736b4456cfcc02140e29" - version = "v3.1.0" + revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" + version = "v3.2.0" [[projects]] branch = "master" @@ -225,7 +227,7 @@ "digestset", "reference" ] - revision = "6fca8d6e6713acbdf3f9ca40cf6370fc5ee5ee53" + revision = "83389a148052d74ac602f5f1d62f86ff2f3c4aa5" [[projects]] branch = "master" @@ -258,10 +260,8 @@ "envoy/api/v2/route", "envoy/config/filter/accesslog/v2", "envoy/config/filter/fault/v2", - "envoy/config/filter/http/fault/v2", "envoy/config/filter/network/http_connection_manager/v2", "envoy/config/filter/network/mongo_proxy/v2", - "envoy/config/filter/network/redis_proxy/v2", "envoy/config/filter/network/tcp_proxy/v2", "envoy/service/discovery/v2", "envoy/type", @@ -270,7 +270,7 @@ "pkg/server", "pkg/util" ] - revision = "aa344ee5f4fff239fadab634413ca6764025511c" + revision = "9fdf4bd79736a87c78b3d48b7baa84ea24be1c1a" [[projects]] name = "github.com/fluent/fluent-logger-golang" @@ -296,20 +296,20 @@ [[projects]] name = "github.com/go-ini/ini" packages = ["."] - revision = "32e4c1e6bc4e7d0d8451aa6b75200d19e37a536a" - version = "v1.32.0" + revision = "6333e38ac20b8949a8dd68baa3650f4dee8f39f0" + version = "v1.33.0" [[projects]] branch = "master" name = "github.com/go-openapi/jsonpointer" packages = ["."] - revision = "779f45308c19820f1a69e9a4cd965f496e0da10f" + revision = "3a0015ad55fa9873f41605d3e8f28cd279c32ab2" [[projects]] branch = "master" name = "github.com/go-openapi/jsonreference" packages = ["."] - revision = "36d33bfe519efae5632669801b180bf1a245da3b" + revision = "3fb327e6747da3043567ee86abd02bb6376b6be2" [[projects]] name = "github.com/go-openapi/spec" @@ -320,7 +320,7 @@ branch = "master" name = "github.com/go-openapi/swag" packages = ["."] - revision = "0d03ad0b6405ada874d59d97c416b5cf4234e154" + revision = "ceb469cb0fdf2d792f28d771bc05da6c606f55e5" [[projects]] name = "github.com/go-redis/redis" @@ -334,8 +334,8 @@ "internal/singleflight", "internal/util" ] - revision = "68362cfda1eeb3a69316e7bc00169a9a8de4823a" - version = "v6.9.2" + revision = "877867d2845fbaf86798befe410b6ceb6f5c29a3" + version = "v6.10.2" [[projects]] name = "github.com/gobwas/glob" @@ -366,34 +366,10 @@ packages = [ "gogoproto", "jsonpb", - "plugin/compare", - "plugin/defaultcheck", - "plugin/description", - "plugin/embedcheck", - "plugin/enumstringer", - "plugin/equal", - "plugin/face", - "plugin/gostring", - "plugin/marshalto", - "plugin/oneofcheck", - "plugin/populate", - "plugin/size", - "plugin/stringer", - "plugin/testgen", - "plugin/union", - "plugin/unmarshal", "proto", "protoc-gen-gogo/descriptor", - "protoc-gen-gogo/generator", - "protoc-gen-gogo/grpc", - "protoc-gen-gogo/plugin", - "protoc-gen-gogoslick", - "protoc-min-version", "sortkeys", - "types", - "vanity", - "vanity/command", - "version" + "types" ] revision = "342cbe0a04158f6dcb03ca0079991a51a4248c02" version = "v0.5" @@ -412,7 +388,6 @@ revision = "66deaeb636dff1ac7d938ce666d090556056a4b0" [[projects]] - branch = "master" name = "github.com/golang/protobuf" packages = [ "jsonpb", @@ -427,13 +402,14 @@ "ptypes/timestamp", "ptypes/wrappers" ] - revision = "bbd03ef6da3a115852eaf24c8a1c46aeb39aa175" + revision = "925541529c1fa6821df4e44ce2723319eb2be768" + version = "v1.0.0" [[projects]] branch = "master" name = "github.com/golang/sync" packages = ["errgroup"] - revision = "fd80eb99c8f653c847d294a001bdf2a3a6f768f5" + revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" [[projects]] branch = "master" @@ -493,7 +469,7 @@ "openstack/utils", "pagination" ] - revision = "afbf0422412f5dc726fa12be280fa0c3cb31fcbd" + revision = "2daf3049f2a9913e6e5bf54926fd90efb1f9a0f0" [[projects]] name = "github.com/gorilla/context" @@ -520,13 +496,13 @@ ".", "diskcache" ] - revision = "2bcd89a1743fd4b373f7370ce8ddc14dfbd18229" + revision = "9cad4c3443a7200dd6400aef47183728de563a38" [[projects]] branch = "master" name = "github.com/grpc-ecosystem/go-grpc-middleware" packages = ["."] - revision = "f7cbcd2ed22c7f17a07b5d8d5523a41626fc60fb" + revision = "aed189ae50cf2ee326c1de8c083f3187e574e0d8" [[projects]] name = "github.com/grpc-ecosystem/go-grpc-prometheus" @@ -604,15 +580,16 @@ revision = "bf9dde6d0d2c004a008c27aaee91170c786f6db8" [[projects]] - branch = "master" name = "github.com/huandu/xstrings" packages = ["."] revision = "2bf18b218c51864a87384c06996e40ff9dcff8e1" + version = "v1.0.0" [[projects]] name = "github.com/imdario/mergo" packages = ["."] - revision = "6633656539c1639d9d78127b7d47c622b5d7b6dc" + revision = "163f41321a19dd09362d4c63cc2489db2015f1f4" + version = "0.3.2" [[projects]] name = "github.com/inconshreveable/mousetrap" @@ -624,7 +601,7 @@ branch = "master" name = "github.com/istio/tools" packages = ["protoc-gen-docs"] - revision = "362a2b16a4fc3877e6667d89df688bae514de4dd" + revision = "d107f7deed6a878efd3adc307bc6f197f78b20e6" [[projects]] name = "github.com/jmespath/go-jmespath" @@ -634,8 +611,8 @@ [[projects]] name = "github.com/json-iterator/go" packages = ["."] - revision = "3353055b2a1a5ae1b6a8dfde887a524e7088f3a2" - version = "1.1.2" + revision = "ca39e5af3ece67bbcda3d0f4f56a8e24d9f2dad4" + version = "1.1.3" [[projects]] name = "github.com/juju/ratelimit" @@ -657,7 +634,7 @@ "jlexer", "jwriter" ] - revision = "32fa128f234d041f196a9f3e0fea5ac9772c08e1" + revision = "8b799c424f57fa123fc63a99d6383bc6e4c02578" [[projects]] name = "github.com/matttproud/golang_protobuf_extensions" @@ -674,8 +651,8 @@ [[projects]] name = "github.com/modern-go/concurrent" packages = ["."] - revision = "938152ca6a933f501bb238954eebd3cbcbf489ff" - version = "1.0.2" + revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + version = "1.0.3" [[projects]] name = "github.com/modern-go/reflect2" @@ -729,8 +706,8 @@ "types", "util" ] - revision = "4b934006914c7964e89563d54bbfc63167922aa0" - version = "v0.5.13" + revision = "688594c3786b0805d061a0de387f6a265a7fa9d0" + version = "v0.7.1" [[projects]] name = "github.com/opencontainers/go-digest" @@ -739,9 +716,10 @@ version = "v1.0.0-rc1" [[projects]] + branch = "master" name = "github.com/openshift/api" packages = ["apps/v1"] - revision = "0d921e363e951d89f583292c60d013c318df64dc" + revision = "dca24d1902afee9d2be02425a2d7c9f910063631" [[projects]] name = "github.com/opentracing/opentracing-go" @@ -796,7 +774,7 @@ ".", "cacheobject" ] - revision = "0dec1b30a0215bb68605dfc568e8855066c9202d" + revision = "525d0eb5f91d30e3b1548de401b7ef9ea6898520" [[projects]] name = "github.com/prometheus/client_golang" @@ -824,7 +802,7 @@ "log", "model" ] - revision = "6fb6fce6f8b75884b92e1889c150403fc0872c5e" + revision = "38c53a9f4bfcd932d1b00bfc65e256a7fba6b37a" [[projects]] branch = "master" @@ -835,7 +813,7 @@ "nfs", "xfs" ] - revision = "d274e363d5759d1c916232217be421f1cc89c5fe" + revision = "780932d4fbbe0e69b84c34c20f5c8d0981e109ea" [[projects]] branch = "master" @@ -843,6 +821,12 @@ packages = ["."] revision = "daa2bca1c13fce65dabc24d4fbd5054d50cf66d9" +[[projects]] + branch = "master" + name = "github.com/rcrowley/go-metrics" + packages = ["."] + revision = "8732c616f52954686704c8645fe1a9d59e9df7c1" + [[projects]] name = "github.com/russross/blackfriday" packages = ["."] @@ -864,8 +848,8 @@ [[projects]] name = "github.com/sirupsen/logrus" packages = ["."] - revision = "d682213848ed68c0a260ca37d6dd5ace8423f5ba" - version = "v1.0.4" + revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc" + version = "v1.0.5" [[projects]] name = "github.com/spf13/cobra" @@ -873,8 +857,8 @@ ".", "doc" ] - revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b" - version = "v0.0.1" + revision = "a1f051bc3eba734da4772d60e2d677f47cf93ef4" + version = "v0.0.2" [[projects]] name = "github.com/spf13/pflag" @@ -912,6 +896,7 @@ ".", "internal/baggage", "internal/spanlog", + "internal/throttler", "log", "thrift-gen/agent", "thrift-gen/jaeger", @@ -921,14 +906,20 @@ "transport/zipkin", "utils" ] - revision = "3ac96c6e679cb60a74589b0d0aa7c70a906183f7" - version = "v2.11.2" + revision = "c107110d057826281414cb964f167bce5be17588" + version = "v2.12.0" [[projects]] name = "github.com/uber/jaeger-lib" packages = ["metrics"] - revision = "7f95f4f7e80028096410abddaae2556e4c61b59f" - version = "v1.3.1" + revision = "4267858c0679cd4e47cefed8d7f70fd386cfb567" + version = "v1.4.0" + +[[projects]] + branch = "master" + name = "github.com/yashtewari/glob-intersection" + packages = ["."] + revision = "7af743e8ec8480fee1932a737a406f7ec817f910" [[projects]] branch = "master" @@ -939,7 +930,26 @@ "parse", "pm" ] - revision = "7d7bc8747e3f614c5c587729a341fe7d8903cdb8" + revision = "84ea3a3c79b3c4b3b39606cc96f255cd63635ce0" + +[[projects]] + name = "go.opencensus.io" + packages = [ + "exporter/stackdriver/propagation", + "internal", + "internal/tagencoding", + "plugin/ocgrpc", + "plugin/ochttp", + "plugin/ochttp/propagation/b3", + "stats", + "stats/internal", + "stats/view", + "tag", + "trace", + "trace/propagation" + ] + revision = "6e3f034057826b530038d93267906ec3c012183f" + version = "v0.6.0" [[projects]] name = "go.uber.org/atomic" @@ -977,7 +987,7 @@ "scrypt", "ssh/terminal" ] - revision = "91a49db82a88618983a78a06c1cbd4e00ab749ab" + revision = "88942b9c40a4c9d203b82b3731787b672d6e809b" [[projects]] branch = "master" @@ -995,7 +1005,7 @@ "lex/httplex", "trace" ] - revision = "cbe0f9307d0156177f9dd5dc85da1a31abc5f2fb" + revision = "6078986fec03a1dcc236c34816c71b0e05018fda" [[projects]] branch = "master" @@ -1007,13 +1017,13 @@ "jws", "jwt" ] - revision = "2f32c3ac0fa4fb807a0fcefb0b6f2468a0d99bd0" + revision = "fdc9e635145ae97e6c2cb777c48305600cf515cb" [[projects]] branch = "master" name = "golang.org/x/sync" packages = ["semaphore"] - revision = "fd80eb99c8f653c847d294a001bdf2a3a6f768f5" + revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" [[projects]] branch = "master" @@ -1024,7 +1034,7 @@ "windows/registry", "windows/svc/eventlog" ] - revision = "f6cff0780e542efa0c8e864dc8fa522808f6a598" + revision = "378d26f46672a356c46195c28f61bdb4c0a781dd" [[projects]] name = "golang.org/x/text" @@ -1064,7 +1074,7 @@ branch = "master" name = "golang.org/x/time" packages = ["rate"] - revision = "6dc17368e09b0e8634d71cac8168d853e869a0c7" + revision = "26559e0f760e39c24d730d3224364aef164ee23f" [[projects]] branch = "master" @@ -1073,7 +1083,7 @@ "go/ast/astutil", "imports" ] - revision = "73e16cff9e0d4a802937444bebb562458548241d" + revision = "77106db15f689a60e7d4e085d967ac557b918fb2" [[projects]] branch = "master" @@ -1092,7 +1102,7 @@ "transport/grpc", "transport/http" ] - revision = "ab90adb3efa287b869ecb698db42f923cc734972" + revision = "dbbc13f71100fa6ece308335445fca6bb0dd5c2f" [[projects]] name = "google.golang.org/appengine" @@ -1128,7 +1138,7 @@ "googleapis/rpc/status", "protobuf/field_mask" ] - revision = "2d9486acae19cf9bd0c093d7dc236a323726a9e4" + revision = "ab0870e398d5dd054b868c0db1481ab029b9a9f2" [[projects]] name = "google.golang.org/grpc" @@ -1163,8 +1173,8 @@ "tap", "transport" ] - revision = "8e4536a86ab602859c20df5ebfd0bd4228d08655" - version = "v1.10.0" + revision = "1e2570b1b19ade82d8dbb31bba4e65e9f9ef5b34" + version = "v1.11.1" [[projects]] name = "gopkg.in/alecthomas/kingpin.v2" @@ -1175,8 +1185,8 @@ [[projects]] name = "gopkg.in/inf.v0" packages = ["."] - revision = "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4" - version = "v0.9.0" + revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf" + version = "v0.9.1" [[projects]] name = "gopkg.in/russross/blackfriday.v2" @@ -1191,8 +1201,8 @@ "cipher", "json" ] - revision = "6ee92191fea850cdcab9a18867abf5f521cdbadb" - version = "v2.1.4" + revision = "76dd09796242edb5b897103a75df2645c028c960" + version = "v2.1.6" [[projects]] branch = "v2" @@ -1203,11 +1213,10 @@ [[projects]] name = "gopkg.in/yaml.v2" packages = ["."] - revision = "7f97868eec74b32b0982dd158a51a446d1da7eb5" - version = "v2.1.1" + revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" + version = "v2.2.1" [[projects]] - branch = "master" name = "istio.io/api" packages = [ "authentication/v1alpha1", @@ -1221,7 +1230,7 @@ "rbac/v1alpha1", "routing/v1alpha1" ] - revision = "64e9770daf900edc2a50fc4c57793f370cfdaf75" + revision = "1e6e1c99aab41d28aa59c2e48afa4c4dad2da2da" [[projects]] name = "istio.io/fortio" @@ -1241,7 +1250,6 @@ version = "v0.8.1" [[projects]] - branch = "release-1.9" name = "k8s.io/api" packages = [ "admission/v1beta1", @@ -1274,7 +1282,8 @@ "storage/v1alpha1", "storage/v1beta1" ] - revision = "acf347b865f29325eb61f4cd2df11e86e073a5ee" + revision = "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" + version = "kubernetes-1.9.1" [[projects]] branch = "release-1.9" @@ -1287,12 +1296,12 @@ "pkg/client/clientset/clientset/typed/apiextensions/v1beta1", "pkg/features" ] - revision = "8cc229a989f288859cf7d7088705c5ee80117966" + revision = "c958999085e1db202fb83549b3c0ff8abd3f5b94" [[projects]] - branch = "release-1.9" name = "k8s.io/apimachinery" packages = [ + "pkg/api/equality", "pkg/api/errors", "pkg/api/meta", "pkg/api/resource", @@ -1302,6 +1311,7 @@ "pkg/apis/meta/v1alpha1", "pkg/conversion", "pkg/conversion/queryparams", + "pkg/conversion/unstructured", "pkg/fields", "pkg/labels", "pkg/runtime", @@ -1340,7 +1350,7 @@ "third_party/forked/golang/netutil", "third_party/forked/golang/reflect" ] - revision = "19e3f5aa3adca672c153d324e6b7d82ff8935f03" + revision = "18a564baac720819100827c16fdebcadb05b2d0d" [[projects]] branch = "master" @@ -1349,7 +1359,7 @@ "pkg/features", "pkg/util/feature" ] - revision = "74a8a89814a24637e718e271b747a717c24da88f" + revision = "f4a9d31325865f18b8023622a564578f079d582b" [[projects]] branch = "release-6.0" @@ -1451,7 +1461,7 @@ "util/jsonpath", "util/workqueue" ] - revision = "9389c055a838d4f208b699b3c7c51b70f2368861" + revision = "90539b4e75a8daaf7f67c3874c6180bfb1a63936" [[projects]] name = "k8s.io/cluster-registry" @@ -1474,8 +1484,8 @@ "pkg/timeconv", "pkg/version" ] - revision = "6af75a8fd72e2aa18a2b278cfe5c7a1c5feca7f2" - version = "v2.8.1" + revision = "a80231648a1473929271764b920a8e346f6de844" + version = "v2.8.2" [[projects]] name = "k8s.io/ingress" @@ -1495,10 +1505,7 @@ [[projects]] branch = "master" name = "k8s.io/kube-openapi" - packages = [ - "pkg/common", - "pkg/util/proto" - ] + packages = ["pkg/common"] revision = "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf" [[projects]] @@ -1514,11 +1521,11 @@ "pkg/util/parsers", "pkg/util/pointer" ] - revision = "3a9f96237f34694167716afcbde53e7365a4ca84" + revision = "f947188850f4e8087459921129e8dce9b35325f1" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "1202ceb12906b81e13742fb6b417387f0797c64037f7e8570b06af46f39c355f" + inputs-digest = "62024f0a7ac9b9eb574b6bd9af2ce90e0f6717966381c83656b9698bbaf6a2ed" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index be6f6e03..a98fd5b2 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -1,6 +1,6 @@ # Gopkg.toml example # -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html # for detailed Gopkg.toml documentation. # # required = ["github.com/user/thing/cmd/thing"] @@ -16,74 +16,30 @@ # source = "github.com/myfork/project2" # # [[override]] -# name = "github.com/x/y" -# version = "2.4.0" - -# TODO: fork the repo to checkin artifacts, or find an alternative repo that has artifacts available. -# This repo includes only istio-generated files. - +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true required = [ ### BEGIN Mixer codegen deps - "github.com/gogo/protobuf/proto", - "github.com/gogo/protobuf/jsonpb", - "github.com/gogo/protobuf/protoc-gen-gogoslick", - "github.com/gogo/protobuf/gogoproto", "github.com/istio/tools/protoc-gen-docs", - "github.com/gogo/protobuf/protoc-min-version", ### END Mixer codegen deps - # fortio binary (main) is used by the testing framework and should not be - # pruned + # fortio is built in vendor for the testing framework "istio.io/fortio", ] -### Pruning settings -[prune] - unused-packages = true - go-tests = true - non-go = true - [[prune.project]] - name = "istio.io/fortio" - non-go = false - unused-packages = false - [[prune.project]] - name = "istio.io/api" - non-go = false - unused-packages = false - [[prune.project]] - name = "github.com/envoyproxy/go-control-plane" - non-go = false - unused-packages = false - [[prune.project]] - name = "github.com/gogo/googleapis" - non-go = false - unused-packages = false - [[prune.project]] - name = "github.com/gogo/protobuf" - non-go = false - unused-packages = false -### - -[[constraint]] - name = "google.golang.org/grpc" - version = "^1.8.2" # match istio/api - - -# Lock mergo against kubernetes/client-go's version to fix merging related kubeconfig bugs -# related to CertificateAuthorityData/certificate-authority-data failures -# https://github.com/kubernetes/client-go/blob/7cd1d3291b7d9b1e2d54d4b69eb65995eaf8888e/tools/clientcmd/client_config.go#L160-L162 +# To use reference package: +# vendor/k8s.io/kubernetes/pkg/util/parsers/parsers.go:36:16: undefined: reference.ParseNormalizedNamed [[override]] - name = "github.com/imdario/mergo" - revision = "6633656539c1639d9d78127b7d47c622b5d7b6dc" + name = "github.com/docker/distribution" + branch = "master" + +# TODO: switch to 1.10 and newer client-go -# When necessary, override transitive contraints that might be pinned -# to older versions (e.g. ingress-nginx pinned to 1.8). -# -# kubernetes has a quarterly release cycle. For now the k8s -# dependencies below follow this convention, but that could possibly -# change in the future as repos are further decoupled from -# kubernetes/kubernetes proper. -# # client-go release-6.0 corresponds to k8s release-1.9 branch. See # https://github.com/kubernetes/client-go/tree/release-6.0#compatibility-matrix # for details. @@ -91,92 +47,293 @@ required = [ name = "k8s.io/client-go" branch = "release-6.0" +# matching client-go 6 == k8s 1.9 == v9 (!) [[override]] - name = "k8s.io/apimachinery" - branch = "release-1.9" + name = "github.com/Azure/go-autorest" + version = "v9.10.0" +# our mock glog: [[override]] - name = "k8s.io/api" - branch = "release-1.9" + name = "github.com/golang/glog" + source = "github.com/istio/glog" -[[override]] - name = "github.com/Azure/go-autorest" - version = "v9.10.0" +[[constraint]] + name = "cloud.google.com/go" + version = "0.20.0" [[constraint]] - name = "k8s.io/apiextensions-apiserver" - branch = "release-1.9" + branch = "master" + name = "code.cloudfoundry.org/copilot" -[[override]] - name = "k8s.io/kubernetes" - branch = "release-1.9" +[[constraint]] + name = "github.com/DataDog/datadog-go" + version = "2.0.0" -# TODO(https://github.com/istio/istio/issues/2413). Keep -# k8s.io/ingress-nginx pinned to an older version until istio ingress code -# is refactored. -# -# istio.io/istio/pilot/pkg/config/kube/ingress uses the following nginx -# controller packages from an older version of k8s.io/ingress which -# have since been made internal and are no longer available. -# -# "k8s.io/ingress-nginx/core/pkg/ingress/status" -# "k8s.io/ingress-nginx/core/pkg/ingress/store" -# "k8s.io/ingress-nginx/core/pkg/ingress/annotations/class" -#[[constraint]] -# name = "k8s.io/ingress-nginx" -# revision = "0c6f15e372c831de52fcc393932540bb3a6d51b5" +[[constraint]] + name = "github.com/alicebob/miniredis" + version = "2.3.2" -[[override]] - name = "github.com/apache/thrift" - version = ">=0.9.3, <0.11.0" +[[constraint]] + name = "github.com/aws/aws-sdk-go" + version = "1.13.24" -# Default behavior of dep is to get the latest tagged version for fortio -# which is what we want. +[[constraint]] + name = "github.com/cactus/go-statsd-client" + version = "3.1.1" [[constraint]] - name = "istio.io/api" - branch = "master" + name = "github.com/cenkalti/backoff" + version = "2.0.0" + +[[constraint]] + name = "github.com/circonus-labs/circonus-gometrics" + version = "2.1.0" + +[[constraint]] + branch = "v2" + name = "github.com/coreos/go-oidc" + +[[constraint]] + name = "github.com/davecgh/go-spew" + version = "1.1.0" [[constraint]] name = "github.com/envoyproxy/go-control-plane" branch = "master" -### Begin Mixer codegen dep pinning +[[constraint]] + name = "github.com/fluent/fluent-logger-golang" + version = "1.3.0" -[[override]] +[[constraint]] + name = "github.com/ghodss/yaml" + version = "1.0.0" + +[[constraint]] + name = "github.com/go-redis/redis" + version = "6.10.2" + +[[constraint]] + branch = "master" + name = "github.com/gogo/googleapis" + +[[constraint]] name = "github.com/gogo/protobuf" - version = "=0.5" + version = "0.5.0" -# Api is pinning this to a version, needs to be fixed. Protobuf is supposed to have stable master. -# The api constraint prevents dep update -[[override]] +[[constraint]] name = "github.com/golang/protobuf" + version = "1.0.0" + +[[constraint]] branch = "master" + name = "github.com/golang/sync" -### End Mixer codegen dep pinning +[[constraint]] + name = "github.com/google/go-github" + version = "15.0.0" [[constraint]] - name = "github.com/open-policy-agent/opa" - version = "0.5.13" + name = "github.com/google/uuid" + version = "0.2.0" -# To use reference package: -# vendor/k8s.io/kubernetes/pkg/util/parsers/parsers.go:36:16: undefined: reference.ParseNormalizedNamed -[[override]] - name = "github.com/docker/distribution" +[[constraint]] + name = "github.com/googleapis/gax-go" + version = "2.0.0" + +[[constraint]] + name = "github.com/gorilla/mux" + version = "1.6.1" + +[[constraint]] + name = "github.com/gorilla/websocket" + version = "1.2.0" + +[[constraint]] branch = "master" + name = "github.com/grpc-ecosystem/go-grpc-middleware" [[constraint]] - name = "code.cloudfoundry.org/copilot" - revision = "ac2922c9b5cfb46d70befdc91612343e6e382811" + name = "github.com/grpc-ecosystem/go-grpc-prometheus" + version = "1.1.0" [[constraint]] branch = "master" - name = "github.com/istio/tools" + name = "github.com/grpc-ecosystem/grpc-opentracing" + +[[constraint]] + name = "github.com/hashicorp/consul" + version = "1.0.6" + +[[constraint]] + branch = "master" + name = "github.com/hashicorp/go-multierror" + +[[constraint]] + name = "github.com/howeyc/fsnotify" + version = "0.9.0" + +[[constraint]] + name = "github.com/natefinch/lumberjack" + version = "2.1.0" + +[[constraint]] + name = "github.com/onsi/gomega" + version = "1.3.0" + +[[constraint]] + name = "github.com/open-policy-agent/opa" + version = "0.7.1" [[constraint]] + branch = "master" name = "github.com/openshift/api" - revision = "0d921e363e951d89f583292c60d013c318df64dc" -[[override]] - name = "github.com/golang/glog" - source = "github.com/istio/glog" +[[constraint]] + name = "github.com/opentracing/opentracing-go" + version = "1.0.2" + +[[constraint]] + name = "github.com/pborman/uuid" + version = "1.1.0" + +[[constraint]] + name = "github.com/pmezard/go-difflib" + version = "1.0.0" + +[[constraint]] + name = "github.com/prometheus/client_golang" + version = "0.9.0-pre1" + +[[constraint]] + branch = "master" + name = "github.com/prometheus/client_model" + +[[constraint]] + branch = "master" + name = "github.com/prometheus/common" + +[[constraint]] + branch = "master" + name = "github.com/prometheus/prom2json" + +[[constraint]] + name = "github.com/satori/go.uuid" + version = "1.2.0" + +[[constraint]] + name = "github.com/spf13/cobra" + version = "0.0.2" + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.2.1" + +[[constraint]] + name = "github.com/uber/jaeger-client-go" + version = "2.12.0" + +[[constraint]] + name = "go.uber.org/atomic" + version = "1.2.0" + +[[constraint]] + name = "go.uber.org/multierr" + version = "1.1.0" + +[[constraint]] + name = "go.uber.org/zap" + version = "1.7.1" + +[[constraint]] + branch = "master" + name = "golang.org/x/net" + +[[constraint]] + branch = "master" + name = "golang.org/x/oauth2" + +[[constraint]] + branch = "master" + name = "golang.org/x/time" + +[[constraint]] + branch = "master" + name = "golang.org/x/tools" + +[[constraint]] + branch = "master" + name = "google.golang.org/api" + +[[constraint]] + branch = "master" + name = "google.golang.org/genproto" + +[[constraint]] + name = "google.golang.org/grpc" + version = "1.11.1" + +[[constraint]] + branch = "v2" + name = "gopkg.in/validator.v2" + +[[constraint]] + name = "gopkg.in/yaml.v2" + version = "2.2.1" + +# TODO: switch back to master once pilot code is caught up +[[constraint]] + revision = "1e6e1c99aab41d28aa59c2e48afa4c4dad2da2da" + name = "istio.io/api" + +# fortio is latest tagged by default + +[[constraint]] + name = "k8s.io/api" + version = "kubernetes-1.9.1" + +[[constraint]] + branch = "release-1.9" + name = "k8s.io/apiextensions-apiserver" + +[[constraint]] + name = "k8s.io/cluster-registry" + version = "0.0.3" + +[[constraint]] + name = "k8s.io/helm" + version = "2.8.2" + +[[constraint]] + name = "k8s.io/ingress" + version = "0.9.6" + +[[constraint]] + name = "k8s.io/kubernetes" + branch = "release-1.9" + +[prune] + go-tests = true + unused-packages = true + non-go = true + [[prune.project]] + name = "istio.io/fortio" + non-go = false + unused-packages = false + [[prune.project]] + name = "istio.io/api" + non-go = false + unused-packages = false + [[prune.project]] + name = "github.com/envoyproxy/go-control-plane" + non-go = false + unused-packages = false + [[prune.project]] + name = "github.com/gogo/googleapis" + non-go = false + unused-packages = false + [[prune.project]] + name = "github.com/gogo/protobuf" + non-go = false + unused-packages = false + diff --git a/cloud.google.com/go/logging/logging.go b/cloud.google.com/go/logging/logging.go index efc510ea..b341f61f 100644 --- a/cloud.google.com/go/logging/logging.go +++ b/cloud.google.com/go/logging/logging.go @@ -79,6 +79,12 @@ const ( // DefaultBufferedByteLimit is the default value for the BufferedByteLimit LoggerOption. DefaultBufferedByteLimit = 1 << 30 // 1GiB + + // defaultWriteTimeout is the timeout for the underlying write API calls. As + // write API calls are not idempotent, they are not retried on timeout. This + // timeout is to allow clients to degrade gracefully if underlying logging + // service is temporarily impaired for some reason. + defaultWriteTimeout = 10 * time.Minute ) // For testing: @@ -228,6 +234,7 @@ type Logger struct { // Options commonResource *mrpb.MonitoredResource commonLabels map[string]string + writeTimeout time.Duration } // A LoggerOption is a configuration option for a Logger. @@ -406,10 +413,8 @@ func (c *Client) Logger(logID string, opts ...LoggerOption) *Logger { logName: internal.LogPath(c.parent, logID), commonResource: r, } - // TODO(jba): determine the right context for the bundle handler. - ctx := context.TODO() l.bundler = bundler.NewBundler(&logpb.LogEntry{}, func(entries interface{}) { - l.writeLogEntries(ctx, entries.([]*logpb.LogEntry)) + l.writeLogEntries(entries.([]*logpb.LogEntry)) }) l.bundler.DelayThreshold = DefaultDelayThreshold l.bundler.BundleCountThreshold = DefaultEntryCountThreshold @@ -744,13 +749,15 @@ func (l *Logger) Flush() error { return l.client.extractErrorInfo() } -func (l *Logger) writeLogEntries(ctx context.Context, entries []*logpb.LogEntry) { +func (l *Logger) writeLogEntries(entries []*logpb.LogEntry) { req := &logpb.WriteLogEntriesRequest{ LogName: l.logName, Resource: l.commonResource, Labels: l.commonLabels, Entries: entries, } + ctx, cancel := context.WithTimeout(context.Background(), defaultWriteTimeout) + defer cancel() _, err := l.client.client.WriteLogEntries(ctx, req) if err != nil { l.client.error(err) diff --git a/cloud.google.com/go/monitoring/apiv3/alert_policy_client.go b/cloud.google.com/go/monitoring/apiv3/alert_policy_client.go new file mode 100644 index 00000000..7cb10a51 --- /dev/null +++ b/cloud.google.com/go/monitoring/apiv3/alert_policy_client.go @@ -0,0 +1,274 @@ +// Copyright 2018 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 +// +// https://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. + +// AUTO-GENERATED CODE. DO NOT EDIT. + +package monitoring + +import ( + "math" + "time" + + "cloud.google.com/go/internal/version" + gax "github.com/googleapis/gax-go" + "golang.org/x/net/context" + "google.golang.org/api/iterator" + "google.golang.org/api/option" + "google.golang.org/api/transport" + monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" +) + +// AlertPolicyCallOptions contains the retry settings for each method of AlertPolicyClient. +type AlertPolicyCallOptions struct { + ListAlertPolicies []gax.CallOption + GetAlertPolicy []gax.CallOption + CreateAlertPolicy []gax.CallOption + DeleteAlertPolicy []gax.CallOption + UpdateAlertPolicy []gax.CallOption +} + +func defaultAlertPolicyClientOptions() []option.ClientOption { + return []option.ClientOption{ + option.WithEndpoint("monitoring.googleapis.com:443"), + option.WithScopes(DefaultAuthScopes()...), + } +} + +func defaultAlertPolicyCallOptions() *AlertPolicyCallOptions { + retry := map[[2]string][]gax.CallOption{ + {"default", "idempotent"}: { + gax.WithRetry(func() gax.Retryer { + return gax.OnCodes([]codes.Code{ + codes.DeadlineExceeded, + codes.Unavailable, + }, gax.Backoff{ + Initial: 100 * time.Millisecond, + Max: 60000 * time.Millisecond, + Multiplier: 1.3, + }) + }), + }, + } + return &AlertPolicyCallOptions{ + ListAlertPolicies: retry[[2]string{"default", "idempotent"}], + GetAlertPolicy: retry[[2]string{"default", "idempotent"}], + CreateAlertPolicy: retry[[2]string{"default", "non_idempotent"}], + DeleteAlertPolicy: retry[[2]string{"default", "idempotent"}], + UpdateAlertPolicy: retry[[2]string{"default", "non_idempotent"}], + } +} + +// AlertPolicyClient is a client for interacting with Stackdriver Monitoring API. +type AlertPolicyClient struct { + // The connection to the service. + conn *grpc.ClientConn + + // The gRPC API client. + alertPolicyClient monitoringpb.AlertPolicyServiceClient + + // The call options for this service. + CallOptions *AlertPolicyCallOptions + + // The x-goog-* metadata to be sent with each request. + xGoogMetadata metadata.MD +} + +// NewAlertPolicyClient creates a new alert policy service client. +// +// The AlertPolicyService API is used to manage (list, create, delete, +// edit) alert policies in Stackdriver Monitoring. An alerting policy is +// a description of the conditions under which some aspect of your +// system is considered to be "unhealthy" and the ways to notify +// people or services about this state. In addition to using this API, alert +// policies can also be managed through +// Stackdriver Monitoring (at https://cloud.google.com/monitoring/docs/), +// which can be reached by clicking the "Monitoring" tab in +// Cloud Console (at https://console.cloud.google.com/). +func NewAlertPolicyClient(ctx context.Context, opts ...option.ClientOption) (*AlertPolicyClient, error) { + conn, err := transport.DialGRPC(ctx, append(defaultAlertPolicyClientOptions(), opts...)...) + if err != nil { + return nil, err + } + c := &AlertPolicyClient{ + conn: conn, + CallOptions: defaultAlertPolicyCallOptions(), + + alertPolicyClient: monitoringpb.NewAlertPolicyServiceClient(conn), + } + c.setGoogleClientInfo() + return c, nil +} + +// Connection returns the client's connection to the API service. +func (c *AlertPolicyClient) Connection() *grpc.ClientConn { + return c.conn +} + +// Close closes the connection to the API service. The user should invoke this when +// the client is no longer required. +func (c *AlertPolicyClient) Close() error { + return c.conn.Close() +} + +// setGoogleClientInfo sets the name and version of the application in +// the `x-goog-api-client` header passed on each request. Intended for +// use by Google-written clients. +func (c *AlertPolicyClient) setGoogleClientInfo(keyval ...string) { + kv := append([]string{"gl-go", version.Go()}, keyval...) + kv = append(kv, "gapic", version.Repo, "gax", gax.Version, "grpc", grpc.Version) + c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...)) +} + +// ListAlertPolicies lists the existing alerting policies for the project. +func (c *AlertPolicyClient) ListAlertPolicies(ctx context.Context, req *monitoringpb.ListAlertPoliciesRequest, opts ...gax.CallOption) *AlertPolicyIterator { + ctx = insertMetadata(ctx, c.xGoogMetadata) + opts = append(c.CallOptions.ListAlertPolicies[0:len(c.CallOptions.ListAlertPolicies):len(c.CallOptions.ListAlertPolicies)], opts...) + it := &AlertPolicyIterator{} + it.InternalFetch = func(pageSize int, pageToken string) ([]*monitoringpb.AlertPolicy, string, error) { + var resp *monitoringpb.ListAlertPoliciesResponse + req.PageToken = pageToken + if pageSize > math.MaxInt32 { + req.PageSize = math.MaxInt32 + } else { + req.PageSize = int32(pageSize) + } + err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { + var err error + resp, err = c.alertPolicyClient.ListAlertPolicies(ctx, req, settings.GRPC...) + return err + }, opts...) + if err != nil { + return nil, "", err + } + return resp.AlertPolicies, resp.NextPageToken, nil + } + fetch := func(pageSize int, pageToken string) (string, error) { + items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) + if err != nil { + return "", err + } + it.items = append(it.items, items...) + return nextPageToken, nil + } + it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) + return it +} + +// GetAlertPolicy gets a single alerting policy. +func (c *AlertPolicyClient) GetAlertPolicy(ctx context.Context, req *monitoringpb.GetAlertPolicyRequest, opts ...gax.CallOption) (*monitoringpb.AlertPolicy, error) { + ctx = insertMetadata(ctx, c.xGoogMetadata) + opts = append(c.CallOptions.GetAlertPolicy[0:len(c.CallOptions.GetAlertPolicy):len(c.CallOptions.GetAlertPolicy)], opts...) + var resp *monitoringpb.AlertPolicy + err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { + var err error + resp, err = c.alertPolicyClient.GetAlertPolicy(ctx, req, settings.GRPC...) + return err + }, opts...) + if err != nil { + return nil, err + } + return resp, nil +} + +// CreateAlertPolicy creates a new alerting policy. +func (c *AlertPolicyClient) CreateAlertPolicy(ctx context.Context, req *monitoringpb.CreateAlertPolicyRequest, opts ...gax.CallOption) (*monitoringpb.AlertPolicy, error) { + ctx = insertMetadata(ctx, c.xGoogMetadata) + opts = append(c.CallOptions.CreateAlertPolicy[0:len(c.CallOptions.CreateAlertPolicy):len(c.CallOptions.CreateAlertPolicy)], opts...) + var resp *monitoringpb.AlertPolicy + err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { + var err error + resp, err = c.alertPolicyClient.CreateAlertPolicy(ctx, req, settings.GRPC...) + return err + }, opts...) + if err != nil { + return nil, err + } + return resp, nil +} + +// DeleteAlertPolicy deletes an alerting policy. +func (c *AlertPolicyClient) DeleteAlertPolicy(ctx context.Context, req *monitoringpb.DeleteAlertPolicyRequest, opts ...gax.CallOption) error { + ctx = insertMetadata(ctx, c.xGoogMetadata) + opts = append(c.CallOptions.DeleteAlertPolicy[0:len(c.CallOptions.DeleteAlertPolicy):len(c.CallOptions.DeleteAlertPolicy)], opts...) + err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { + var err error + _, err = c.alertPolicyClient.DeleteAlertPolicy(ctx, req, settings.GRPC...) + return err + }, opts...) + return err +} + +// UpdateAlertPolicy updates an alerting policy. You can either replace the entire policy with +// a new one or replace only certain fields in the current alerting policy by +// specifying the fields to be updated via updateMask. Returns the +// updated alerting policy. +func (c *AlertPolicyClient) UpdateAlertPolicy(ctx context.Context, req *monitoringpb.UpdateAlertPolicyRequest, opts ...gax.CallOption) (*monitoringpb.AlertPolicy, error) { + ctx = insertMetadata(ctx, c.xGoogMetadata) + opts = append(c.CallOptions.UpdateAlertPolicy[0:len(c.CallOptions.UpdateAlertPolicy):len(c.CallOptions.UpdateAlertPolicy)], opts...) + var resp *monitoringpb.AlertPolicy + err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { + var err error + resp, err = c.alertPolicyClient.UpdateAlertPolicy(ctx, req, settings.GRPC...) + return err + }, opts...) + if err != nil { + return nil, err + } + return resp, nil +} + +// AlertPolicyIterator manages a stream of *monitoringpb.AlertPolicy. +type AlertPolicyIterator struct { + items []*monitoringpb.AlertPolicy + pageInfo *iterator.PageInfo + nextFunc func() error + + // InternalFetch is for use by the Google Cloud Libraries only. + // It is not part of the stable interface of this package. + // + // InternalFetch returns results from a single call to the underlying RPC. + // The number of results is no greater than pageSize. + // If there are no more results, nextPageToken is empty and err is nil. + InternalFetch func(pageSize int, pageToken string) (results []*monitoringpb.AlertPolicy, nextPageToken string, err error) +} + +// PageInfo supports pagination. See the google.golang.org/api/iterator package for details. +func (it *AlertPolicyIterator) PageInfo() *iterator.PageInfo { + return it.pageInfo +} + +// Next returns the next result. Its second return value is iterator.Done if there are no more +// results. Once Next returns Done, all subsequent calls will return Done. +func (it *AlertPolicyIterator) Next() (*monitoringpb.AlertPolicy, error) { + var item *monitoringpb.AlertPolicy + if err := it.nextFunc(); err != nil { + return item, err + } + item = it.items[0] + it.items = it.items[1:] + return item, nil +} + +func (it *AlertPolicyIterator) bufLen() int { + return len(it.items) +} + +func (it *AlertPolicyIterator) takeBuf() interface{} { + b := it.items + it.items = nil + return b +} diff --git a/cloud.google.com/go/monitoring/apiv3/notification_channel_client.go b/cloud.google.com/go/monitoring/apiv3/notification_channel_client.go new file mode 100644 index 00000000..54fdbc61 --- /dev/null +++ b/cloud.google.com/go/monitoring/apiv3/notification_channel_client.go @@ -0,0 +1,369 @@ +// Copyright 2018 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 +// +// https://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. + +// AUTO-GENERATED CODE. DO NOT EDIT. + +package monitoring + +import ( + "math" + "time" + + "cloud.google.com/go/internal/version" + gax "github.com/googleapis/gax-go" + "golang.org/x/net/context" + "google.golang.org/api/iterator" + "google.golang.org/api/option" + "google.golang.org/api/transport" + monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" +) + +// NotificationChannelCallOptions contains the retry settings for each method of NotificationChannelClient. +type NotificationChannelCallOptions struct { + ListNotificationChannelDescriptors []gax.CallOption + GetNotificationChannelDescriptor []gax.CallOption + ListNotificationChannels []gax.CallOption + GetNotificationChannel []gax.CallOption + CreateNotificationChannel []gax.CallOption + UpdateNotificationChannel []gax.CallOption + DeleteNotificationChannel []gax.CallOption +} + +func defaultNotificationChannelClientOptions() []option.ClientOption { + return []option.ClientOption{ + option.WithEndpoint("monitoring.googleapis.com:443"), + option.WithScopes(DefaultAuthScopes()...), + } +} + +func defaultNotificationChannelCallOptions() *NotificationChannelCallOptions { + retry := map[[2]string][]gax.CallOption{ + {"default", "idempotent"}: { + gax.WithRetry(func() gax.Retryer { + return gax.OnCodes([]codes.Code{ + codes.DeadlineExceeded, + codes.Unavailable, + }, gax.Backoff{ + Initial: 100 * time.Millisecond, + Max: 60000 * time.Millisecond, + Multiplier: 1.3, + }) + }), + }, + } + return &NotificationChannelCallOptions{ + ListNotificationChannelDescriptors: retry[[2]string{"default", "idempotent"}], + GetNotificationChannelDescriptor: retry[[2]string{"default", "idempotent"}], + ListNotificationChannels: retry[[2]string{"default", "idempotent"}], + GetNotificationChannel: retry[[2]string{"default", "idempotent"}], + CreateNotificationChannel: retry[[2]string{"default", "non_idempotent"}], + UpdateNotificationChannel: retry[[2]string{"default", "non_idempotent"}], + DeleteNotificationChannel: retry[[2]string{"default", "idempotent"}], + } +} + +// NotificationChannelClient is a client for interacting with Stackdriver Monitoring API. +type NotificationChannelClient struct { + // The connection to the service. + conn *grpc.ClientConn + + // The gRPC API client. + notificationChannelClient monitoringpb.NotificationChannelServiceClient + + // The call options for this service. + CallOptions *NotificationChannelCallOptions + + // The x-goog-* metadata to be sent with each request. + xGoogMetadata metadata.MD +} + +// NewNotificationChannelClient creates a new notification channel service client. +// +// The Notification Channel API provides access to configuration that +// controls how messages related to incidents are sent. +func NewNotificationChannelClient(ctx context.Context, opts ...option.ClientOption) (*NotificationChannelClient, error) { + conn, err := transport.DialGRPC(ctx, append(defaultNotificationChannelClientOptions(), opts...)...) + if err != nil { + return nil, err + } + c := &NotificationChannelClient{ + conn: conn, + CallOptions: defaultNotificationChannelCallOptions(), + + notificationChannelClient: monitoringpb.NewNotificationChannelServiceClient(conn), + } + c.setGoogleClientInfo() + return c, nil +} + +// Connection returns the client's connection to the API service. +func (c *NotificationChannelClient) Connection() *grpc.ClientConn { + return c.conn +} + +// Close closes the connection to the API service. The user should invoke this when +// the client is no longer required. +func (c *NotificationChannelClient) Close() error { + return c.conn.Close() +} + +// setGoogleClientInfo sets the name and version of the application in +// the `x-goog-api-client` header passed on each request. Intended for +// use by Google-written clients. +func (c *NotificationChannelClient) setGoogleClientInfo(keyval ...string) { + kv := append([]string{"gl-go", version.Go()}, keyval...) + kv = append(kv, "gapic", version.Repo, "gax", gax.Version, "grpc", grpc.Version) + c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...)) +} + +// ListNotificationChannelDescriptors lists the descriptors for supported channel types. The use of descriptors +// makes it possible for new channel types to be dynamically added. +func (c *NotificationChannelClient) ListNotificationChannelDescriptors(ctx context.Context, req *monitoringpb.ListNotificationChannelDescriptorsRequest, opts ...gax.CallOption) *NotificationChannelDescriptorIterator { + ctx = insertMetadata(ctx, c.xGoogMetadata) + opts = append(c.CallOptions.ListNotificationChannelDescriptors[0:len(c.CallOptions.ListNotificationChannelDescriptors):len(c.CallOptions.ListNotificationChannelDescriptors)], opts...) + it := &NotificationChannelDescriptorIterator{} + it.InternalFetch = func(pageSize int, pageToken string) ([]*monitoringpb.NotificationChannelDescriptor, string, error) { + var resp *monitoringpb.ListNotificationChannelDescriptorsResponse + req.PageToken = pageToken + if pageSize > math.MaxInt32 { + req.PageSize = math.MaxInt32 + } else { + req.PageSize = int32(pageSize) + } + err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { + var err error + resp, err = c.notificationChannelClient.ListNotificationChannelDescriptors(ctx, req, settings.GRPC...) + return err + }, opts...) + if err != nil { + return nil, "", err + } + return resp.ChannelDescriptors, resp.NextPageToken, nil + } + fetch := func(pageSize int, pageToken string) (string, error) { + items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) + if err != nil { + return "", err + } + it.items = append(it.items, items...) + return nextPageToken, nil + } + it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) + return it +} + +// GetNotificationChannelDescriptor gets a single channel descriptor. The descriptor indicates which fields +// are expected / permitted for a notification channel of the given type. +func (c *NotificationChannelClient) GetNotificationChannelDescriptor(ctx context.Context, req *monitoringpb.GetNotificationChannelDescriptorRequest, opts ...gax.CallOption) (*monitoringpb.NotificationChannelDescriptor, error) { + ctx = insertMetadata(ctx, c.xGoogMetadata) + opts = append(c.CallOptions.GetNotificationChannelDescriptor[0:len(c.CallOptions.GetNotificationChannelDescriptor):len(c.CallOptions.GetNotificationChannelDescriptor)], opts...) + var resp *monitoringpb.NotificationChannelDescriptor + err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { + var err error + resp, err = c.notificationChannelClient.GetNotificationChannelDescriptor(ctx, req, settings.GRPC...) + return err + }, opts...) + if err != nil { + return nil, err + } + return resp, nil +} + +// ListNotificationChannels lists the notification channels that have been created for the project. +func (c *NotificationChannelClient) ListNotificationChannels(ctx context.Context, req *monitoringpb.ListNotificationChannelsRequest, opts ...gax.CallOption) *NotificationChannelIterator { + ctx = insertMetadata(ctx, c.xGoogMetadata) + opts = append(c.CallOptions.ListNotificationChannels[0:len(c.CallOptions.ListNotificationChannels):len(c.CallOptions.ListNotificationChannels)], opts...) + it := &NotificationChannelIterator{} + it.InternalFetch = func(pageSize int, pageToken string) ([]*monitoringpb.NotificationChannel, string, error) { + var resp *monitoringpb.ListNotificationChannelsResponse + req.PageToken = pageToken + if pageSize > math.MaxInt32 { + req.PageSize = math.MaxInt32 + } else { + req.PageSize = int32(pageSize) + } + err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { + var err error + resp, err = c.notificationChannelClient.ListNotificationChannels(ctx, req, settings.GRPC...) + return err + }, opts...) + if err != nil { + return nil, "", err + } + return resp.NotificationChannels, resp.NextPageToken, nil + } + fetch := func(pageSize int, pageToken string) (string, error) { + items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) + if err != nil { + return "", err + } + it.items = append(it.items, items...) + return nextPageToken, nil + } + it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) + return it +} + +// GetNotificationChannel gets a single notification channel. The channel includes the relevant +// configuration details with which the channel was created. However, the +// response may truncate or omit passwords, API keys, or other private key +// matter and thus the response may not be 100% identical to the information +// that was supplied in the call to the create method. +func (c *NotificationChannelClient) GetNotificationChannel(ctx context.Context, req *monitoringpb.GetNotificationChannelRequest, opts ...gax.CallOption) (*monitoringpb.NotificationChannel, error) { + ctx = insertMetadata(ctx, c.xGoogMetadata) + opts = append(c.CallOptions.GetNotificationChannel[0:len(c.CallOptions.GetNotificationChannel):len(c.CallOptions.GetNotificationChannel)], opts...) + var resp *monitoringpb.NotificationChannel + err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { + var err error + resp, err = c.notificationChannelClient.GetNotificationChannel(ctx, req, settings.GRPC...) + return err + }, opts...) + if err != nil { + return nil, err + } + return resp, nil +} + +// CreateNotificationChannel creates a new notification channel, representing a single notification +// endpoint such as an email address, SMS number, or pagerduty service. +func (c *NotificationChannelClient) CreateNotificationChannel(ctx context.Context, req *monitoringpb.CreateNotificationChannelRequest, opts ...gax.CallOption) (*monitoringpb.NotificationChannel, error) { + ctx = insertMetadata(ctx, c.xGoogMetadata) + opts = append(c.CallOptions.CreateNotificationChannel[0:len(c.CallOptions.CreateNotificationChannel):len(c.CallOptions.CreateNotificationChannel)], opts...) + var resp *monitoringpb.NotificationChannel + err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { + var err error + resp, err = c.notificationChannelClient.CreateNotificationChannel(ctx, req, settings.GRPC...) + return err + }, opts...) + if err != nil { + return nil, err + } + return resp, nil +} + +// UpdateNotificationChannel updates a notification channel. Fields not specified in the field mask +// remain unchanged. +func (c *NotificationChannelClient) UpdateNotificationChannel(ctx context.Context, req *monitoringpb.UpdateNotificationChannelRequest, opts ...gax.CallOption) (*monitoringpb.NotificationChannel, error) { + ctx = insertMetadata(ctx, c.xGoogMetadata) + opts = append(c.CallOptions.UpdateNotificationChannel[0:len(c.CallOptions.UpdateNotificationChannel):len(c.CallOptions.UpdateNotificationChannel)], opts...) + var resp *monitoringpb.NotificationChannel + err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { + var err error + resp, err = c.notificationChannelClient.UpdateNotificationChannel(ctx, req, settings.GRPC...) + return err + }, opts...) + if err != nil { + return nil, err + } + return resp, nil +} + +// DeleteNotificationChannel deletes a notification channel. +func (c *NotificationChannelClient) DeleteNotificationChannel(ctx context.Context, req *monitoringpb.DeleteNotificationChannelRequest, opts ...gax.CallOption) error { + ctx = insertMetadata(ctx, c.xGoogMetadata) + opts = append(c.CallOptions.DeleteNotificationChannel[0:len(c.CallOptions.DeleteNotificationChannel):len(c.CallOptions.DeleteNotificationChannel)], opts...) + err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { + var err error + _, err = c.notificationChannelClient.DeleteNotificationChannel(ctx, req, settings.GRPC...) + return err + }, opts...) + return err +} + +// NotificationChannelDescriptorIterator manages a stream of *monitoringpb.NotificationChannelDescriptor. +type NotificationChannelDescriptorIterator struct { + items []*monitoringpb.NotificationChannelDescriptor + pageInfo *iterator.PageInfo + nextFunc func() error + + // InternalFetch is for use by the Google Cloud Libraries only. + // It is not part of the stable interface of this package. + // + // InternalFetch returns results from a single call to the underlying RPC. + // The number of results is no greater than pageSize. + // If there are no more results, nextPageToken is empty and err is nil. + InternalFetch func(pageSize int, pageToken string) (results []*monitoringpb.NotificationChannelDescriptor, nextPageToken string, err error) +} + +// PageInfo supports pagination. See the google.golang.org/api/iterator package for details. +func (it *NotificationChannelDescriptorIterator) PageInfo() *iterator.PageInfo { + return it.pageInfo +} + +// Next returns the next result. Its second return value is iterator.Done if there are no more +// results. Once Next returns Done, all subsequent calls will return Done. +func (it *NotificationChannelDescriptorIterator) Next() (*monitoringpb.NotificationChannelDescriptor, error) { + var item *monitoringpb.NotificationChannelDescriptor + if err := it.nextFunc(); err != nil { + return item, err + } + item = it.items[0] + it.items = it.items[1:] + return item, nil +} + +func (it *NotificationChannelDescriptorIterator) bufLen() int { + return len(it.items) +} + +func (it *NotificationChannelDescriptorIterator) takeBuf() interface{} { + b := it.items + it.items = nil + return b +} + +// NotificationChannelIterator manages a stream of *monitoringpb.NotificationChannel. +type NotificationChannelIterator struct { + items []*monitoringpb.NotificationChannel + pageInfo *iterator.PageInfo + nextFunc func() error + + // InternalFetch is for use by the Google Cloud Libraries only. + // It is not part of the stable interface of this package. + // + // InternalFetch returns results from a single call to the underlying RPC. + // The number of results is no greater than pageSize. + // If there are no more results, nextPageToken is empty and err is nil. + InternalFetch func(pageSize int, pageToken string) (results []*monitoringpb.NotificationChannel, nextPageToken string, err error) +} + +// PageInfo supports pagination. See the google.golang.org/api/iterator package for details. +func (it *NotificationChannelIterator) PageInfo() *iterator.PageInfo { + return it.pageInfo +} + +// Next returns the next result. Its second return value is iterator.Done if there are no more +// results. Once Next returns Done, all subsequent calls will return Done. +func (it *NotificationChannelIterator) Next() (*monitoringpb.NotificationChannel, error) { + var item *monitoringpb.NotificationChannel + if err := it.nextFunc(); err != nil { + return item, err + } + item = it.items[0] + it.items = it.items[1:] + return item, nil +} + +func (it *NotificationChannelIterator) bufLen() int { + return len(it.items) +} + +func (it *NotificationChannelIterator) takeBuf() interface{} { + b := it.items + it.items = nil + return b +} diff --git a/code.cloudfoundry.org/copilot/api/cloud_controller.pb.go b/code.cloudfoundry.org/copilot/api/cloud_controller.pb.go index 622c2dde..68f5a408 100644 --- a/code.cloudfoundry.org/copilot/api/cloud_controller.pb.go +++ b/code.cloudfoundry.org/copilot/api/cloud_controller.pb.go @@ -7,25 +7,37 @@ Package api is a generated protocol buffer package. It is generated from these files: cloud_controller.proto istio.proto + common.proto It has these top-level messages: + ListCfRoutesRequest + ListCfRoutesResponse + ListCfRouteMappingsRequest + ListCfRouteMappingsResponse + ListCapiDiegoProcessAssociationsRequest + DiegoProcessGuids + ListCapiDiegoProcessAssociationsResponse Route UpsertRouteRequest UpsertRouteResponse DeleteRouteRequest DeleteRouteResponse - CapiProcess RouteMapping MapRouteRequest MapRouteResponse UnmapRouteRequest UnmapRouteResponse - HealthRequest - HealthResponse + CapiDiegoProcessAssociation + UpsertCapiDiegoProcessAssociationRequest + UpsertCapiDiegoProcessAssociationResponse + DeleteCapiDiegoProcessAssociationRequest + DeleteCapiDiegoProcessAssociationResponse RoutesRequest RoutesResponse BackendSet Backend + HealthResponse + HealthRequest */ package api @@ -49,6 +61,111 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +type ListCfRoutesRequest struct { +} + +func (m *ListCfRoutesRequest) Reset() { *m = ListCfRoutesRequest{} } +func (m *ListCfRoutesRequest) String() string { return proto.CompactTextString(m) } +func (*ListCfRoutesRequest) ProtoMessage() {} +func (*ListCfRoutesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type ListCfRoutesResponse struct { + // key is route guid + // value is host + Routes map[string]string `protobuf:"bytes,1,rep,name=routes" json:"routes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *ListCfRoutesResponse) Reset() { *m = ListCfRoutesResponse{} } +func (m *ListCfRoutesResponse) String() string { return proto.CompactTextString(m) } +func (*ListCfRoutesResponse) ProtoMessage() {} +func (*ListCfRoutesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *ListCfRoutesResponse) GetRoutes() map[string]string { + if m != nil { + return m.Routes + } + return nil +} + +type ListCfRouteMappingsRequest struct { +} + +func (m *ListCfRouteMappingsRequest) Reset() { *m = ListCfRouteMappingsRequest{} } +func (m *ListCfRouteMappingsRequest) String() string { return proto.CompactTextString(m) } +func (*ListCfRouteMappingsRequest) ProtoMessage() {} +func (*ListCfRouteMappingsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +type ListCfRouteMappingsResponse struct { + // key is '-' + // value is a route_mapping + RouteMappings map[string]*RouteMapping `protobuf:"bytes,1,rep,name=route_mappings,json=routeMappings" json:"route_mappings,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *ListCfRouteMappingsResponse) Reset() { *m = ListCfRouteMappingsResponse{} } +func (m *ListCfRouteMappingsResponse) String() string { return proto.CompactTextString(m) } +func (*ListCfRouteMappingsResponse) ProtoMessage() {} +func (*ListCfRouteMappingsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *ListCfRouteMappingsResponse) GetRouteMappings() map[string]*RouteMapping { + if m != nil { + return m.RouteMappings + } + return nil +} + +type ListCapiDiegoProcessAssociationsRequest struct { +} + +func (m *ListCapiDiegoProcessAssociationsRequest) Reset() { + *m = ListCapiDiegoProcessAssociationsRequest{} +} +func (m *ListCapiDiegoProcessAssociationsRequest) String() string { return proto.CompactTextString(m) } +func (*ListCapiDiegoProcessAssociationsRequest) ProtoMessage() {} +func (*ListCapiDiegoProcessAssociationsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{4} +} + +// this is only for ListCapiDiegoProcessAssociationsResponse, +// since protobuf does not support list values in maps. +// it's gross. try not to use it. +type DiegoProcessGuids struct { + DiegoProcessGuids []string `protobuf:"bytes,1,rep,name=diego_process_guids,json=diegoProcessGuids" json:"diego_process_guids,omitempty"` +} + +func (m *DiegoProcessGuids) Reset() { *m = DiegoProcessGuids{} } +func (m *DiegoProcessGuids) String() string { return proto.CompactTextString(m) } +func (*DiegoProcessGuids) ProtoMessage() {} +func (*DiegoProcessGuids) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *DiegoProcessGuids) GetDiegoProcessGuids() []string { + if m != nil { + return m.DiegoProcessGuids + } + return nil +} + +type ListCapiDiegoProcessAssociationsResponse struct { + // key is capi process guid + // value is a list of diego process guids + CapiDiegoProcessAssociations map[string]*DiegoProcessGuids `protobuf:"bytes,1,rep,name=capi_diego_process_associations,json=capiDiegoProcessAssociations" json:"capi_diego_process_associations,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *ListCapiDiegoProcessAssociationsResponse) Reset() { + *m = ListCapiDiegoProcessAssociationsResponse{} +} +func (m *ListCapiDiegoProcessAssociationsResponse) String() string { return proto.CompactTextString(m) } +func (*ListCapiDiegoProcessAssociationsResponse) ProtoMessage() {} +func (*ListCapiDiegoProcessAssociationsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{6} +} + +func (m *ListCapiDiegoProcessAssociationsResponse) GetCapiDiegoProcessAssociations() map[string]*DiegoProcessGuids { + if m != nil { + return m.CapiDiegoProcessAssociations + } + return nil +} + type Route struct { Guid string `protobuf:"bytes,1,opt,name=guid" json:"guid,omitempty"` Host string `protobuf:"bytes,2,opt,name=host" json:"host,omitempty"` @@ -57,7 +174,7 @@ type Route struct { func (m *Route) Reset() { *m = Route{} } func (m *Route) String() string { return proto.CompactTextString(m) } func (*Route) ProtoMessage() {} -func (*Route) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*Route) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } func (m *Route) GetGuid() string { if m != nil { @@ -80,7 +197,7 @@ type UpsertRouteRequest struct { func (m *UpsertRouteRequest) Reset() { *m = UpsertRouteRequest{} } func (m *UpsertRouteRequest) String() string { return proto.CompactTextString(m) } func (*UpsertRouteRequest) ProtoMessage() {} -func (*UpsertRouteRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*UpsertRouteRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } func (m *UpsertRouteRequest) GetRoute() *Route { if m != nil { @@ -95,7 +212,7 @@ type UpsertRouteResponse struct { func (m *UpsertRouteResponse) Reset() { *m = UpsertRouteResponse{} } func (m *UpsertRouteResponse) String() string { return proto.CompactTextString(m) } func (*UpsertRouteResponse) ProtoMessage() {} -func (*UpsertRouteResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*UpsertRouteResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } type DeleteRouteRequest struct { Guid string `protobuf:"bytes,1,opt,name=guid" json:"guid,omitempty"` @@ -104,7 +221,7 @@ type DeleteRouteRequest struct { func (m *DeleteRouteRequest) Reset() { *m = DeleteRouteRequest{} } func (m *DeleteRouteRequest) String() string { return proto.CompactTextString(m) } func (*DeleteRouteRequest) ProtoMessage() {} -func (*DeleteRouteRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (*DeleteRouteRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } func (m *DeleteRouteRequest) GetGuid() string { if m != nil { @@ -119,47 +236,23 @@ type DeleteRouteResponse struct { func (m *DeleteRouteResponse) Reset() { *m = DeleteRouteResponse{} } func (m *DeleteRouteResponse) String() string { return proto.CompactTextString(m) } func (*DeleteRouteResponse) ProtoMessage() {} -func (*DeleteRouteResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } - -type CapiProcess struct { - Guid string `protobuf:"bytes,1,opt,name=guid" json:"guid,omitempty"` - DiegoProcessGuid string `protobuf:"bytes,2,opt,name=diego_process_guid,json=diegoProcessGuid" json:"diego_process_guid,omitempty"` -} - -func (m *CapiProcess) Reset() { *m = CapiProcess{} } -func (m *CapiProcess) String() string { return proto.CompactTextString(m) } -func (*CapiProcess) ProtoMessage() {} -func (*CapiProcess) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } - -func (m *CapiProcess) GetGuid() string { - if m != nil { - return m.Guid - } - return "" -} - -func (m *CapiProcess) GetDiegoProcessGuid() string { - if m != nil { - return m.DiegoProcessGuid - } - return "" -} +func (*DeleteRouteResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } type RouteMapping struct { - CapiProcess *CapiProcess `protobuf:"bytes,1,opt,name=capi_process,json=capiProcess" json:"capi_process,omitempty"` - RouteGuid string `protobuf:"bytes,2,opt,name=route_guid,json=routeGuid" json:"route_guid,omitempty"` + CapiProcessGuid string `protobuf:"bytes,1,opt,name=capi_process_guid,json=capiProcessGuid" json:"capi_process_guid,omitempty"` + RouteGuid string `protobuf:"bytes,2,opt,name=route_guid,json=routeGuid" json:"route_guid,omitempty"` } func (m *RouteMapping) Reset() { *m = RouteMapping{} } func (m *RouteMapping) String() string { return proto.CompactTextString(m) } func (*RouteMapping) ProtoMessage() {} -func (*RouteMapping) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (*RouteMapping) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } -func (m *RouteMapping) GetCapiProcess() *CapiProcess { +func (m *RouteMapping) GetCapiProcessGuid() string { if m != nil { - return m.CapiProcess + return m.CapiProcessGuid } - return nil + return "" } func (m *RouteMapping) GetRouteGuid() string { @@ -176,7 +269,7 @@ type MapRouteRequest struct { func (m *MapRouteRequest) Reset() { *m = MapRouteRequest{} } func (m *MapRouteRequest) String() string { return proto.CompactTextString(m) } func (*MapRouteRequest) ProtoMessage() {} -func (*MapRouteRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } +func (*MapRouteRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } func (m *MapRouteRequest) GetRouteMapping() *RouteMapping { if m != nil { @@ -191,52 +284,143 @@ type MapRouteResponse struct { func (m *MapRouteResponse) Reset() { *m = MapRouteResponse{} } func (m *MapRouteResponse) String() string { return proto.CompactTextString(m) } func (*MapRouteResponse) ProtoMessage() {} -func (*MapRouteResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (*MapRouteResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } type UnmapRouteRequest struct { - CapiProcessGuid string `protobuf:"bytes,1,opt,name=capi_process_guid,json=capiProcessGuid" json:"capi_process_guid,omitempty"` - RouteGuid string `protobuf:"bytes,2,opt,name=route_guid,json=routeGuid" json:"route_guid,omitempty"` + RouteMapping *RouteMapping `protobuf:"bytes,1,opt,name=route_mapping,json=routeMapping" json:"route_mapping,omitempty"` } func (m *UnmapRouteRequest) Reset() { *m = UnmapRouteRequest{} } func (m *UnmapRouteRequest) String() string { return proto.CompactTextString(m) } func (*UnmapRouteRequest) ProtoMessage() {} -func (*UnmapRouteRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (*UnmapRouteRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } -func (m *UnmapRouteRequest) GetCapiProcessGuid() string { +func (m *UnmapRouteRequest) GetRouteMapping() *RouteMapping { + if m != nil { + return m.RouteMapping + } + return nil +} + +type UnmapRouteResponse struct { +} + +func (m *UnmapRouteResponse) Reset() { *m = UnmapRouteResponse{} } +func (m *UnmapRouteResponse) String() string { return proto.CompactTextString(m) } +func (*UnmapRouteResponse) ProtoMessage() {} +func (*UnmapRouteResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } + +type CapiDiegoProcessAssociation struct { + CapiProcessGuid string `protobuf:"bytes,1,opt,name=capi_process_guid,json=capiProcessGuid" json:"capi_process_guid,omitempty"` + DiegoProcessGuids []string `protobuf:"bytes,2,rep,name=diego_process_guids,json=diegoProcessGuids" json:"diego_process_guids,omitempty"` +} + +func (m *CapiDiegoProcessAssociation) Reset() { *m = CapiDiegoProcessAssociation{} } +func (m *CapiDiegoProcessAssociation) String() string { return proto.CompactTextString(m) } +func (*CapiDiegoProcessAssociation) ProtoMessage() {} +func (*CapiDiegoProcessAssociation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } + +func (m *CapiDiegoProcessAssociation) GetCapiProcessGuid() string { if m != nil { return m.CapiProcessGuid } return "" } -func (m *UnmapRouteRequest) GetRouteGuid() string { +func (m *CapiDiegoProcessAssociation) GetDiegoProcessGuids() []string { if m != nil { - return m.RouteGuid + return m.DiegoProcessGuids + } + return nil +} + +type UpsertCapiDiegoProcessAssociationRequest struct { + CapiDiegoProcessAssociation *CapiDiegoProcessAssociation `protobuf:"bytes,1,opt,name=capi_diego_process_association,json=capiDiegoProcessAssociation" json:"capi_diego_process_association,omitempty"` +} + +func (m *UpsertCapiDiegoProcessAssociationRequest) Reset() { + *m = UpsertCapiDiegoProcessAssociationRequest{} +} +func (m *UpsertCapiDiegoProcessAssociationRequest) String() string { return proto.CompactTextString(m) } +func (*UpsertCapiDiegoProcessAssociationRequest) ProtoMessage() {} +func (*UpsertCapiDiegoProcessAssociationRequest) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{18} +} + +func (m *UpsertCapiDiegoProcessAssociationRequest) GetCapiDiegoProcessAssociation() *CapiDiegoProcessAssociation { + if m != nil { + return m.CapiDiegoProcessAssociation + } + return nil +} + +type UpsertCapiDiegoProcessAssociationResponse struct { +} + +func (m *UpsertCapiDiegoProcessAssociationResponse) Reset() { + *m = UpsertCapiDiegoProcessAssociationResponse{} +} +func (m *UpsertCapiDiegoProcessAssociationResponse) String() string { return proto.CompactTextString(m) } +func (*UpsertCapiDiegoProcessAssociationResponse) ProtoMessage() {} +func (*UpsertCapiDiegoProcessAssociationResponse) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{19} +} + +type DeleteCapiDiegoProcessAssociationRequest struct { + CapiProcessGuid string `protobuf:"bytes,1,opt,name=capi_process_guid,json=capiProcessGuid" json:"capi_process_guid,omitempty"` +} + +func (m *DeleteCapiDiegoProcessAssociationRequest) Reset() { + *m = DeleteCapiDiegoProcessAssociationRequest{} +} +func (m *DeleteCapiDiegoProcessAssociationRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteCapiDiegoProcessAssociationRequest) ProtoMessage() {} +func (*DeleteCapiDiegoProcessAssociationRequest) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{20} +} + +func (m *DeleteCapiDiegoProcessAssociationRequest) GetCapiProcessGuid() string { + if m != nil { + return m.CapiProcessGuid } return "" } -type UnmapRouteResponse struct { +type DeleteCapiDiegoProcessAssociationResponse struct { } -func (m *UnmapRouteResponse) Reset() { *m = UnmapRouteResponse{} } -func (m *UnmapRouteResponse) String() string { return proto.CompactTextString(m) } -func (*UnmapRouteResponse) ProtoMessage() {} -func (*UnmapRouteResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (m *DeleteCapiDiegoProcessAssociationResponse) Reset() { + *m = DeleteCapiDiegoProcessAssociationResponse{} +} +func (m *DeleteCapiDiegoProcessAssociationResponse) String() string { return proto.CompactTextString(m) } +func (*DeleteCapiDiegoProcessAssociationResponse) ProtoMessage() {} +func (*DeleteCapiDiegoProcessAssociationResponse) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{21} +} func init() { + proto.RegisterType((*ListCfRoutesRequest)(nil), "api.ListCfRoutesRequest") + proto.RegisterType((*ListCfRoutesResponse)(nil), "api.ListCfRoutesResponse") + proto.RegisterType((*ListCfRouteMappingsRequest)(nil), "api.ListCfRouteMappingsRequest") + proto.RegisterType((*ListCfRouteMappingsResponse)(nil), "api.ListCfRouteMappingsResponse") + proto.RegisterType((*ListCapiDiegoProcessAssociationsRequest)(nil), "api.ListCapiDiegoProcessAssociationsRequest") + proto.RegisterType((*DiegoProcessGuids)(nil), "api.DiegoProcessGuids") + proto.RegisterType((*ListCapiDiegoProcessAssociationsResponse)(nil), "api.ListCapiDiegoProcessAssociationsResponse") proto.RegisterType((*Route)(nil), "api.Route") proto.RegisterType((*UpsertRouteRequest)(nil), "api.UpsertRouteRequest") proto.RegisterType((*UpsertRouteResponse)(nil), "api.UpsertRouteResponse") proto.RegisterType((*DeleteRouteRequest)(nil), "api.DeleteRouteRequest") proto.RegisterType((*DeleteRouteResponse)(nil), "api.DeleteRouteResponse") - proto.RegisterType((*CapiProcess)(nil), "api.CapiProcess") proto.RegisterType((*RouteMapping)(nil), "api.RouteMapping") proto.RegisterType((*MapRouteRequest)(nil), "api.MapRouteRequest") proto.RegisterType((*MapRouteResponse)(nil), "api.MapRouteResponse") proto.RegisterType((*UnmapRouteRequest)(nil), "api.UnmapRouteRequest") proto.RegisterType((*UnmapRouteResponse)(nil), "api.UnmapRouteResponse") + proto.RegisterType((*CapiDiegoProcessAssociation)(nil), "api.CapiDiegoProcessAssociation") + proto.RegisterType((*UpsertCapiDiegoProcessAssociationRequest)(nil), "api.UpsertCapiDiegoProcessAssociationRequest") + proto.RegisterType((*UpsertCapiDiegoProcessAssociationResponse)(nil), "api.UpsertCapiDiegoProcessAssociationResponse") + proto.RegisterType((*DeleteCapiDiegoProcessAssociationRequest)(nil), "api.DeleteCapiDiegoProcessAssociationRequest") + proto.RegisterType((*DeleteCapiDiegoProcessAssociationResponse)(nil), "api.DeleteCapiDiegoProcessAssociationResponse") } // Reference imports to suppress errors if they are not otherwise used. @@ -250,10 +434,16 @@ const _ = grpc.SupportPackageIsVersion4 // Client API for CloudControllerCopilot service type CloudControllerCopilotClient interface { + ListCfRoutes(ctx context.Context, in *ListCfRoutesRequest, opts ...grpc.CallOption) (*ListCfRoutesResponse, error) + ListCfRouteMappings(ctx context.Context, in *ListCfRouteMappingsRequest, opts ...grpc.CallOption) (*ListCfRouteMappingsResponse, error) + ListCapiDiegoProcessAssociations(ctx context.Context, in *ListCapiDiegoProcessAssociationsRequest, opts ...grpc.CallOption) (*ListCapiDiegoProcessAssociationsResponse, error) UpsertRoute(ctx context.Context, in *UpsertRouteRequest, opts ...grpc.CallOption) (*UpsertRouteResponse, error) DeleteRoute(ctx context.Context, in *DeleteRouteRequest, opts ...grpc.CallOption) (*DeleteRouteResponse, error) MapRoute(ctx context.Context, in *MapRouteRequest, opts ...grpc.CallOption) (*MapRouteResponse, error) UnmapRoute(ctx context.Context, in *UnmapRouteRequest, opts ...grpc.CallOption) (*UnmapRouteResponse, error) + UpsertCapiDiegoProcessAssociation(ctx context.Context, in *UpsertCapiDiegoProcessAssociationRequest, opts ...grpc.CallOption) (*UpsertCapiDiegoProcessAssociationResponse, error) + DeleteCapiDiegoProcessAssociation(ctx context.Context, in *DeleteCapiDiegoProcessAssociationRequest, opts ...grpc.CallOption) (*DeleteCapiDiegoProcessAssociationResponse, error) + Health(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error) } type cloudControllerCopilotClient struct { @@ -264,6 +454,33 @@ func NewCloudControllerCopilotClient(cc *grpc.ClientConn) CloudControllerCopilot return &cloudControllerCopilotClient{cc} } +func (c *cloudControllerCopilotClient) ListCfRoutes(ctx context.Context, in *ListCfRoutesRequest, opts ...grpc.CallOption) (*ListCfRoutesResponse, error) { + out := new(ListCfRoutesResponse) + err := grpc.Invoke(ctx, "/api.CloudControllerCopilot/ListCfRoutes", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *cloudControllerCopilotClient) ListCfRouteMappings(ctx context.Context, in *ListCfRouteMappingsRequest, opts ...grpc.CallOption) (*ListCfRouteMappingsResponse, error) { + out := new(ListCfRouteMappingsResponse) + err := grpc.Invoke(ctx, "/api.CloudControllerCopilot/ListCfRouteMappings", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *cloudControllerCopilotClient) ListCapiDiegoProcessAssociations(ctx context.Context, in *ListCapiDiegoProcessAssociationsRequest, opts ...grpc.CallOption) (*ListCapiDiegoProcessAssociationsResponse, error) { + out := new(ListCapiDiegoProcessAssociationsResponse) + err := grpc.Invoke(ctx, "/api.CloudControllerCopilot/ListCapiDiegoProcessAssociations", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *cloudControllerCopilotClient) UpsertRoute(ctx context.Context, in *UpsertRouteRequest, opts ...grpc.CallOption) (*UpsertRouteResponse, error) { out := new(UpsertRouteResponse) err := grpc.Invoke(ctx, "/api.CloudControllerCopilot/UpsertRoute", in, out, c.cc, opts...) @@ -300,19 +517,106 @@ func (c *cloudControllerCopilotClient) UnmapRoute(ctx context.Context, in *Unmap return out, nil } +func (c *cloudControllerCopilotClient) UpsertCapiDiegoProcessAssociation(ctx context.Context, in *UpsertCapiDiegoProcessAssociationRequest, opts ...grpc.CallOption) (*UpsertCapiDiegoProcessAssociationResponse, error) { + out := new(UpsertCapiDiegoProcessAssociationResponse) + err := grpc.Invoke(ctx, "/api.CloudControllerCopilot/UpsertCapiDiegoProcessAssociation", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *cloudControllerCopilotClient) DeleteCapiDiegoProcessAssociation(ctx context.Context, in *DeleteCapiDiegoProcessAssociationRequest, opts ...grpc.CallOption) (*DeleteCapiDiegoProcessAssociationResponse, error) { + out := new(DeleteCapiDiegoProcessAssociationResponse) + err := grpc.Invoke(ctx, "/api.CloudControllerCopilot/DeleteCapiDiegoProcessAssociation", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *cloudControllerCopilotClient) Health(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error) { + out := new(HealthResponse) + err := grpc.Invoke(ctx, "/api.CloudControllerCopilot/Health", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for CloudControllerCopilot service type CloudControllerCopilotServer interface { + ListCfRoutes(context.Context, *ListCfRoutesRequest) (*ListCfRoutesResponse, error) + ListCfRouteMappings(context.Context, *ListCfRouteMappingsRequest) (*ListCfRouteMappingsResponse, error) + ListCapiDiegoProcessAssociations(context.Context, *ListCapiDiegoProcessAssociationsRequest) (*ListCapiDiegoProcessAssociationsResponse, error) UpsertRoute(context.Context, *UpsertRouteRequest) (*UpsertRouteResponse, error) DeleteRoute(context.Context, *DeleteRouteRequest) (*DeleteRouteResponse, error) MapRoute(context.Context, *MapRouteRequest) (*MapRouteResponse, error) UnmapRoute(context.Context, *UnmapRouteRequest) (*UnmapRouteResponse, error) + UpsertCapiDiegoProcessAssociation(context.Context, *UpsertCapiDiegoProcessAssociationRequest) (*UpsertCapiDiegoProcessAssociationResponse, error) + DeleteCapiDiegoProcessAssociation(context.Context, *DeleteCapiDiegoProcessAssociationRequest) (*DeleteCapiDiegoProcessAssociationResponse, error) + Health(context.Context, *HealthRequest) (*HealthResponse, error) } func RegisterCloudControllerCopilotServer(s *grpc.Server, srv CloudControllerCopilotServer) { s.RegisterService(&_CloudControllerCopilot_serviceDesc, srv) } +func _CloudControllerCopilot_ListCfRoutes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListCfRoutesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CloudControllerCopilotServer).ListCfRoutes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.CloudControllerCopilot/ListCfRoutes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CloudControllerCopilotServer).ListCfRoutes(ctx, req.(*ListCfRoutesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _CloudControllerCopilot_ListCfRouteMappings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListCfRouteMappingsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CloudControllerCopilotServer).ListCfRouteMappings(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.CloudControllerCopilot/ListCfRouteMappings", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CloudControllerCopilotServer).ListCfRouteMappings(ctx, req.(*ListCfRouteMappingsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _CloudControllerCopilot_ListCapiDiegoProcessAssociations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListCapiDiegoProcessAssociationsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CloudControllerCopilotServer).ListCapiDiegoProcessAssociations(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.CloudControllerCopilot/ListCapiDiegoProcessAssociations", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CloudControllerCopilotServer).ListCapiDiegoProcessAssociations(ctx, req.(*ListCapiDiegoProcessAssociationsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _CloudControllerCopilot_UpsertRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(UpsertRouteRequest) if err := dec(in); err != nil { @@ -385,10 +689,76 @@ func _CloudControllerCopilot_UnmapRoute_Handler(srv interface{}, ctx context.Con return interceptor(ctx, in, info, handler) } +func _CloudControllerCopilot_UpsertCapiDiegoProcessAssociation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpsertCapiDiegoProcessAssociationRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CloudControllerCopilotServer).UpsertCapiDiegoProcessAssociation(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.CloudControllerCopilot/UpsertCapiDiegoProcessAssociation", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CloudControllerCopilotServer).UpsertCapiDiegoProcessAssociation(ctx, req.(*UpsertCapiDiegoProcessAssociationRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _CloudControllerCopilot_DeleteCapiDiegoProcessAssociation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteCapiDiegoProcessAssociationRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CloudControllerCopilotServer).DeleteCapiDiegoProcessAssociation(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.CloudControllerCopilot/DeleteCapiDiegoProcessAssociation", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CloudControllerCopilotServer).DeleteCapiDiegoProcessAssociation(ctx, req.(*DeleteCapiDiegoProcessAssociationRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _CloudControllerCopilot_Health_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HealthRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CloudControllerCopilotServer).Health(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.CloudControllerCopilot/Health", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CloudControllerCopilotServer).Health(ctx, req.(*HealthRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _CloudControllerCopilot_serviceDesc = grpc.ServiceDesc{ ServiceName: "api.CloudControllerCopilot", HandlerType: (*CloudControllerCopilotServer)(nil), Methods: []grpc.MethodDesc{ + { + MethodName: "ListCfRoutes", + Handler: _CloudControllerCopilot_ListCfRoutes_Handler, + }, + { + MethodName: "ListCfRouteMappings", + Handler: _CloudControllerCopilot_ListCfRouteMappings_Handler, + }, + { + MethodName: "ListCapiDiegoProcessAssociations", + Handler: _CloudControllerCopilot_ListCapiDiegoProcessAssociations_Handler, + }, { MethodName: "UpsertRoute", Handler: _CloudControllerCopilot_UpsertRoute_Handler, @@ -405,6 +775,18 @@ var _CloudControllerCopilot_serviceDesc = grpc.ServiceDesc{ MethodName: "UnmapRoute", Handler: _CloudControllerCopilot_UnmapRoute_Handler, }, + { + MethodName: "UpsertCapiDiegoProcessAssociation", + Handler: _CloudControllerCopilot_UpsertCapiDiegoProcessAssociation_Handler, + }, + { + MethodName: "DeleteCapiDiegoProcessAssociation", + Handler: _CloudControllerCopilot_DeleteCapiDiegoProcessAssociation_Handler, + }, + { + MethodName: "Health", + Handler: _CloudControllerCopilot_Health_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "cloud_controller.proto", @@ -413,30 +795,54 @@ var _CloudControllerCopilot_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("cloud_controller.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 391 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x53, 0x5b, 0x6b, 0xea, 0x40, - 0x10, 0x56, 0xcf, 0xf1, 0x70, 0x9c, 0x58, 0xd4, 0xa9, 0x37, 0x84, 0x82, 0xe4, 0x49, 0x4a, 0xb1, - 0xa0, 0x20, 0xf4, 0xa9, 0xd0, 0x14, 0x4a, 0x1f, 0xa4, 0x25, 0xe0, 0x6b, 0x43, 0x8c, 0x8b, 0x5d, - 0x88, 0xd9, 0x6d, 0xb2, 0xf9, 0x37, 0xfd, 0xb1, 0x65, 0x2f, 0xea, 0x26, 0x11, 0xfa, 0x96, 0x9d, - 0x9d, 0xef, 0x36, 0x3b, 0x81, 0x61, 0x14, 0xb3, 0x7c, 0x17, 0x44, 0x2c, 0x11, 0x29, 0x8b, 0x63, - 0x92, 0xce, 0x79, 0xca, 0x04, 0xc3, 0x3f, 0x21, 0xa7, 0xee, 0x3d, 0x34, 0x7d, 0x96, 0x0b, 0x82, - 0x08, 0x7f, 0xf7, 0x39, 0xdd, 0x8d, 0xeb, 0xd3, 0xfa, 0xac, 0xe5, 0xab, 0x6f, 0x59, 0xfb, 0x64, - 0x99, 0x18, 0x37, 0x74, 0x4d, 0x7e, 0xbb, 0x2b, 0xc0, 0x0d, 0xcf, 0x48, 0x2a, 0x14, 0xcc, 0x27, - 0x5f, 0x39, 0xc9, 0x04, 0x4e, 0xa1, 0x99, 0xca, 0xb3, 0x82, 0x3b, 0x0b, 0x98, 0x87, 0x9c, 0xce, - 0x75, 0x87, 0xbe, 0x70, 0x07, 0x70, 0x5d, 0xc0, 0x65, 0x9c, 0x25, 0x19, 0x71, 0x67, 0x80, 0xcf, - 0x24, 0x26, 0x82, 0x14, 0xe8, 0x2e, 0x98, 0x91, 0x04, 0x85, 0x4e, 0x43, 0xf0, 0x06, 0x8e, 0x17, - 0x72, 0xfa, 0x9e, 0xb2, 0x88, 0x64, 0xd9, 0xc5, 0x18, 0x77, 0x80, 0x3b, 0x4a, 0xf6, 0x2c, 0xe0, - 0xba, 0x29, 0x50, 0x1d, 0x3a, 0x54, 0x57, 0xdd, 0x18, 0xf4, 0x8b, 0xd4, 0xd9, 0x42, 0x5b, 0x29, - 0xac, 0x43, 0xce, 0x69, 0xb2, 0xc7, 0x25, 0xb4, 0xa3, 0x90, 0xd3, 0x23, 0xd8, 0x24, 0xec, 0xaa, - 0x84, 0x96, 0xb2, 0xef, 0x44, 0x96, 0x8d, 0x1b, 0x00, 0x15, 0xdb, 0x96, 0x6a, 0xa9, 0x8a, 0xd2, - 0x78, 0x85, 0xce, 0x3a, 0xe4, 0x85, 0xc8, 0x2b, 0xb8, 0xd2, 0x88, 0x83, 0xd6, 0x35, 0x3a, 0xbd, - 0xf3, 0x24, 0x8d, 0x21, 0xbf, 0x9d, 0x5a, 0x27, 0x17, 0xa1, 0x7b, 0xa6, 0x32, 0x33, 0xf9, 0x80, - 0xde, 0x26, 0x39, 0x94, 0x04, 0x6e, 0xa1, 0x67, 0xe7, 0x08, 0xac, 0x31, 0x75, 0x2c, 0xeb, 0xd2, - 0xdf, 0x6f, 0xf6, 0xfb, 0x80, 0x36, 0xbf, 0x56, 0x5d, 0x7c, 0x37, 0x60, 0xe8, 0xc9, 0x55, 0xf3, - 0x4e, 0x9b, 0xe6, 0x31, 0x4e, 0x63, 0x26, 0xf0, 0x09, 0x1c, 0xeb, 0xf1, 0x71, 0xa4, 0x42, 0x55, - 0xd7, 0x68, 0x32, 0xae, 0x5e, 0x98, 0x48, 0x35, 0xc9, 0x61, 0xbd, 0xbf, 0xe1, 0xa8, 0xee, 0x8e, - 0xe1, 0xb8, 0xb4, 0x2a, 0x35, 0x7c, 0x80, 0xff, 0xc7, 0x61, 0x61, 0x5f, 0xf5, 0x95, 0x9e, 0x61, - 0x32, 0x28, 0x55, 0x4f, 0xd0, 0x47, 0x80, 0x73, 0x66, 0x1c, 0x6a, 0xa3, 0xe5, 0x21, 0x4f, 0x46, - 0x95, 0xfa, 0x91, 0x60, 0xfb, 0x4f, 0xfd, 0x75, 0xcb, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x14, - 0x16, 0x0e, 0x5d, 0x8f, 0x03, 0x00, 0x00, + // 772 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x5f, 0x4f, 0xd3, 0x50, + 0x14, 0x5f, 0x87, 0xa0, 0x9c, 0x0d, 0x61, 0x87, 0x01, 0xb3, 0xa0, 0x8c, 0x26, 0x86, 0xa1, 0x50, + 0x93, 0x91, 0x10, 0x31, 0x31, 0x46, 0x07, 0x51, 0xa3, 0x44, 0x33, 0x83, 0x89, 0xbc, 0x2c, 0xb5, + 0xbb, 0x8e, 0xc6, 0xae, 0xb7, 0xb6, 0x9d, 0x09, 0x8f, 0x26, 0xc6, 0x67, 0x7d, 0xf1, 0x53, 0xf8, + 0x59, 0xfc, 0x4c, 0xa6, 0xf7, 0xde, 0x6d, 0xb7, 0x6b, 0xd7, 0x76, 0x89, 0x6f, 0xeb, 0xef, 0x9e, + 0xf3, 0xbb, 0xbf, 0x73, 0xee, 0xf9, 0x33, 0x58, 0x37, 0x6d, 0x3a, 0xe8, 0x76, 0x4c, 0xea, 0x04, + 0x1e, 0xb5, 0x6d, 0xe2, 0xe9, 0xae, 0x47, 0x03, 0x8a, 0x73, 0x86, 0x6b, 0xa9, 0x65, 0x93, 0xf6, + 0xfb, 0xd4, 0xe1, 0x90, 0xb6, 0x06, 0xab, 0xaf, 0x2d, 0x3f, 0x68, 0x7d, 0x6a, 0xd3, 0x41, 0x40, + 0xfc, 0x36, 0xf9, 0x32, 0x20, 0x7e, 0xa0, 0xfd, 0x54, 0xa0, 0x1a, 0xc5, 0x7d, 0x97, 0x3a, 0x3e, + 0xc1, 0xc7, 0xb0, 0xe0, 0x31, 0xa4, 0xa6, 0xd4, 0xe7, 0x1a, 0xa5, 0xe6, 0x5d, 0xdd, 0x70, 0x2d, + 0x3d, 0xc9, 0x54, 0xe7, 0x9f, 0xa7, 0x4e, 0xe0, 0x5d, 0xb5, 0x85, 0x93, 0x7a, 0x0c, 0x25, 0x09, + 0xc6, 0x15, 0x98, 0xfb, 0x4c, 0xae, 0x6a, 0x4a, 0x5d, 0x69, 0x2c, 0xb6, 0xc3, 0x9f, 0x58, 0x85, + 0xf9, 0xaf, 0x86, 0x3d, 0x20, 0xb5, 0x22, 0xc3, 0xf8, 0xc7, 0xa3, 0xe2, 0x43, 0x45, 0xdb, 0x02, + 0x55, 0xba, 0xe6, 0xcc, 0x70, 0x5d, 0xcb, 0xe9, 0x8d, 0x04, 0xff, 0x55, 0x60, 0x33, 0xf1, 0x58, + 0xe8, 0xbe, 0x80, 0x9b, 0x4c, 0x42, 0xa7, 0x2f, 0x4e, 0x84, 0xfe, 0xc3, 0x49, 0xfd, 0x93, 0x9e, + 0x7a, 0x04, 0xe5, 0xd1, 0x2c, 0x79, 0x32, 0xa6, 0xbe, 0x03, 0x8c, 0x1b, 0x25, 0xc4, 0xb6, 0x2b, + 0xc7, 0x56, 0x6a, 0x56, 0xd8, 0xd5, 0xb2, 0xa7, 0x1c, 0xee, 0x1e, 0xec, 0x32, 0x55, 0x86, 0x6b, + 0x9d, 0x58, 0xa4, 0x47, 0xdf, 0x7a, 0xd4, 0x24, 0xbe, 0xff, 0xd4, 0xf7, 0xa9, 0x69, 0x19, 0x81, + 0x45, 0x9d, 0x51, 0xec, 0x2d, 0xa8, 0xc8, 0x26, 0xcf, 0x07, 0x56, 0xd7, 0x47, 0x1d, 0x56, 0xbb, + 0x21, 0xd8, 0x71, 0x39, 0xda, 0xe9, 0x85, 0x30, 0x8b, 0x7a, 0xb1, 0x5d, 0xe9, 0x4e, 0xda, 0x6b, + 0x7f, 0x8a, 0xd0, 0xc8, 0xbe, 0x50, 0x64, 0xf3, 0xb7, 0x02, 0xdb, 0xa6, 0xe1, 0x5a, 0x9d, 0xe8, + 0x15, 0x86, 0x64, 0x2b, 0xf2, 0xfb, 0x66, 0x9c, 0xdf, 0x1c, 0xc4, 0x7a, 0x9a, 0x11, 0xcf, 0xfd, + 0x96, 0x99, 0x62, 0xa2, 0xf6, 0x60, 0x27, 0x93, 0x22, 0xe1, 0x65, 0xf6, 0xa3, 0x2f, 0xb3, 0xce, + 0x44, 0xc7, 0x72, 0x2a, 0x3f, 0xcf, 0x03, 0x98, 0x67, 0x2f, 0x87, 0x08, 0xd7, 0xc2, 0xcc, 0x0a, + 0x36, 0xf6, 0x3b, 0xc4, 0x2e, 0xa9, 0x1f, 0x88, 0x1a, 0x66, 0xbf, 0xb5, 0x23, 0xc0, 0x73, 0xd7, + 0x27, 0x5e, 0xc0, 0xdc, 0xc4, 0xd3, 0x61, 0x1d, 0xe6, 0x59, 0x2d, 0x31, 0xf7, 0x52, 0x13, 0xc6, + 0x25, 0xd1, 0xe6, 0x07, 0x61, 0x83, 0x46, 0xfc, 0x78, 0xa2, 0xb4, 0x06, 0xe0, 0x09, 0xb1, 0x49, + 0x40, 0x22, 0x74, 0x09, 0x62, 0x42, 0x82, 0x88, 0xa5, 0x20, 0xf8, 0x00, 0x65, 0xb9, 0xf4, 0xf0, + 0x1e, 0x54, 0xd8, 0x8b, 0xca, 0xe5, 0x22, 0x78, 0x96, 0xc3, 0x03, 0x29, 0x11, 0x78, 0x1b, 0x80, + 0x37, 0x13, 0x33, 0xe2, 0x51, 0x2e, 0x32, 0x24, 0x3c, 0xd6, 0x5e, 0xc2, 0xf2, 0x99, 0xe1, 0x46, + 0x84, 0x1d, 0xc1, 0x52, 0xa4, 0xfd, 0x44, 0xbc, 0x09, 0x2d, 0x50, 0x96, 0x7b, 0x4b, 0x43, 0x58, + 0x19, 0x53, 0x09, 0xe5, 0xaf, 0xa0, 0x72, 0xee, 0xf4, 0xff, 0xd3, 0x05, 0x55, 0x40, 0x99, 0x4c, + 0x5c, 0x71, 0x05, 0x9b, 0x29, 0x65, 0x34, 0x53, 0xae, 0xa6, 0xf4, 0x61, 0x71, 0x5a, 0x1f, 0xfe, + 0x52, 0xa0, 0xc1, 0x1f, 0x3c, 0x45, 0xc1, 0x30, 0x6a, 0x02, 0x77, 0xd2, 0xdb, 0x50, 0xa4, 0xa1, + 0xce, 0xd2, 0x90, 0x46, 0xb8, 0x99, 0xd2, 0x56, 0xda, 0x7d, 0xd8, 0xcb, 0x21, 0x49, 0xe4, 0xee, + 0x3d, 0x34, 0x78, 0xbd, 0xe5, 0xd0, 0x3f, 0x43, 0x22, 0x43, 0x11, 0x39, 0x78, 0xb9, 0x88, 0xe6, + 0x8f, 0xeb, 0xb0, 0xde, 0x0a, 0x97, 0x60, 0x6b, 0xb4, 0x03, 0x5b, 0xd4, 0xb5, 0x6c, 0x1a, 0xe0, + 0x29, 0x94, 0xe5, 0x75, 0x85, 0xb5, 0x84, 0x0d, 0xc6, 0xd4, 0xa9, 0xb7, 0xa6, 0xee, 0x36, 0xad, + 0x80, 0x17, 0x91, 0xc5, 0x39, 0x1c, 0xfd, 0xb8, 0x3d, 0x7d, 0x9f, 0x70, 0xd2, 0x7a, 0xd6, 0xc2, + 0xd1, 0x0a, 0xf8, 0x4d, 0x81, 0x7a, 0xd6, 0xc8, 0xc4, 0xfd, 0x9c, 0x93, 0x95, 0x5f, 0x7b, 0x30, + 0xd3, 0x1c, 0xd6, 0x0a, 0xf8, 0x0c, 0x4a, 0xd2, 0xdc, 0xc1, 0x0d, 0xe6, 0x1f, 0x9f, 0x60, 0x6a, + 0x2d, 0x7e, 0x20, 0x73, 0x48, 0xa3, 0x47, 0x70, 0xc4, 0xc7, 0x96, 0xe0, 0x48, 0x9a, 0x52, 0x05, + 0x3c, 0x86, 0x1b, 0xc3, 0x09, 0x80, 0x55, 0x66, 0x37, 0x31, 0x5b, 0xd4, 0xb5, 0x09, 0x74, 0xe4, + 0xfa, 0x04, 0x60, 0xdc, 0xdb, 0xc8, 0x87, 0x7a, 0x6c, 0x72, 0xa8, 0x1b, 0x31, 0x7c, 0x44, 0xf0, + 0x5d, 0x81, 0x9d, 0xcc, 0xc2, 0xc7, 0x03, 0x29, 0x03, 0xd9, 0x35, 0xaf, 0xea, 0x79, 0xcd, 0x23, + 0x32, 0x32, 0x4b, 0x5f, 0xc8, 0xc8, 0xdb, 0x7a, 0x42, 0x46, 0xee, 0x8e, 0xd2, 0x0a, 0x78, 0x08, + 0x0b, 0x2f, 0x88, 0x61, 0x07, 0x97, 0x88, 0xcc, 0x97, 0x7f, 0x0c, 0xf9, 0x56, 0x23, 0xd8, 0xd0, + 0xe9, 0xe3, 0x02, 0xfb, 0x9b, 0x79, 0xf8, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x0f, 0x60, 0x95, + 0x93, 0x0a, 0x00, 0x00, } diff --git a/code.cloudfoundry.org/copilot/api/common.pb.go b/code.cloudfoundry.org/copilot/api/common.pb.go new file mode 100644 index 00000000..ab039890 --- /dev/null +++ b/code.cloudfoundry.org/copilot/api/common.pb.go @@ -0,0 +1,54 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: common.proto + +package api + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type HealthResponse struct { + Healthy bool `protobuf:"varint,1,opt,name=healthy" json:"healthy,omitempty"` +} + +func (m *HealthResponse) Reset() { *m = HealthResponse{} } +func (m *HealthResponse) String() string { return proto.CompactTextString(m) } +func (*HealthResponse) ProtoMessage() {} +func (*HealthResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } + +func (m *HealthResponse) GetHealthy() bool { + if m != nil { + return m.Healthy + } + return false +} + +type HealthRequest struct { +} + +func (m *HealthRequest) Reset() { *m = HealthRequest{} } +func (m *HealthRequest) String() string { return proto.CompactTextString(m) } +func (*HealthRequest) ProtoMessage() {} +func (*HealthRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{1} } + +func init() { + proto.RegisterType((*HealthResponse)(nil), "api.HealthResponse") + proto.RegisterType((*HealthRequest)(nil), "api.HealthRequest") +} + +func init() { proto.RegisterFile("common.proto", fileDescriptor2) } + +var fileDescriptor2 = []byte{ + // 94 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x49, 0xce, 0xcf, 0xcd, + 0xcd, 0xcf, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x4e, 0x2c, 0xc8, 0x54, 0xd2, 0xe2, + 0xe2, 0xf3, 0x48, 0x4d, 0xcc, 0x29, 0xc9, 0x08, 0x4a, 0x2d, 0x2e, 0xc8, 0xcf, 0x2b, 0x4e, 0x15, + 0x92, 0xe0, 0x62, 0xcf, 0x00, 0x8b, 0x54, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x04, 0xc1, 0xb8, + 0x4a, 0xfc, 0x5c, 0xbc, 0x30, 0xb5, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x49, 0x6c, 0x60, 0x83, 0x8c, + 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x55, 0x23, 0x59, 0x44, 0x58, 0x00, 0x00, 0x00, +} diff --git a/code.cloudfoundry.org/copilot/api/istio.pb.go b/code.cloudfoundry.org/copilot/api/istio.pb.go index 422ca647..cdf0bb93 100644 --- a/code.cloudfoundry.org/copilot/api/istio.pb.go +++ b/code.cloudfoundry.org/copilot/api/istio.pb.go @@ -17,37 +17,13 @@ var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf -type HealthRequest struct { -} - -func (m *HealthRequest) Reset() { *m = HealthRequest{} } -func (m *HealthRequest) String() string { return proto.CompactTextString(m) } -func (*HealthRequest) ProtoMessage() {} -func (*HealthRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } - -type HealthResponse struct { - Healthy bool `protobuf:"varint,1,opt,name=healthy" json:"healthy,omitempty"` -} - -func (m *HealthResponse) Reset() { *m = HealthResponse{} } -func (m *HealthResponse) String() string { return proto.CompactTextString(m) } -func (*HealthResponse) ProtoMessage() {} -func (*HealthResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } - -func (m *HealthResponse) GetHealthy() bool { - if m != nil { - return m.Healthy - } - return false -} - type RoutesRequest struct { } func (m *RoutesRequest) Reset() { *m = RoutesRequest{} } func (m *RoutesRequest) String() string { return proto.CompactTextString(m) } func (*RoutesRequest) ProtoMessage() {} -func (*RoutesRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} } +func (*RoutesRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } type RoutesResponse struct { // key is hostname @@ -57,7 +33,7 @@ type RoutesResponse struct { func (m *RoutesResponse) Reset() { *m = RoutesResponse{} } func (m *RoutesResponse) String() string { return proto.CompactTextString(m) } func (*RoutesResponse) ProtoMessage() {} -func (*RoutesResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } +func (*RoutesResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } func (m *RoutesResponse) GetBackends() map[string]*BackendSet { if m != nil { @@ -73,7 +49,7 @@ type BackendSet struct { func (m *BackendSet) Reset() { *m = BackendSet{} } func (m *BackendSet) String() string { return proto.CompactTextString(m) } func (*BackendSet) ProtoMessage() {} -func (*BackendSet) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} } +func (*BackendSet) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} } func (m *BackendSet) GetBackends() []*Backend { if m != nil { @@ -90,7 +66,7 @@ type Backend struct { func (m *Backend) Reset() { *m = Backend{} } func (m *Backend) String() string { return proto.CompactTextString(m) } func (*Backend) ProtoMessage() {} -func (*Backend) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} } +func (*Backend) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } func (m *Backend) GetAddress() string { if m != nil { @@ -107,8 +83,6 @@ func (m *Backend) GetPort() uint32 { } func init() { - proto.RegisterType((*HealthRequest)(nil), "api.HealthRequest") - proto.RegisterType((*HealthResponse)(nil), "api.HealthResponse") proto.RegisterType((*RoutesRequest)(nil), "api.RoutesRequest") proto.RegisterType((*RoutesResponse)(nil), "api.RoutesResponse") proto.RegisterType((*BackendSet)(nil), "api.BackendSet") @@ -223,23 +197,23 @@ var _IstioCopilot_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("istio.proto", fileDescriptor1) } var fileDescriptor1 = []byte{ - // 286 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x91, 0x41, 0x4b, 0xc3, 0x30, - 0x14, 0xc7, 0x97, 0x55, 0xb7, 0xf9, 0xba, 0x6e, 0x12, 0x2f, 0x65, 0xa7, 0x1a, 0x10, 0x8a, 0x87, - 0x1e, 0x3a, 0x50, 0x11, 0xbc, 0x28, 0x82, 0x82, 0xa7, 0xf8, 0x09, 0x32, 0xfb, 0x60, 0x65, 0xa5, - 0x89, 0x4d, 0x2a, 0xee, 0xc3, 0xf8, 0x5d, 0xa5, 0x69, 0xea, 0x0c, 0xbb, 0x25, 0xff, 0xf7, 0x7e, - 0xed, 0x9f, 0x5f, 0x20, 0x2c, 0xb5, 0x29, 0x65, 0xa6, 0x1a, 0x69, 0x24, 0x0d, 0x84, 0x2a, 0xd9, - 0x12, 0xa2, 0x17, 0x14, 0x95, 0xd9, 0x72, 0xfc, 0x6c, 0x51, 0x1b, 0x76, 0x0d, 0x8b, 0x21, 0xd0, - 0x4a, 0xd6, 0x1a, 0x69, 0x0c, 0xd3, 0xad, 0x4d, 0xf6, 0x31, 0x49, 0x48, 0x3a, 0xe3, 0xc3, 0xb5, - 0x83, 0xb9, 0x6c, 0x0d, 0xea, 0x01, 0xfe, 0x21, 0xb0, 0x18, 0x12, 0x47, 0x3f, 0xc0, 0x6c, 0x23, - 0x3e, 0x76, 0x58, 0x17, 0x3a, 0x26, 0x49, 0x90, 0x86, 0xf9, 0x65, 0x26, 0x54, 0x99, 0xf9, 0x6b, - 0xd9, 0xa3, 0xdb, 0x79, 0xae, 0x4d, 0xb3, 0xe7, 0x7f, 0xc8, 0xea, 0x0d, 0x22, 0x6f, 0x44, 0xcf, - 0x21, 0xd8, 0x61, 0xdf, 0xe4, 0x8c, 0x77, 0x47, 0x7a, 0x05, 0xa7, 0x5f, 0xa2, 0x6a, 0x31, 0x1e, - 0x27, 0x24, 0x0d, 0xf3, 0xa5, 0xfd, 0xbc, 0x83, 0xde, 0xd1, 0xf0, 0x7e, 0x7a, 0x3f, 0xbe, 0x23, - 0xec, 0x06, 0xe0, 0x30, 0xa0, 0xe9, 0x51, 0xb5, 0xf9, 0x7f, 0xf6, 0xd0, 0x82, 0xdd, 0xc2, 0xd4, - 0x85, 0x9d, 0x0d, 0x51, 0x14, 0x0d, 0x6a, 0xed, 0x3a, 0x0c, 0x57, 0x4a, 0xe1, 0x44, 0xc9, 0xc6, - 0xd8, 0x1a, 0x11, 0xb7, 0xe7, 0xfc, 0x1b, 0xe6, 0xaf, 0x9d, 0xf2, 0x27, 0xa9, 0xca, 0x4a, 0x1a, - 0xba, 0x86, 0x49, 0x6f, 0x97, 0x52, 0xfb, 0x2b, 0xcf, 0xfd, 0xea, 0xc2, 0xcb, 0x7a, 0x33, 0x6c, - 0xd4, 0x41, 0xbd, 0x2d, 0x07, 0x79, 0xce, 0x1d, 0xe4, 0xeb, 0x64, 0xa3, 0xcd, 0xc4, 0x3e, 0xf2, - 0xfa, 0x37, 0x00, 0x00, 0xff, 0xff, 0xb5, 0x72, 0xb6, 0x91, 0xf3, 0x01, 0x00, 0x00, + // 276 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x91, 0x41, 0x4b, 0xc3, 0x40, + 0x10, 0x85, 0xbb, 0x8d, 0xb6, 0x3a, 0x49, 0xac, 0x8c, 0x97, 0x90, 0x53, 0x5c, 0x10, 0x72, 0xca, + 0x21, 0x05, 0x15, 0xc1, 0x8b, 0x22, 0x28, 0x78, 0x5a, 0x7f, 0xc1, 0xb6, 0x59, 0x30, 0x34, 0xcd, + 0xac, 0xd9, 0x8d, 0xd8, 0x1f, 0xe3, 0x7f, 0x95, 0x24, 0x5b, 0x6b, 0xf0, 0x36, 0xf3, 0xde, 0xbc, + 0xe4, 0xf1, 0x2d, 0xf8, 0xa5, 0xb1, 0x25, 0x65, 0xba, 0x21, 0x4b, 0xe8, 0x49, 0x5d, 0xc6, 0xc1, + 0x9a, 0xb6, 0x5b, 0xaa, 0x07, 0x89, 0x2f, 0x20, 0x14, 0xd4, 0x5a, 0x65, 0x84, 0xfa, 0x68, 0x95, + 0xb1, 0xfc, 0x9b, 0xc1, 0xd9, 0x5e, 0x31, 0x9a, 0x6a, 0xa3, 0xf0, 0x1e, 0x4e, 0x56, 0x72, 0xbd, + 0x51, 0x75, 0x61, 0x22, 0x96, 0x78, 0xa9, 0x9f, 0x5f, 0x66, 0x52, 0x97, 0xd9, 0xf8, 0x2c, 0x7b, + 0x70, 0x37, 0x4f, 0xb5, 0x6d, 0x76, 0xe2, 0x37, 0x12, 0xbf, 0x42, 0x38, 0xb2, 0xf0, 0x1c, 0xbc, + 0x8d, 0xda, 0x45, 0x2c, 0x61, 0xe9, 0xa9, 0xe8, 0x46, 0xbc, 0x82, 0xe3, 0x4f, 0x59, 0xb5, 0x2a, + 0x9a, 0x26, 0x2c, 0xf5, 0xf3, 0x45, 0xff, 0x79, 0x17, 0x7a, 0x53, 0x56, 0x0c, 0xee, 0xdd, 0xf4, + 0x96, 0xf1, 0x6b, 0x80, 0x83, 0x81, 0xe9, 0xbf, 0x6a, 0xc1, 0xdf, 0xec, 0xa1, 0x05, 0xbf, 0x81, + 0xb9, 0x13, 0x31, 0x82, 0xb9, 0x2c, 0x8a, 0x46, 0x19, 0xe3, 0x3a, 0xec, 0x57, 0x44, 0x38, 0xd2, + 0xd4, 0xd8, 0xbe, 0x46, 0x28, 0xfa, 0x39, 0xff, 0x82, 0xe0, 0xa5, 0x63, 0xf8, 0x48, 0xba, 0xac, + 0xc8, 0xe2, 0x12, 0x66, 0xcf, 0x4a, 0x56, 0xf6, 0x1d, 0xb1, 0xff, 0xd5, 0xb0, 0x38, 0x7c, 0xf1, + 0xc5, 0x48, 0x1b, 0xc8, 0xf0, 0x49, 0x17, 0x1a, 0x68, 0xb9, 0xd0, 0x88, 0xb9, 0x0b, 0x8d, 0x71, + 0xf2, 0xc9, 0x6a, 0xd6, 0x3f, 0xd1, 0xf2, 0x27, 0x00, 0x00, 0xff, 0xff, 0x93, 0x4c, 0x70, 0x80, + 0xc4, 0x01, 0x00, 0x00, } diff --git a/code.cloudfoundry.org/copilot/testhelpers/credentials.go b/code.cloudfoundry.org/copilot/testhelpers/credentials.go index c1c03f24..96f3f14b 100644 --- a/code.cloudfoundry.org/copilot/testhelpers/credentials.go +++ b/code.cloudfoundry.org/copilot/testhelpers/credentials.go @@ -17,16 +17,18 @@ type Credentials struct { } type MTLSCredentials struct { - Server *Credentials - Client *Credentials - TempDir string + Server *Credentials + Client *Credentials + OtherClient *Credentials + TempDir string } func GenerateMTLS() MTLSCredentials { return MTLSCredentials{ - Server: generateCredentials("serverCA", "CopilotServer"), - Client: generateCredentials("clientCA", "CopilotClient"), - TempDir: TempDir(), + Server: generateCredentials("serverCA", "CopilotServer"), + Client: generateCredentials("clientCA", "CopilotClient"), + OtherClient: generateCredentials("otherClientCA", "OtherCopilotClient"), + TempDir: TempDir(), } } @@ -76,10 +78,32 @@ func (m MTLSCredentials) ServerTLSConfig() *tls.Config { tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, }, - CurvePreferences: []tls.CurveID{tls.CurveP384}, - ClientAuth: tls.RequireAndVerifyClientCert, - ClientCAs: clientCAs, - Certificates: []tls.Certificate{serverCert}, + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: clientCAs, + Certificates: []tls.Certificate{serverCert}, + } +} + +func (m MTLSCredentials) ServerTLSConfigForOtherClient() *tls.Config { + otherClientCAs := x509.NewCertPool() + ok := otherClientCAs.AppendCertsFromPEM(m.OtherClient.CA) + if !ok { + panic("failed appending certs") + } + + serverCert, err := tls.X509KeyPair(m.Server.Cert, m.Server.Key) + assertNoError(err) + + return &tls.Config{ + MinVersion: tls.VersionTLS12, + PreferServerCipherSuites: true, + CipherSuites: []uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + }, + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: otherClientCAs, + Certificates: []tls.Certificate{serverCert}, } } @@ -100,14 +124,35 @@ func (m MTLSCredentials) ClientTLSConfig() *tls.Config { tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, }, - CurvePreferences: []tls.CurveID{tls.CurveP384}, - RootCAs: rootCAs, - Certificates: []tls.Certificate{clientCert}, + RootCAs: rootCAs, + Certificates: []tls.Certificate{clientCert}, + } +} + +func (m MTLSCredentials) OtherClientTLSConfig() *tls.Config { + rootCAs := x509.NewCertPool() + ok := rootCAs.AppendCertsFromPEM(m.Server.CA) + if !ok { + panic("failed appending certs") + } + + otherClientCert, err := tls.X509KeyPair(m.OtherClient.Cert, m.OtherClient.Key) + assertNoError(err) + + return &tls.Config{ + MinVersion: tls.VersionTLS12, + PreferServerCipherSuites: true, + CipherSuites: []uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + }, + RootCAs: rootCAs, + Certificates: []tls.Certificate{otherClientCert}, } } type ServerTLSFilePaths struct { - ClientCA, ServerCert, ServerKey string + ClientCA, OtherClientCA, ServerCert, ServerKey string } func (m MTLSCredentials) saveTemp(shortName string, data []byte) string { @@ -122,9 +167,10 @@ func (m MTLSCredentials) saveTemp(shortName string, data []byte) string { // Call m.CleanupTempFiles to remove these files func (m MTLSCredentials) CreateServerTLSFiles() ServerTLSFilePaths { s := ServerTLSFilePaths{ - ClientCA: m.saveTemp("client.ca", m.Client.CA), - ServerCert: m.saveTemp("server.crt", m.Server.Cert), - ServerKey: m.saveTemp("server.key", m.Server.Key), + ClientCA: m.saveTemp("client.ca", m.Client.CA), + OtherClientCA: m.saveTemp("other-client.ca", m.OtherClient.CA), + ServerCert: m.saveTemp("server.crt", m.Server.Cert), + ServerKey: m.saveTemp("server.key", m.Server.Key), } return s } diff --git a/github.com/aws/aws-sdk-go/aws/client/client.go b/github.com/aws/aws-sdk-go/aws/client/client.go index 788fe6e2..3271a18e 100644 --- a/github.com/aws/aws-sdk-go/aws/client/client.go +++ b/github.com/aws/aws-sdk-go/aws/client/client.go @@ -15,6 +15,12 @@ type Config struct { Endpoint string SigningRegion string SigningName string + + // States that the signing name did not come from a modeled source but + // was derived based on other data. Used by service client constructors + // to determine if the signin name can be overriden based on metadata the + // service has. + SigningNameDerived bool } // ConfigProvider provides a generic way for a service client to receive diff --git a/github.com/aws/aws-sdk-go/aws/client/default_retryer.go b/github.com/aws/aws-sdk-go/aws/client/default_retryer.go index 4148d62e..a397b0d0 100644 --- a/github.com/aws/aws-sdk-go/aws/client/default_retryer.go +++ b/github.com/aws/aws-sdk-go/aws/client/default_retryer.go @@ -62,7 +62,7 @@ func (d DefaultRetryer) ShouldRetry(r *request.Request) bool { return *r.Retryable } - if r.HTTPResponse.StatusCode >= 500 { + if r.HTTPResponse.StatusCode >= 500 && r.HTTPResponse.StatusCode != 501 { return true } return r.IsErrorRetryable() || d.shouldThrottle(r) diff --git a/github.com/aws/aws-sdk-go/aws/config.go b/github.com/aws/aws-sdk-go/aws/config.go index 4fd0d072..5421b5d4 100644 --- a/github.com/aws/aws-sdk-go/aws/config.go +++ b/github.com/aws/aws-sdk-go/aws/config.go @@ -151,6 +151,15 @@ type Config struct { // with accelerate. S3UseAccelerate *bool + // S3DisableContentMD5Validation config option is temporarily disabled, + // For S3 GetObject API calls, #1837. + // + // Set this to `true` to disable the S3 service client from automatically + // adding the ContentMD5 to S3 Object Put and Upload API calls. This option + // will also disable the SDK from performing object ContentMD5 validation + // on GetObject API calls. + S3DisableContentMD5Validation *bool + // Set this to `true` to disable the EC2Metadata client from overriding the // default http.Client's Timeout. This is helpful if you do not want the // EC2Metadata client to create a new http.Client. This options is only @@ -336,6 +345,15 @@ func (c *Config) WithS3Disable100Continue(disable bool) *Config { func (c *Config) WithS3UseAccelerate(enable bool) *Config { c.S3UseAccelerate = &enable return c + +} + +// WithS3DisableContentMD5Validation sets a config +// S3DisableContentMD5Validation value returning a Config pointer for chaining. +func (c *Config) WithS3DisableContentMD5Validation(enable bool) *Config { + c.S3DisableContentMD5Validation = &enable + return c + } // WithUseDualStack sets a config UseDualStack value returning a Config @@ -435,6 +453,10 @@ func mergeInConfig(dst *Config, other *Config) { dst.S3UseAccelerate = other.S3UseAccelerate } + if other.S3DisableContentMD5Validation != nil { + dst.S3DisableContentMD5Validation = other.S3DisableContentMD5Validation + } + if other.UseDualStack != nil { dst.UseDualStack = other.UseDualStack } diff --git a/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go b/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go index bfb1fcd1..cfcddf3d 100644 --- a/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go +++ b/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go @@ -7,7 +7,6 @@ import ( "net/http" "net/url" "regexp" - "runtime" "strconv" "time" @@ -54,13 +53,6 @@ var BuildContentLengthHandler = request.NamedHandler{Name: "core.BuildContentLen } }} -// SDKVersionUserAgentHandler is a request handler for adding the SDK Version to the user agent. -var SDKVersionUserAgentHandler = request.NamedHandler{ - Name: "core.SDKVersionUserAgentHandler", - Fn: request.MakeAddToUserAgentHandler(aws.SDKName, aws.SDKVersion, - runtime.Version(), runtime.GOOS, runtime.GOARCH), -} - var reStatusCode = regexp.MustCompile(`^(\d{3})`) // ValidateReqSigHandler is a request handler to ensure that the request's diff --git a/github.com/aws/aws-sdk-go/aws/corehandlers/user_agent.go b/github.com/aws/aws-sdk-go/aws/corehandlers/user_agent.go new file mode 100644 index 00000000..a15f496b --- /dev/null +++ b/github.com/aws/aws-sdk-go/aws/corehandlers/user_agent.go @@ -0,0 +1,37 @@ +package corehandlers + +import ( + "os" + "runtime" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/request" +) + +// SDKVersionUserAgentHandler is a request handler for adding the SDK Version +// to the user agent. +var SDKVersionUserAgentHandler = request.NamedHandler{ + Name: "core.SDKVersionUserAgentHandler", + Fn: request.MakeAddToUserAgentHandler(aws.SDKName, aws.SDKVersion, + runtime.Version(), runtime.GOOS, runtime.GOARCH), +} + +const execEnvVar = `AWS_EXECUTION_ENV` +const execEnvUAKey = `exec_env` + +// AddHostExecEnvUserAgentHander is a request handler appending the SDK's +// execution environment to the user agent. +// +// If the environment variable AWS_EXECUTION_ENV is set, its value will be +// appended to the user agent string. +var AddHostExecEnvUserAgentHander = request.NamedHandler{ + Name: "core.AddHostExecEnvUserAgentHander", + Fn: func(r *request.Request) { + v := os.Getenv(execEnvVar) + if len(v) == 0 { + return + } + + request.AddToUserAgent(r, execEnvUAKey+"/"+v) + }, +} diff --git a/github.com/aws/aws-sdk-go/aws/defaults/defaults.go b/github.com/aws/aws-sdk-go/aws/defaults/defaults.go index 2cb08182..3cf1036b 100644 --- a/github.com/aws/aws-sdk-go/aws/defaults/defaults.go +++ b/github.com/aws/aws-sdk-go/aws/defaults/defaults.go @@ -73,6 +73,7 @@ func Handlers() request.Handlers { handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler) handlers.Validate.AfterEachFn = request.HandlerListStopOnError handlers.Build.PushBackNamed(corehandlers.SDKVersionUserAgentHandler) + handlers.Build.PushBackNamed(corehandlers.AddHostExecEnvUserAgentHander) handlers.Build.AfterEachFn = request.HandlerListStopOnError handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler) handlers.Send.PushBackNamed(corehandlers.ValidateReqSigHandler) diff --git a/github.com/aws/aws-sdk-go/aws/endpoints/decode.go b/github.com/aws/aws-sdk-go/aws/endpoints/decode.go index 6dc035a5..74f72de0 100644 --- a/github.com/aws/aws-sdk-go/aws/endpoints/decode.go +++ b/github.com/aws/aws-sdk-go/aws/endpoints/decode.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "io" - "os" "github.com/aws/aws-sdk-go/aws/awserr" ) @@ -85,34 +84,11 @@ func decodeV3Endpoints(modelDef modelDefinition, opts DecodeModelOptions) (Resol custAddEC2Metadata(p) custAddS3DualStack(p) custRmIotDataService(p) - - custFixCloudHSMv2SigningName(p) } return ps, nil } -func custFixCloudHSMv2SigningName(p *partition) { - // Workaround for aws/aws-sdk-go#1745 until the endpoint model can be - // fixed upstream. TODO remove this once the endpoints model is updated. - - s, ok := p.Services["cloudhsmv2"] - if !ok { - return - } - - if len(s.Defaults.CredentialScope.Service) != 0 { - fmt.Fprintf(os.Stderr, "cloudhsmv2 signing name already set, ignoring override.\n") - // If the value is already set don't override - return - } - - s.Defaults.CredentialScope.Service = "cloudhsm" - fmt.Fprintf(os.Stderr, "cloudhsmv2 signing name not set, overriding.\n") - - p.Services["cloudhsmv2"] = s -} - func custAddS3DualStack(p *partition) { if p.ID != "aws" { return diff --git a/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go b/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go index 537dfb74..1d9a30ce 100644 --- a/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go +++ b/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go @@ -45,6 +45,7 @@ const ( // Service identifiers const ( + A4bServiceID = "a4b" // A4b. AcmServiceID = "acm" // Acm. ApiPricingServiceID = "api.pricing" // ApiPricing. ApigatewayServiceID = "apigateway" // Apigateway. @@ -55,6 +56,8 @@ const ( AutoscalingPlansServiceID = "autoscaling-plans" // AutoscalingPlans. BatchServiceID = "batch" // Batch. BudgetsServiceID = "budgets" // Budgets. + CeServiceID = "ce" // Ce. + Cloud9ServiceID = "cloud9" // Cloud9. ClouddirectoryServiceID = "clouddirectory" // Clouddirectory. CloudformationServiceID = "cloudformation" // Cloudformation. CloudfrontServiceID = "cloudfront" // Cloudfront. @@ -70,6 +73,7 @@ const ( CognitoIdentityServiceID = "cognito-identity" // CognitoIdentity. CognitoIdpServiceID = "cognito-idp" // CognitoIdp. CognitoSyncServiceID = "cognito-sync" // CognitoSync. + ComprehendServiceID = "comprehend" // Comprehend. ConfigServiceID = "config" // Config. CurServiceID = "cur" // Cur. DatapipelineServiceID = "datapipeline" // Datapipeline. @@ -99,6 +103,7 @@ const ( GlacierServiceID = "glacier" // Glacier. GlueServiceID = "glue" // Glue. GreengrassServiceID = "greengrass" // Greengrass. + GuarddutyServiceID = "guardduty" // Guardduty. HealthServiceID = "health" // Health. IamServiceID = "iam" // Iam. ImportexportServiceID = "importexport" // Importexport. @@ -130,11 +135,15 @@ const ( RdsServiceID = "rds" // Rds. RedshiftServiceID = "redshift" // Redshift. RekognitionServiceID = "rekognition" // Rekognition. + ResourceGroupsServiceID = "resource-groups" // ResourceGroups. Route53ServiceID = "route53" // Route53. Route53domainsServiceID = "route53domains" // Route53domains. RuntimeLexServiceID = "runtime.lex" // RuntimeLex. + RuntimeSagemakerServiceID = "runtime.sagemaker" // RuntimeSagemaker. S3ServiceID = "s3" // S3. + SagemakerServiceID = "sagemaker" // Sagemaker. SdbServiceID = "sdb" // Sdb. + ServerlessrepoServiceID = "serverlessrepo" // Serverlessrepo. ServicecatalogServiceID = "servicecatalog" // Servicecatalog. ServicediscoveryServiceID = "servicediscovery" // Servicediscovery. ShieldServiceID = "shield" // Shield. @@ -150,9 +159,11 @@ const ( SupportServiceID = "support" // Support. SwfServiceID = "swf" // Swf. TaggingServiceID = "tagging" // Tagging. + TranslateServiceID = "translate" // Translate. WafServiceID = "waf" // Waf. WafRegionalServiceID = "waf-regional" // WafRegional. WorkdocsServiceID = "workdocs" // Workdocs. + WorkmailServiceID = "workmail" // Workmail. WorkspacesServiceID = "workspaces" // Workspaces. XrayServiceID = "xray" // Xray. ) @@ -250,6 +261,12 @@ var awsPartition = partition{ }, }, Services: services{ + "a4b": service{ + + Endpoints: endpoints{ + "us-east-1": endpoint{}, + }, + }, "acm": service{ Endpoints: endpoints{ @@ -396,13 +413,16 @@ var awsPartition = partition{ Endpoints: endpoints{ "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, "ap-southeast-1": endpoint{}, "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, "eu-central-1": endpoint{}, "eu-west-1": endpoint{}, "eu-west-2": endpoint{}, "us-east-1": endpoint{}, "us-east-2": endpoint{}, + "us-west-1": endpoint{}, "us-west-2": endpoint{}, }, }, @@ -419,6 +439,29 @@ var awsPartition = partition{ }, }, }, + "ce": service{ + PartitionEndpoint: "aws-global", + IsRegionalized: boxedFalse, + + Endpoints: endpoints{ + "aws-global": endpoint{ + Hostname: "ce.us-east-1.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-east-1", + }, + }, + }, + }, + "cloud9": service{ + + Endpoints: endpoints{ + "ap-southeast-1": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, "clouddirectory": service{ Endpoints: endpoints{ @@ -541,12 +584,15 @@ var awsPartition = partition{ Endpoints: endpoints{ "ap-northeast-1": endpoint{}, "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, "ap-southeast-1": endpoint{}, "ap-southeast-2": endpoint{}, "ca-central-1": endpoint{}, "eu-central-1": endpoint{}, "eu-west-1": endpoint{}, "eu-west-2": endpoint{}, + "eu-west-3": endpoint{}, + "sa-east-1": endpoint{}, "us-east-1": endpoint{}, "us-east-2": endpoint{}, "us-west-1": endpoint{}, @@ -677,6 +723,17 @@ var awsPartition = partition{ "us-west-2": endpoint{}, }, }, + "comprehend": service{ + Defaults: endpoint{ + Protocols: []string{"https"}, + }, + Endpoints: endpoints{ + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, "config": service{ Endpoints: endpoints{ @@ -948,6 +1005,7 @@ var awsPartition = partition{ "eu-west-1": endpoint{}, "us-east-1": endpoint{}, "us-east-2": endpoint{}, + "us-west-1": endpoint{}, "us-west-2": endpoint{}, }, }, @@ -1148,6 +1206,29 @@ var awsPartition = partition{ "us-west-2": endpoint{}, }, }, + "guardduty": service{ + IsRegionalized: boxedTrue, + Defaults: endpoint{ + Protocols: []string{"https"}, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "eu-west-3": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, "health": service{ Endpoints: endpoints{ @@ -1346,12 +1427,17 @@ var awsPartition = partition{ Endpoints: endpoints{ "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, "ap-south-1": endpoint{}, "ap-southeast-1": endpoint{}, "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, "eu-central-1": endpoint{}, "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, "us-east-1": endpoint{}, + "us-east-2": endpoint{}, "us-west-1": endpoint{}, "us-west-2": endpoint{}, }, @@ -1371,11 +1457,13 @@ var awsPartition = partition{ Endpoints: endpoints{ "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, "ap-southeast-1": endpoint{}, "ap-southeast-2": endpoint{}, "eu-central-1": endpoint{}, "eu-west-1": endpoint{}, "eu-west-3": endpoint{}, + "sa-east-1": endpoint{}, "us-east-1": endpoint{}, "us-west-2": endpoint{}, }, @@ -1396,6 +1484,7 @@ var awsPartition = partition{ "eu-central-1": endpoint{}, "eu-west-1": endpoint{}, "eu-west-2": endpoint{}, + "eu-west-3": endpoint{}, "sa-east-1": endpoint{}, "us-east-1": endpoint{}, "us-east-2": endpoint{}, @@ -1422,6 +1511,7 @@ var awsPartition = partition{ }, }, Endpoints: endpoints{ + "eu-west-1": endpoint{}, "us-east-1": endpoint{}, }, }, @@ -1480,9 +1570,15 @@ var awsPartition = partition{ "opsworks-cm": service{ Endpoints: endpoints{ - "eu-west-1": endpoint{}, - "us-east-1": endpoint{}, - "us-west-2": endpoint{}, + "ap-northeast-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, }, }, "organizations": service{ @@ -1573,10 +1669,31 @@ var awsPartition = partition{ "rekognition": service{ Endpoints: endpoints{ - "eu-west-1": endpoint{}, - "us-east-1": endpoint{}, - "us-east-2": endpoint{}, - "us-west-2": endpoint{}, + "ap-northeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "resource-groups": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, }, }, "route53": service{ @@ -1609,6 +1726,15 @@ var awsPartition = partition{ "us-east-1": endpoint{}, }, }, + "runtime.sagemaker": service{ + + Endpoints: endpoints{ + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, "s3": service{ PartitionEndpoint: "us-east-1", IsRegionalized: boxedTrue, @@ -1668,6 +1794,15 @@ var awsPartition = partition{ }, }, }, + "sagemaker": service{ + + Endpoints: endpoints{ + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, "sdb": service{ Defaults: endpoint{ Protocols: []string{"http", "https"}, @@ -1686,6 +1821,55 @@ var awsPartition = partition{ "us-west-2": endpoint{}, }, }, + "serverlessrepo": service{ + Defaults: endpoint{ + Protocols: []string{"https"}, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{ + Protocols: []string{"https"}, + }, + "ap-northeast-2": endpoint{ + Protocols: []string{"https"}, + }, + "ap-south-1": endpoint{ + Protocols: []string{"https"}, + }, + "ap-southeast-1": endpoint{ + Protocols: []string{"https"}, + }, + "ap-southeast-2": endpoint{ + Protocols: []string{"https"}, + }, + "ca-central-1": endpoint{ + Protocols: []string{"https"}, + }, + "eu-central-1": endpoint{ + Protocols: []string{"https"}, + }, + "eu-west-1": endpoint{ + Protocols: []string{"https"}, + }, + "eu-west-2": endpoint{ + Protocols: []string{"https"}, + }, + "sa-east-1": endpoint{ + Protocols: []string{"https"}, + }, + "us-east-1": endpoint{ + Protocols: []string{"https"}, + }, + "us-east-2": endpoint{ + Protocols: []string{"https"}, + }, + "us-west-1": endpoint{ + Protocols: []string{"https"}, + }, + "us-west-2": endpoint{ + Protocols: []string{"https"}, + }, + }, + }, "servicecatalog": service{ Endpoints: endpoints{ @@ -1731,6 +1915,7 @@ var awsPartition = partition{ "ap-northeast-1": endpoint{}, "ap-northeast-2": endpoint{}, "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, "ap-southeast-2": endpoint{}, "ca-central-1": endpoint{}, "eu-central-1": endpoint{}, @@ -1748,6 +1933,7 @@ var awsPartition = partition{ Endpoints: endpoints{ "ap-northeast-1": endpoint{}, "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, "ap-southeast-2": endpoint{}, "ca-central-1": endpoint{}, "eu-central-1": endpoint{}, @@ -1989,6 +2175,7 @@ var awsPartition = partition{ "eu-central-1": endpoint{}, "eu-west-1": endpoint{}, "eu-west-2": endpoint{}, + "eu-west-3": endpoint{}, "sa-east-1": endpoint{}, "us-east-1": endpoint{}, "us-east-2": endpoint{}, @@ -1996,6 +2183,16 @@ var awsPartition = partition{ "us-west-2": endpoint{}, }, }, + "translate": service{ + Defaults: endpoint{ + Protocols: []string{"https"}, + }, + Endpoints: endpoints{ + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, "waf": service{ PartitionEndpoint: "aws-global", IsRegionalized: boxedFalse, @@ -2032,15 +2229,27 @@ var awsPartition = partition{ "us-west-2": endpoint{}, }, }, + "workmail": service{ + Defaults: endpoint{ + Protocols: []string{"https"}, + }, + Endpoints: endpoints{ + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, "workspaces": service{ Endpoints: endpoints{ "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, "ap-southeast-1": endpoint{}, "ap-southeast-2": endpoint{}, "eu-central-1": endpoint{}, "eu-west-1": endpoint{}, "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, "us-east-1": endpoint{}, "us-west-2": endpoint{}, }, @@ -2409,7 +2618,8 @@ var awscnPartition = partition{ "tagging": service{ Endpoints: endpoints{ - "cn-north-1": endpoint{}, + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, }, }, }, @@ -2629,12 +2839,28 @@ var awsusgovPartition = partition{ "us-gov-west-1": endpoint{}, }, }, + "metering.marketplace": service{ + Defaults: endpoint{ + CredentialScope: credentialScope{ + Service: "aws-marketplace", + }, + }, + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, "monitoring": service{ Endpoints: endpoints{ "us-gov-west-1": endpoint{}, }, }, + "polly": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, "rds": service{ Endpoints: endpoints{ @@ -2668,10 +2894,6 @@ var awsusgovPartition = partition{ Hostname: "s3.us-gov-west-1.amazonaws.com", Protocols: []string{"http", "https"}, }, - "us-gov-west-1-dualstack": endpoint{ - Hostname: "s3.dualstack.us-gov-west-1.amazonaws.com", - SignatureVersions: []string{"s3", "s3v4"}, - }, }, }, "sms": service{ @@ -2733,6 +2955,12 @@ var awsusgovPartition = partition{ }, "swf": service{ + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "tagging": service{ + Endpoints: endpoints{ "us-gov-west-1": endpoint{}, }, diff --git a/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go b/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go index 9c3eedb4..d6be83c1 100644 --- a/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go +++ b/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go @@ -347,6 +347,10 @@ type ResolvedEndpoint struct { // The service name that should be used for signing requests. SigningName string + // States that the signing name for this endpoint was derived from metadata + // passed in, but was not explicitly modeled. + SigningNameDerived bool + // The signing method that should be used for signing requests. SigningMethod string } diff --git a/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go b/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go index 13d968a2..ff6f76db 100644 --- a/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go +++ b/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go @@ -226,16 +226,20 @@ func (e endpoint) resolve(service, region, dnsSuffix string, defs []endpoint, op if len(signingRegion) == 0 { signingRegion = region } + signingName := e.CredentialScope.Service + var signingNameDerived bool if len(signingName) == 0 { signingName = service + signingNameDerived = true } return ResolvedEndpoint{ - URL: u, - SigningRegion: signingRegion, - SigningName: signingName, - SigningMethod: getByPriority(e.SignatureVersions, signerPriority, defaultSigner), + URL: u, + SigningRegion: signingRegion, + SigningName: signingName, + SigningNameDerived: signingNameDerived, + SigningMethod: getByPriority(e.SignatureVersions, signerPriority, defaultSigner), } } diff --git a/github.com/aws/aws-sdk-go/aws/request/offset_reader.go b/github.com/aws/aws-sdk-go/aws/request/offset_reader.go index 02f07f4a..b0c2ef4f 100644 --- a/github.com/aws/aws-sdk-go/aws/request/offset_reader.go +++ b/github.com/aws/aws-sdk-go/aws/request/offset_reader.go @@ -3,6 +3,8 @@ package request import ( "io" "sync" + + "github.com/aws/aws-sdk-go/internal/sdkio" ) // offsetReader is a thread-safe io.ReadCloser to prevent racing @@ -15,7 +17,7 @@ type offsetReader struct { func newOffsetReader(buf io.ReadSeeker, offset int64) *offsetReader { reader := &offsetReader{} - buf.Seek(offset, 0) + buf.Seek(offset, sdkio.SeekStart) reader.buf = buf return reader diff --git a/github.com/aws/aws-sdk-go/aws/request/request.go b/github.com/aws/aws-sdk-go/aws/request/request.go index 81abcb80..69b7a01a 100644 --- a/github.com/aws/aws-sdk-go/aws/request/request.go +++ b/github.com/aws/aws-sdk-go/aws/request/request.go @@ -14,6 +14,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/internal/sdkio" ) const ( @@ -258,7 +259,7 @@ func (r *Request) SetStringBody(s string) { // SetReaderBody will set the request's body reader. func (r *Request) SetReaderBody(reader io.ReadSeeker) { r.Body = reader - r.BodyStart, _ = reader.Seek(0, 1) // Get the Bodies current offset. + r.BodyStart, _ = reader.Seek(0, sdkio.SeekCurrent) // Get the Bodies current offset. r.ResetBody() } @@ -296,6 +297,11 @@ func (r *Request) PresignRequest(expire time.Duration) (string, http.Header, err return getPresignedURL(r, expire) } +// IsPresigned returns true if the request represents a presigned API url. +func (r *Request) IsPresigned() bool { + return r.ExpireTime != 0 +} + func getPresignedURL(r *Request, expire time.Duration) (string, http.Header, error) { if expire <= 0 { return "", nil, awserr.New( @@ -336,7 +342,7 @@ func debugLogReqError(r *Request, stage string, retrying bool, err error) { // Build will build the request's object so it can be signed and sent // to the service. Build will also validate all the request's parameters. -// Anny additional build Handlers set on this request will be run +// Any additional build Handlers set on this request will be run // in the order they were set. // // The request will only be built once. Multiple calls to build will have diff --git a/github.com/aws/aws-sdk-go/aws/session/session.go b/github.com/aws/aws-sdk-go/aws/session/session.go index 2fc789d6..259b5c0f 100644 --- a/github.com/aws/aws-sdk-go/aws/session/session.go +++ b/github.com/aws/aws-sdk-go/aws/session/session.go @@ -26,7 +26,7 @@ import ( // Sessions are safe to create service clients concurrently, but it is not safe // to mutate the Session concurrently. // -// The Session satisfies the service client's client.ClientConfigProvider. +// The Session satisfies the service client's client.ConfigProvider. type Session struct { Config *aws.Config Handlers request.Handlers @@ -571,11 +571,12 @@ func (s *Session) clientConfigWithErr(serviceName string, cfgs ...*aws.Config) ( } return client.Config{ - Config: s.Config, - Handlers: s.Handlers, - Endpoint: resolved.URL, - SigningRegion: resolved.SigningRegion, - SigningName: resolved.SigningName, + Config: s.Config, + Handlers: s.Handlers, + Endpoint: resolved.URL, + SigningRegion: resolved.SigningRegion, + SigningNameDerived: resolved.SigningNameDerived, + SigningName: resolved.SigningName, }, err } @@ -595,10 +596,11 @@ func (s *Session) ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) client.Conf } return client.Config{ - Config: s.Config, - Handlers: s.Handlers, - Endpoint: resolved.URL, - SigningRegion: resolved.SigningRegion, - SigningName: resolved.SigningName, + Config: s.Config, + Handlers: s.Handlers, + Endpoint: resolved.URL, + SigningRegion: resolved.SigningRegion, + SigningNameDerived: resolved.SigningNameDerived, + SigningName: resolved.SigningName, } } diff --git a/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go b/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go index 4261bbcd..6e463761 100644 --- a/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go +++ b/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go @@ -71,6 +71,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/internal/sdkio" "github.com/aws/aws-sdk-go/private/protocol/rest" ) @@ -726,8 +727,8 @@ func makeSha256(data []byte) []byte { func makeSha256Reader(reader io.ReadSeeker) []byte { hash := sha256.New() - start, _ := reader.Seek(0, 1) - defer reader.Seek(start, 0) + start, _ := reader.Seek(0, sdkio.SeekCurrent) + defer reader.Seek(start, sdkio.SeekStart) io.Copy(hash, reader) return hash.Sum(nil) diff --git a/github.com/aws/aws-sdk-go/aws/types.go b/github.com/aws/aws-sdk-go/aws/types.go index 3b4348a1..8b6f2342 100644 --- a/github.com/aws/aws-sdk-go/aws/types.go +++ b/github.com/aws/aws-sdk-go/aws/types.go @@ -3,6 +3,8 @@ package aws import ( "io" "sync" + + "github.com/aws/aws-sdk-go/internal/sdkio" ) // ReadSeekCloser wraps a io.Reader returning a ReaderSeekerCloser. Should @@ -119,17 +121,17 @@ func SeekerLen(s io.Seeker) (int64, error) { } func seekerLen(s io.Seeker) (int64, error) { - curOffset, err := s.Seek(0, 1) + curOffset, err := s.Seek(0, sdkio.SeekCurrent) if err != nil { return 0, err } - endOffset, err := s.Seek(0, 2) + endOffset, err := s.Seek(0, sdkio.SeekEnd) if err != nil { return 0, err } - _, err = s.Seek(curOffset, 0) + _, err = s.Seek(curOffset, sdkio.SeekStart) if err != nil { return 0, err } diff --git a/github.com/aws/aws-sdk-go/aws/version.go b/github.com/aws/aws-sdk-go/aws/version.go index 9e3d620b..c603da94 100644 --- a/github.com/aws/aws-sdk-go/aws/version.go +++ b/github.com/aws/aws-sdk-go/aws/version.go @@ -5,4 +5,4 @@ package aws const SDKName = "aws-sdk-go" // SDKVersion is the version of this SDK -const SDKVersion = "1.13.7" +const SDKVersion = "1.13.24" diff --git a/github.com/aws/aws-sdk-go/internal/sdkio/io_go1.6.go b/github.com/aws/aws-sdk-go/internal/sdkio/io_go1.6.go new file mode 100644 index 00000000..5aa9137e --- /dev/null +++ b/github.com/aws/aws-sdk-go/internal/sdkio/io_go1.6.go @@ -0,0 +1,10 @@ +// +build !go1.7 + +package sdkio + +// Copy of Go 1.7 io package's Seeker constants. +const ( + SeekStart = 0 // seek relative to the origin of the file + SeekCurrent = 1 // seek relative to the current offset + SeekEnd = 2 // seek relative to the end +) diff --git a/github.com/aws/aws-sdk-go/internal/sdkio/io_go1.7.go b/github.com/aws/aws-sdk-go/internal/sdkio/io_go1.7.go new file mode 100644 index 00000000..e5f00561 --- /dev/null +++ b/github.com/aws/aws-sdk-go/internal/sdkio/io_go1.7.go @@ -0,0 +1,12 @@ +// +build go1.7 + +package sdkio + +import "io" + +// Alias for Go 1.7 io package Seeker constants +const ( + SeekStart = io.SeekStart // seek relative to the origin of the file + SeekCurrent = io.SeekCurrent // seek relative to the current offset + SeekEnd = io.SeekEnd // seek relative to the end +) diff --git a/github.com/aws/aws-sdk-go/private/protocol/query/build.go b/github.com/aws/aws-sdk-go/private/protocol/query/build.go index 18169f0f..60e5b09d 100644 --- a/github.com/aws/aws-sdk-go/private/protocol/query/build.go +++ b/github.com/aws/aws-sdk-go/private/protocol/query/build.go @@ -25,7 +25,7 @@ func Build(r *request.Request) { return } - if r.ExpireTime == 0 { + if !r.IsPresigned() { r.HTTPRequest.Method = "POST" r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8") r.SetBufferBody([]byte(body.Encode())) diff --git a/github.com/aws/aws-sdk-go/service/sts/api.go b/github.com/aws/aws-sdk-go/service/sts/api.go index 2b17d066..89d2ce6a 100644 --- a/github.com/aws/aws-sdk-go/service/sts/api.go +++ b/github.com/aws/aws-sdk-go/service/sts/api.go @@ -88,9 +88,18 @@ func (c *STS) AssumeRoleRequest(input *AssumeRoleInput) (req *request.Request, o // Scenarios for Temporary Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html#sts-introduction) // in the IAM User Guide. // -// The temporary security credentials are valid for the duration that you specified -// when calling AssumeRole, which can be from 900 seconds (15 minutes) to a -// maximum of 3600 seconds (1 hour). The default is 1 hour. +// By default, the temporary security credentials created by AssumeRole last +// for one hour. However, you can use the optional DurationSeconds parameter +// to specify the duration of your session. You can provide a value from 900 +// seconds (15 minutes) up to the maximum session duration setting for the role. +// This setting can have a value from 1 hour to 12 hours. To learn how to view +// the maximum value for your role, see View the Maximum Session Duration Setting +// for a Role (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html#id_roles_use_view-role-max-session) +// in the IAM User Guide. The maximum session duration limit applies when you +// use the AssumeRole* API operations or the assume-role* CLI operations but +// does not apply when you use those operations to create a console URL. For +// more information, see Using IAM Roles (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html) +// in the IAM User Guide. // // The temporary security credentials created by AssumeRole can be used to make // API calls to any AWS service with the following exception: you cannot call @@ -252,11 +261,20 @@ func (c *STS) AssumeRoleWithSAMLRequest(input *AssumeRoleWithSAMLInput) (req *re // an access key ID, a secret access key, and a security token. Applications // can use these temporary security credentials to sign calls to AWS services. // -// The temporary security credentials are valid for the duration that you specified -// when calling AssumeRole, or until the time specified in the SAML authentication -// response's SessionNotOnOrAfter value, whichever is shorter. The duration -// can be from 900 seconds (15 minutes) to a maximum of 3600 seconds (1 hour). -// The default is 1 hour. +// By default, the temporary security credentials created by AssumeRoleWithSAML +// last for one hour. However, you can use the optional DurationSeconds parameter +// to specify the duration of your session. Your role session lasts for the +// duration that you specify, or until the time specified in the SAML authentication +// response's SessionNotOnOrAfter value, whichever is shorter. You can provide +// a DurationSeconds value from 900 seconds (15 minutes) up to the maximum session +// duration setting for the role. This setting can have a value from 1 hour +// to 12 hours. To learn how to view the maximum value for your role, see View +// the Maximum Session Duration Setting for a Role (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html#id_roles_use_view-role-max-session) +// in the IAM User Guide. The maximum session duration limit applies when you +// use the AssumeRole* API operations or the assume-role* CLI operations but +// does not apply when you use those operations to create a console URL. For +// more information, see Using IAM Roles (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html) +// in the IAM User Guide. // // The temporary security credentials created by AssumeRoleWithSAML can be used // to make API calls to any AWS service with the following exception: you cannot @@ -443,9 +461,18 @@ func (c *STS) AssumeRoleWithWebIdentityRequest(input *AssumeRoleWithWebIdentityI // key ID, a secret access key, and a security token. Applications can use these // temporary security credentials to sign calls to AWS service APIs. // -// The credentials are valid for the duration that you specified when calling -// AssumeRoleWithWebIdentity, which can be from 900 seconds (15 minutes) to -// a maximum of 3600 seconds (1 hour). The default is 1 hour. +// By default, the temporary security credentials created by AssumeRoleWithWebIdentity +// last for one hour. However, you can use the optional DurationSeconds parameter +// to specify the duration of your session. You can provide a value from 900 +// seconds (15 minutes) up to the maximum session duration setting for the role. +// This setting can have a value from 1 hour to 12 hours. To learn how to view +// the maximum value for your role, see View the Maximum Session Duration Setting +// for a Role (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html#id_roles_use_view-role-max-session) +// in the IAM User Guide. The maximum session duration limit applies when you +// use the AssumeRole* API operations or the assume-role* CLI operations but +// does not apply when you use those operations to create a console URL. For +// more information, see Using IAM Roles (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html) +// in the IAM User Guide. // // The temporary security credentials created by AssumeRoleWithWebIdentity can // be used to make API calls to any AWS service with the following exception: @@ -1058,15 +1085,23 @@ type AssumeRoleInput struct { _ struct{} `type:"structure"` // The duration, in seconds, of the role session. The value can range from 900 - // seconds (15 minutes) to 3600 seconds (1 hour). By default, the value is set - // to 3600 seconds. + // seconds (15 minutes) up to the maximum session duration setting for the role. + // This setting can have a value from 1 hour to 12 hours. If you specify a value + // higher than this setting, the operation fails. For example, if you specify + // a session duration of 12 hours, but your administrator set the maximum session + // duration to 6 hours, your operation fails. To learn how to view the maximum + // value for your role, see View the Maximum Session Duration Setting for a + // Role (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html#id_roles_use_view-role-max-session) + // in the IAM User Guide. + // + // By default, the value is set to 3600 seconds. // - // This is separate from the duration of a console session that you might request - // using the returned credentials. The request to the federation endpoint for - // a console sign-in token takes a SessionDuration parameter that specifies - // the maximum length of the console session, separately from the DurationSeconds - // parameter on this API. For more information, see Creating a URL that Enables - // Federated Users to Access the AWS Management Console (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html) + // The DurationSeconds parameter is separate from the duration of a console + // session that you might request using the returned credentials. The request + // to the federation endpoint for a console sign-in token takes a SessionDuration + // parameter that specifies the maximum length of the console session. For more + // information, see Creating a URL that Enables Federated Users to Access the + // AWS Management Console (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html) // in the IAM User Guide. DurationSeconds *int64 `min:"900" type:"integer"` @@ -1301,18 +1336,27 @@ func (s *AssumeRoleOutput) SetPackedPolicySize(v int64) *AssumeRoleOutput { type AssumeRoleWithSAMLInput struct { _ struct{} `type:"structure"` - // The duration, in seconds, of the role session. The value can range from 900 - // seconds (15 minutes) to 3600 seconds (1 hour). By default, the value is set - // to 3600 seconds. An expiration can also be specified in the SAML authentication - // response's SessionNotOnOrAfter value. The actual expiration time is whichever - // value is shorter. + // The duration, in seconds, of the role session. Your role session lasts for + // the duration that you specify for the DurationSeconds parameter, or until + // the time specified in the SAML authentication response's SessionNotOnOrAfter + // value, whichever is shorter. You can provide a DurationSeconds value from + // 900 seconds (15 minutes) up to the maximum session duration setting for the + // role. This setting can have a value from 1 hour to 12 hours. If you specify + // a value higher than this setting, the operation fails. For example, if you + // specify a session duration of 12 hours, but your administrator set the maximum + // session duration to 6 hours, your operation fails. To learn how to view the + // maximum value for your role, see View the Maximum Session Duration Setting + // for a Role (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html#id_roles_use_view-role-max-session) + // in the IAM User Guide. + // + // By default, the value is set to 3600 seconds. // - // This is separate from the duration of a console session that you might request - // using the returned credentials. The request to the federation endpoint for - // a console sign-in token takes a SessionDuration parameter that specifies - // the maximum length of the console session, separately from the DurationSeconds - // parameter on this API. For more information, see Enabling SAML 2.0 Federated - // Users to Access the AWS Management Console (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-saml.html) + // The DurationSeconds parameter is separate from the duration of a console + // session that you might request using the returned credentials. The request + // to the federation endpoint for a console sign-in token takes a SessionDuration + // parameter that specifies the maximum length of the console session. For more + // information, see Creating a URL that Enables Federated Users to Access the + // AWS Management Console (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html) // in the IAM User Guide. DurationSeconds *int64 `min:"900" type:"integer"` @@ -1553,15 +1597,23 @@ type AssumeRoleWithWebIdentityInput struct { _ struct{} `type:"structure"` // The duration, in seconds, of the role session. The value can range from 900 - // seconds (15 minutes) to 3600 seconds (1 hour). By default, the value is set - // to 3600 seconds. + // seconds (15 minutes) up to the maximum session duration setting for the role. + // This setting can have a value from 1 hour to 12 hours. If you specify a value + // higher than this setting, the operation fails. For example, if you specify + // a session duration of 12 hours, but your administrator set the maximum session + // duration to 6 hours, your operation fails. To learn how to view the maximum + // value for your role, see View the Maximum Session Duration Setting for a + // Role (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html#id_roles_use_view-role-max-session) + // in the IAM User Guide. + // + // By default, the value is set to 3600 seconds. // - // This is separate from the duration of a console session that you might request - // using the returned credentials. The request to the federation endpoint for - // a console sign-in token takes a SessionDuration parameter that specifies - // the maximum length of the console session, separately from the DurationSeconds - // parameter on this API. For more information, see Creating a URL that Enables - // Federated Users to Access the AWS Management Console (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html) + // The DurationSeconds parameter is separate from the duration of a console + // session that you might request using the returned credentials. The request + // to the federation endpoint for a console sign-in token takes a SessionDuration + // parameter that specifies the maximum length of the console session. For more + // information, see Creating a URL that Enables Federated Users to Access the + // AWS Management Console (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html) // in the IAM User Guide. DurationSeconds *int64 `min:"900" type:"integer"` diff --git a/github.com/beorn7/perks/quantile/stream.go b/github.com/beorn7/perks/quantile/stream.go index f4cabd66..d7d14f8e 100644 --- a/github.com/beorn7/perks/quantile/stream.go +++ b/github.com/beorn7/perks/quantile/stream.go @@ -77,15 +77,20 @@ func NewHighBiased(epsilon float64) *Stream { // is guaranteed to be within (Quantile±Epsilon). // // See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties. -func NewTargeted(targets map[float64]float64) *Stream { +func NewTargeted(targetMap map[float64]float64) *Stream { + // Convert map to slice to avoid slow iterations on a map. + // ƒ is called on the hot path, so converting the map to a slice + // beforehand results in significant CPU savings. + targets := targetMapToSlice(targetMap) + ƒ := func(s *stream, r float64) float64 { var m = math.MaxFloat64 var f float64 - for quantile, epsilon := range targets { - if quantile*s.n <= r { - f = (2 * epsilon * r) / quantile + for _, t := range targets { + if t.quantile*s.n <= r { + f = (2 * t.epsilon * r) / t.quantile } else { - f = (2 * epsilon * (s.n - r)) / (1 - quantile) + f = (2 * t.epsilon * (s.n - r)) / (1 - t.quantile) } if f < m { m = f @@ -96,6 +101,25 @@ func NewTargeted(targets map[float64]float64) *Stream { return newStream(ƒ) } +type target struct { + quantile float64 + epsilon float64 +} + +func targetMapToSlice(targetMap map[float64]float64) []target { + targets := make([]target, 0, len(targetMap)) + + for quantile, epsilon := range targetMap { + t := target{ + quantile: quantile, + epsilon: epsilon, + } + targets = append(targets, t) + } + + return targets +} + // Stream computes quantiles for a stream of float64s. It is not thread-safe by // design. Take care when using across multiple goroutines. type Stream struct { diff --git a/github.com/dgrijalva/jwt-go/ecdsa.go b/github.com/dgrijalva/jwt-go/ecdsa.go index 2f59a222..f9773812 100644 --- a/github.com/dgrijalva/jwt-go/ecdsa.go +++ b/github.com/dgrijalva/jwt-go/ecdsa.go @@ -14,6 +14,7 @@ var ( ) // Implements the ECDSA family of signing methods signing methods +// Expects *ecdsa.PrivateKey for signing and *ecdsa.PublicKey for verification type SigningMethodECDSA struct { Name string Hash crypto.Hash diff --git a/github.com/dgrijalva/jwt-go/hmac.go b/github.com/dgrijalva/jwt-go/hmac.go index c2299192..addbe5d4 100644 --- a/github.com/dgrijalva/jwt-go/hmac.go +++ b/github.com/dgrijalva/jwt-go/hmac.go @@ -7,6 +7,7 @@ import ( ) // Implements the HMAC-SHA family of signing methods signing methods +// Expects key type of []byte for both signing and validation type SigningMethodHMAC struct { Name string Hash crypto.Hash @@ -90,5 +91,5 @@ func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, return EncodeSegment(hasher.Sum(nil)), nil } - return "", ErrInvalidKey + return "", ErrInvalidKeyType } diff --git a/github.com/dgrijalva/jwt-go/parser.go b/github.com/dgrijalva/jwt-go/parser.go index 7bf1c4ea..d6901d9a 100644 --- a/github.com/dgrijalva/jwt-go/parser.go +++ b/github.com/dgrijalva/jwt-go/parser.go @@ -21,55 +21,9 @@ func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { } func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { - parts := strings.Split(tokenString, ".") - if len(parts) != 3 { - return nil, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed) - } - - var err error - 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, NewValidationError("tokenstring should not contain 'bearer '", ValidationErrorMalformed) - } - return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - if err = json.Unmarshal(headerBytes, &token.Header); err != nil { - return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - - // parse Claims - var claimBytes []byte - token.Claims = claims - - if claimBytes, err = DecodeSegment(parts[1]); err != nil { - return token, &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 + token, parts, err := p.ParseUnverified(tokenString, claims) if err != nil { - return token, &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, NewValidationError("signing method (alg) is unavailable.", ValidationErrorUnverifiable) - } - } else { - return token, NewValidationError("signing method (alg) is unspecified.", ValidationErrorUnverifiable) + return token, err } // Verify signing method is in the required set @@ -96,6 +50,9 @@ func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyf } 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} } @@ -129,3 +86,63 @@ func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyf return token, vErr } + +// WARNING: Don't use this method unless you know what you're doing +// +// This method parses the token but doesn't validate the signature. 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/github.com/dgrijalva/jwt-go/rsa.go b/github.com/dgrijalva/jwt-go/rsa.go index 0ae0b198..e4caf1ca 100644 --- a/github.com/dgrijalva/jwt-go/rsa.go +++ b/github.com/dgrijalva/jwt-go/rsa.go @@ -7,6 +7,7 @@ import ( ) // Implements the RSA family of signing methods signing methods +// Expects *rsa.PrivateKey for signing and *rsa.PublicKey for validation type SigningMethodRSA struct { Name string Hash crypto.Hash @@ -44,7 +45,7 @@ func (m *SigningMethodRSA) Alg() string { } // Implements the Verify method from SigningMethod -// For this signing method, must be an rsa.PublicKey structure. +// For this signing method, must be an *rsa.PublicKey structure. func (m *SigningMethodRSA) Verify(signingString, signature string, key interface{}) error { var err error @@ -73,7 +74,7 @@ func (m *SigningMethodRSA) Verify(signingString, signature string, key interface } // Implements the Sign method from SigningMethod -// For this signing method, must be an rsa.PrivateKey structure. +// 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 diff --git a/github.com/dgrijalva/jwt-go/rsa_utils.go b/github.com/dgrijalva/jwt-go/rsa_utils.go index 213a90db..a5ababf9 100644 --- a/github.com/dgrijalva/jwt-go/rsa_utils.go +++ b/github.com/dgrijalva/jwt-go/rsa_utils.go @@ -39,6 +39,38 @@ func ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) { return pkey, nil } +// Parse PEM encoded PKCS1 or PKCS8 private key protected with password +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 +} + // Parse PEM encoded PKCS1 or PKCS8 public key func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) { var err error diff --git a/github.com/envoyproxy/go-control-plane/Makefile b/github.com/envoyproxy/go-control-plane/Makefile index f4acf2f1..6cecbeaf 100644 --- a/github.com/envoyproxy/go-control-plane/Makefile +++ b/github.com/envoyproxy/go-control-plane/Makefile @@ -94,7 +94,7 @@ integration.docker: docker #-- code generaion #----------------- -generate: $(BINDIR)/gogofast +generate: $(BINDIR)/gogofast $(BINDIR)/validate @echo "--> generating pb.go files" $(SHELL) build/generate_protos.sh @@ -152,3 +152,7 @@ tools.glide: $(BINDIR)/gogofast: vendor @echo "--> building $@" @go build -o $@ vendor/github.com/gogo/protobuf/protoc-gen-gogofast/main.go + +$(BINDIR)/validate: vendor + @echo "--> building $@" + @go build -o $@ vendor/github.com/lyft/protoc-gen-validate/main.go diff --git a/github.com/envoyproxy/go-control-plane/build/generate_protos.sh b/github.com/envoyproxy/go-control-plane/build/generate_protos.sh index 6f140078..7fe72d5d 100755 --- a/github.com/envoyproxy/go-control-plane/build/generate_protos.sh +++ b/github.com/envoyproxy/go-control-plane/build/generate_protos.sh @@ -72,6 +72,7 @@ do then echo "Generating protos ${path} ..." $protoc ${protocarg} ${path}/*.proto \ - --plugin=protoc-gen-gogofast=${root}/bin/gogofast --gogofast_out=${gogoarg}:. + --plugin=protoc-gen-gogofast=${root}/bin/gogofast --gogofast_out=${gogoarg}:. \ + --plugin=protoc-gen-validate=${root}/bin/validate --validate_out="lang=gogo:." fi done diff --git a/github.com/envoyproxy/go-control-plane/envoy/admin/v2/config_dump.pb.go b/github.com/envoyproxy/go-control-plane/envoy/admin/v2/config_dump.pb.go new file mode 100644 index 00000000..c415d90f --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/admin/v2/config_dump.pb.go @@ -0,0 +1,650 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: envoy/admin/v2/config_dump.proto + +/* + Package envoy_admin_v2 is a generated protocol buffer package. + + It is generated from these files: + envoy/admin/v2/config_dump.proto + + It has these top-level messages: + ConfigDump + RouteConfigDump +*/ +package envoy_admin_v2 + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" +import google_protobuf "github.com/gogo/protobuf/types" +import envoy_api_v21 "github.com/envoyproxy/go-control-plane/envoy/api/v2" +import _ "github.com/gogo/protobuf/gogoproto" + +import io "io" + +// 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.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +// The /config_dump admin endpoint uses this wrapper message to maintain and serve arbitrary +// configuration information from any component in Envoy. +// TODO(jsedgwick) In the future, we may want to formalize this further with an RPC for config_dump, +// and perhaps even with an RPC per config type. That strategy across all endpoints will allow for +// more flexibility w.r.t. protocol, serialization, parameters, etc. +type ConfigDump struct { + // This map is serialized and dumped in its entirety at the /config_dump endpoint. + // + // Keys should be a short descriptor of the config object they map to. For example, envoy's HTTP + // routing subsystem might use "routes" as the key for its config, for which it uses the message + // RouteConfigDump as defined below. In the future, the key will also be used to filter the output + // of the /config_dump endpoint. + Configs map[string]google_protobuf.Any `protobuf:"bytes,1,rep,name=configs" json:"configs" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *ConfigDump) Reset() { *m = ConfigDump{} } +func (m *ConfigDump) String() string { return proto.CompactTextString(m) } +func (*ConfigDump) ProtoMessage() {} +func (*ConfigDump) Descriptor() ([]byte, []int) { return fileDescriptorConfigDump, []int{0} } + +func (m *ConfigDump) GetConfigs() map[string]google_protobuf.Any { + if m != nil { + return m.Configs + } + return nil +} + +// Envoy's RDS implementation fills this message with all currently loaded routes, as described by +// their RouteConnfiguration objects. Static routes configured in the bootstrap configuration are +// separated from those configured dynamically via RDS. This message is available at the +// /config_dump admin endpoint. +type RouteConfigDump struct { + StaticRouteConfigs []envoy_api_v21.RouteConfiguration `protobuf:"bytes,1,rep,name=static_route_configs,json=staticRouteConfigs" json:"static_route_configs"` + DynamicRouteConfigs []envoy_api_v21.RouteConfiguration `protobuf:"bytes,2,rep,name=dynamic_route_configs,json=dynamicRouteConfigs" json:"dynamic_route_configs"` +} + +func (m *RouteConfigDump) Reset() { *m = RouteConfigDump{} } +func (m *RouteConfigDump) String() string { return proto.CompactTextString(m) } +func (*RouteConfigDump) ProtoMessage() {} +func (*RouteConfigDump) Descriptor() ([]byte, []int) { return fileDescriptorConfigDump, []int{1} } + +func (m *RouteConfigDump) GetStaticRouteConfigs() []envoy_api_v21.RouteConfiguration { + if m != nil { + return m.StaticRouteConfigs + } + return nil +} + +func (m *RouteConfigDump) GetDynamicRouteConfigs() []envoy_api_v21.RouteConfiguration { + if m != nil { + return m.DynamicRouteConfigs + } + return nil +} + +func init() { + proto.RegisterType((*ConfigDump)(nil), "envoy.admin.v2.ConfigDump") + proto.RegisterType((*RouteConfigDump)(nil), "envoy.admin.v2.RouteConfigDump") +} +func (m *ConfigDump) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConfigDump) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Configs) > 0 { + for k, _ := range m.Configs { + dAtA[i] = 0xa + i++ + v := m.Configs[k] + msgSize := 0 + if (&v) != nil { + msgSize = (&v).Size() + msgSize += 1 + sovConfigDump(uint64(msgSize)) + } + mapSize := 1 + len(k) + sovConfigDump(uint64(len(k))) + msgSize + i = encodeVarintConfigDump(dAtA, i, uint64(mapSize)) + dAtA[i] = 0xa + i++ + i = encodeVarintConfigDump(dAtA, i, uint64(len(k))) + i += copy(dAtA[i:], k) + dAtA[i] = 0x12 + i++ + i = encodeVarintConfigDump(dAtA, i, uint64((&v).Size())) + n1, err := (&v).MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n1 + } + } + return i, nil +} + +func (m *RouteConfigDump) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RouteConfigDump) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.StaticRouteConfigs) > 0 { + for _, msg := range m.StaticRouteConfigs { + dAtA[i] = 0xa + i++ + i = encodeVarintConfigDump(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.DynamicRouteConfigs) > 0 { + for _, msg := range m.DynamicRouteConfigs { + dAtA[i] = 0x12 + i++ + i = encodeVarintConfigDump(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func encodeVarintConfigDump(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *ConfigDump) Size() (n int) { + var l int + _ = l + if len(m.Configs) > 0 { + for k, v := range m.Configs { + _ = k + _ = v + l = v.Size() + mapEntrySize := 1 + len(k) + sovConfigDump(uint64(len(k))) + 1 + l + sovConfigDump(uint64(l)) + n += mapEntrySize + 1 + sovConfigDump(uint64(mapEntrySize)) + } + } + return n +} + +func (m *RouteConfigDump) Size() (n int) { + var l int + _ = l + if len(m.StaticRouteConfigs) > 0 { + for _, e := range m.StaticRouteConfigs { + l = e.Size() + n += 1 + l + sovConfigDump(uint64(l)) + } + } + if len(m.DynamicRouteConfigs) > 0 { + for _, e := range m.DynamicRouteConfigs { + l = e.Size() + n += 1 + l + sovConfigDump(uint64(l)) + } + } + return n +} + +func sovConfigDump(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozConfigDump(x uint64) (n int) { + return sovConfigDump(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ConfigDump) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfigDump + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConfigDump: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConfigDump: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Configs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfigDump + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthConfigDump + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Configs == nil { + m.Configs = make(map[string]google_protobuf.Any) + } + var mapkey string + mapvalue := &google_protobuf.Any{} + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfigDump + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfigDump + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthConfigDump + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfigDump + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return ErrInvalidLengthConfigDump + } + postmsgIndex := iNdEx + mapmsglen + if mapmsglen < 0 { + return ErrInvalidLengthConfigDump + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue = &google_protobuf.Any{} + if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + } else { + iNdEx = entryPreIndex + skippy, err := skipConfigDump(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthConfigDump + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Configs[mapkey] = *mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipConfigDump(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthConfigDump + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RouteConfigDump) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfigDump + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RouteConfigDump: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RouteConfigDump: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StaticRouteConfigs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfigDump + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthConfigDump + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StaticRouteConfigs = append(m.StaticRouteConfigs, envoy_api_v21.RouteConfiguration{}) + if err := m.StaticRouteConfigs[len(m.StaticRouteConfigs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DynamicRouteConfigs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfigDump + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthConfigDump + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DynamicRouteConfigs = append(m.DynamicRouteConfigs, envoy_api_v21.RouteConfiguration{}) + if err := m.DynamicRouteConfigs[len(m.DynamicRouteConfigs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipConfigDump(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthConfigDump + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipConfigDump(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowConfigDump + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowConfigDump + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowConfigDump + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthConfigDump + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowConfigDump + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipConfigDump(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthConfigDump = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowConfigDump = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("envoy/admin/v2/config_dump.proto", fileDescriptorConfigDump) } + +var fileDescriptorConfigDump = []byte{ + // 311 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x8f, 0xb1, 0x4e, 0xf3, 0x30, + 0x14, 0x85, 0x7f, 0xb7, 0x3f, 0x20, 0xdc, 0x0a, 0x90, 0x29, 0xa8, 0x64, 0x08, 0x51, 0x17, 0x22, + 0x06, 0x5b, 0x0a, 0x0b, 0x62, 0xa3, 0x80, 0x58, 0x51, 0x26, 0xc4, 0x12, 0xb9, 0x4d, 0x1a, 0x59, + 0x34, 0x76, 0x94, 0xd8, 0x91, 0xfc, 0x44, 0x3c, 0x0a, 0x1d, 0x79, 0x02, 0x84, 0xf2, 0x24, 0x28, + 0x76, 0x22, 0x52, 0x31, 0xb1, 0x1d, 0xdd, 0x73, 0xee, 0x77, 0xcf, 0x85, 0x5e, 0xc2, 0x2b, 0xa1, + 0x09, 0x8d, 0x33, 0xc6, 0x49, 0x15, 0x90, 0xa5, 0xe0, 0x2b, 0x96, 0x46, 0xb1, 0xca, 0x72, 0x9c, + 0x17, 0x42, 0x0a, 0x74, 0x60, 0x12, 0xd8, 0x24, 0x70, 0x15, 0x38, 0x67, 0xa9, 0x10, 0xe9, 0x3a, + 0x21, 0xc6, 0x5d, 0xa8, 0x15, 0xa1, 0x5c, 0xdb, 0xa8, 0x73, 0xda, 0xc2, 0x72, 0xd6, 0xa0, 0x8a, + 0xb8, 0x6c, 0xe7, 0x93, 0x54, 0xa4, 0xc2, 0x48, 0xd2, 0x28, 0x3b, 0x9d, 0xbd, 0x01, 0x08, 0xef, + 0xcc, 0xb9, 0x7b, 0x95, 0xe5, 0xe8, 0x11, 0xee, 0xd9, 0xe3, 0xe5, 0x14, 0x78, 0x43, 0x7f, 0x14, + 0x5c, 0xe0, 0xed, 0xcb, 0xf8, 0x27, 0xdc, 0xca, 0xf2, 0x81, 0xcb, 0x42, 0xcf, 0xff, 0x6f, 0x3e, + 0xcf, 0xff, 0x85, 0xdd, 0xb6, 0xf3, 0x04, 0xc7, 0x7d, 0x1b, 0x1d, 0xc1, 0xe1, 0x6b, 0xa2, 0xa7, + 0xc0, 0x03, 0xfe, 0x7e, 0xd8, 0x48, 0x74, 0x09, 0x77, 0x2a, 0xba, 0x56, 0xc9, 0x74, 0xe0, 0x01, + 0x7f, 0x14, 0x4c, 0xb0, 0x7d, 0x09, 0x77, 0x2f, 0xe1, 0x5b, 0xae, 0x43, 0x1b, 0xb9, 0x19, 0x5c, + 0x83, 0xd9, 0x3b, 0x80, 0x87, 0xa1, 0x50, 0x32, 0xe9, 0xd5, 0x7d, 0x86, 0x93, 0x52, 0x52, 0xc9, + 0x96, 0x51, 0xd1, 0x38, 0xd1, 0x76, 0x77, 0xaf, 0xeb, 0x9e, 0xb3, 0xa6, 0x79, 0x6f, 0x59, 0x15, + 0x54, 0x32, 0xc1, 0xdb, 0xd2, 0xc8, 0x32, 0x7a, 0x7e, 0x89, 0x5e, 0xe0, 0x49, 0xac, 0x39, 0xcd, + 0x7e, 0xa1, 0x07, 0x7f, 0x42, 0x1f, 0xb7, 0x90, 0x3e, 0x7b, 0x3e, 0xde, 0xd4, 0x2e, 0xf8, 0xa8, + 0x5d, 0xf0, 0x55, 0xbb, 0x60, 0xb1, 0x6b, 0x1e, 0xbe, 0xfa, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x2a, + 0x10, 0xc8, 0xf0, 0x05, 0x02, 0x00, 0x00, +} diff --git a/github.com/envoyproxy/go-control-plane/envoy/admin/v2/config_dump.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/admin/v2/config_dump.pb.validate.go new file mode 100644 index 00000000..a394987f --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/admin/v2/config_dump.pb.validate.go @@ -0,0 +1,150 @@ +// Code generated by protoc-gen-validate +// source: envoy/admin/v2/config_dump.proto +// DO NOT EDIT!!! + +package envoy_admin_v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on ConfigDump with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *ConfigDump) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Configs + + return nil +} + +// ConfigDumpValidationError is the validation error returned by +// ConfigDump.Validate if the designated constraints aren't met. +type ConfigDumpValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ConfigDumpValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sConfigDump.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ConfigDumpValidationError{} + +// Validate checks the field values on RouteConfigDump with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *RouteConfigDump) Validate() error { + if m == nil { + return nil + } + + for idx, item := range m.GetStaticRouteConfigs() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteConfigDumpValidationError{ + Field: fmt.Sprintf("StaticRouteConfigs[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetDynamicRouteConfigs() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteConfigDumpValidationError{ + Field: fmt.Sprintf("DynamicRouteConfigs[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// RouteConfigDumpValidationError is the validation error returned by +// RouteConfigDump.Validate if the designated constraints aren't met. +type RouteConfigDumpValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RouteConfigDumpValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRouteConfigDump.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RouteConfigDumpValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/auth/auth.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/auth/auth.pb.validate.go new file mode 100644 index 00000000..448be5d5 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/auth/auth.pb.validate.go @@ -0,0 +1,341 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/auth/auth.proto +// DO NOT EDIT!!! + +package auth + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on AuthAction with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *AuthAction) Validate() error { + if m == nil { + return nil + } + + // no validation rules for ActionType + + for idx, item := range m.GetRules() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AuthActionValidationError{ + Field: fmt.Sprintf("Rules[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// AuthActionValidationError is the validation error returned by +// AuthAction.Validate if the designated constraints aren't met. +type AuthActionValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AuthActionValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAuthAction.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AuthActionValidationError{} + +// Validate checks the field values on AuthAction_AndRule with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *AuthAction_AndRule) Validate() error { + if m == nil { + return nil + } + + for idx, item := range m.GetRules() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AuthAction_AndRuleValidationError{ + Field: fmt.Sprintf("Rules[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// AuthAction_AndRuleValidationError is the validation error returned by +// AuthAction_AndRule.Validate if the designated constraints aren't met. +type AuthAction_AndRuleValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AuthAction_AndRuleValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAuthAction_AndRule.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AuthAction_AndRuleValidationError{} + +// Validate checks the field values on AuthAction_OrRule with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *AuthAction_OrRule) Validate() error { + if m == nil { + return nil + } + + for idx, item := range m.GetRules() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AuthAction_OrRuleValidationError{ + Field: fmt.Sprintf("Rules[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// AuthAction_OrRuleValidationError is the validation error returned by +// AuthAction_OrRule.Validate if the designated constraints aren't met. +type AuthAction_OrRuleValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AuthAction_OrRuleValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAuthAction_OrRule.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AuthAction_OrRuleValidationError{} + +// Validate checks the field values on AuthAction_X509Rule with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *AuthAction_X509Rule) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetValidationContext()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AuthAction_X509RuleValidationError{ + Field: "ValidationContext", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// AuthAction_X509RuleValidationError is the validation error returned by +// AuthAction_X509Rule.Validate if the designated constraints aren't met. +type AuthAction_X509RuleValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AuthAction_X509RuleValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAuthAction_X509Rule.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AuthAction_X509RuleValidationError{} + +// Validate checks the field values on AuthAction_Rule with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *AuthAction_Rule) Validate() error { + if m == nil { + return nil + } + + switch m.RuleSpecifier.(type) { + + case *AuthAction_Rule_AndRule: + + if v, ok := interface{}(m.GetAndRule()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AuthAction_RuleValidationError{ + Field: "AndRule", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *AuthAction_Rule_OrRule: + + if v, ok := interface{}(m.GetOrRule()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AuthAction_RuleValidationError{ + Field: "OrRule", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *AuthAction_Rule_X509Rule: + + if v, ok := interface{}(m.GetX509Rule()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AuthAction_RuleValidationError{ + Field: "X509Rule", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// AuthAction_RuleValidationError is the validation error returned by +// AuthAction_Rule.Validate if the designated constraints aren't met. +type AuthAction_RuleValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AuthAction_RuleValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAuthAction_Rule.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AuthAction_RuleValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/auth/cert.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/auth/cert.pb.validate.go new file mode 100644 index 00000000..accfe7fd --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/auth/cert.pb.validate.go @@ -0,0 +1,768 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/auth/cert.proto +// DO NOT EDIT!!! + +package auth + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on TlsParameters with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *TlsParameters) Validate() error { + if m == nil { + return nil + } + + if _, ok := TlsParameters_TlsProtocol_name[int32(m.GetTlsMinimumProtocolVersion())]; !ok { + return TlsParametersValidationError{ + Field: "TlsMinimumProtocolVersion", + Reason: "value must be one of the defined enum values", + } + } + + if _, ok := TlsParameters_TlsProtocol_name[int32(m.GetTlsMaximumProtocolVersion())]; !ok { + return TlsParametersValidationError{ + Field: "TlsMaximumProtocolVersion", + Reason: "value must be one of the defined enum values", + } + } + + return nil +} + +// TlsParametersValidationError is the validation error returned by +// TlsParameters.Validate if the designated constraints aren't met. +type TlsParametersValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TlsParametersValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTlsParameters.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TlsParametersValidationError{} + +// Validate checks the field values on TlsCertificate with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *TlsCertificate) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetCertificateChain()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TlsCertificateValidationError{ + Field: "CertificateChain", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetPrivateKey()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TlsCertificateValidationError{ + Field: "PrivateKey", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetPassword()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TlsCertificateValidationError{ + Field: "Password", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetOcspStaple()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TlsCertificateValidationError{ + Field: "OcspStaple", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetSignedCertificateTimestamp() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TlsCertificateValidationError{ + Field: fmt.Sprintf("SignedCertificateTimestamp[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// TlsCertificateValidationError is the validation error returned by +// TlsCertificate.Validate if the designated constraints aren't met. +type TlsCertificateValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TlsCertificateValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTlsCertificate.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TlsCertificateValidationError{} + +// Validate checks the field values on TlsSessionTicketKeys with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *TlsSessionTicketKeys) Validate() error { + if m == nil { + return nil + } + + if len(m.GetKeys()) < 1 { + return TlsSessionTicketKeysValidationError{ + Field: "Keys", + Reason: "value must contain at least 1 item(s)", + } + } + + for idx, item := range m.GetKeys() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TlsSessionTicketKeysValidationError{ + Field: fmt.Sprintf("Keys[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// TlsSessionTicketKeysValidationError is the validation error returned by +// TlsSessionTicketKeys.Validate if the designated constraints aren't met. +type TlsSessionTicketKeysValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TlsSessionTicketKeysValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTlsSessionTicketKeys.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TlsSessionTicketKeysValidationError{} + +// Validate checks the field values on CertificateValidationContext with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *CertificateValidationContext) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetTrustedCa()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CertificateValidationContextValidationError{ + Field: "TrustedCa", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetRequireOcspStaple()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CertificateValidationContextValidationError{ + Field: "RequireOcspStaple", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetRequireSignedCertificateTimestamp()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CertificateValidationContextValidationError{ + Field: "RequireSignedCertificateTimestamp", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetCrl()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CertificateValidationContextValidationError{ + Field: "Crl", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// CertificateValidationContextValidationError is the validation error returned +// by CertificateValidationContext.Validate if the designated constraints +// aren't met. +type CertificateValidationContextValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e CertificateValidationContextValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCertificateValidationContext.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = CertificateValidationContextValidationError{} + +// Validate checks the field values on CommonTlsContext with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *CommonTlsContext) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetTlsParams()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CommonTlsContextValidationError{ + Field: "TlsParams", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if len(m.GetTlsCertificates()) > 1 { + return CommonTlsContextValidationError{ + Field: "TlsCertificates", + Reason: "value must contain no more than 1 item(s)", + } + } + + for idx, item := range m.GetTlsCertificates() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CommonTlsContextValidationError{ + Field: fmt.Sprintf("TlsCertificates[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetTlsCertificateSdsSecretConfigs() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CommonTlsContextValidationError{ + Field: fmt.Sprintf("TlsCertificateSdsSecretConfigs[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetValidationContext()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CommonTlsContextValidationError{ + Field: "ValidationContext", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetDeprecatedV1()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CommonTlsContextValidationError{ + Field: "DeprecatedV1", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// CommonTlsContextValidationError is the validation error returned by +// CommonTlsContext.Validate if the designated constraints aren't met. +type CommonTlsContextValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e CommonTlsContextValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCommonTlsContext.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = CommonTlsContextValidationError{} + +// Validate checks the field values on UpstreamTlsContext with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *UpstreamTlsContext) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetCommonTlsContext()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return UpstreamTlsContextValidationError{ + Field: "CommonTlsContext", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for Sni + + return nil +} + +// UpstreamTlsContextValidationError is the validation error returned by +// UpstreamTlsContext.Validate if the designated constraints aren't met. +type UpstreamTlsContextValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e UpstreamTlsContextValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sUpstreamTlsContext.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = UpstreamTlsContextValidationError{} + +// Validate checks the field values on DownstreamTlsContext with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *DownstreamTlsContext) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetCommonTlsContext()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return DownstreamTlsContextValidationError{ + Field: "CommonTlsContext", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetRequireClientCertificate()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return DownstreamTlsContextValidationError{ + Field: "RequireClientCertificate", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetRequireSni()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return DownstreamTlsContextValidationError{ + Field: "RequireSni", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + switch m.SessionTicketKeysType.(type) { + + case *DownstreamTlsContext_SessionTicketKeys: + + if v, ok := interface{}(m.GetSessionTicketKeys()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return DownstreamTlsContextValidationError{ + Field: "SessionTicketKeys", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *DownstreamTlsContext_SessionTicketKeysSdsSecretConfig: + + if v, ok := interface{}(m.GetSessionTicketKeysSdsSecretConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return DownstreamTlsContextValidationError{ + Field: "SessionTicketKeysSdsSecretConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// DownstreamTlsContextValidationError is the validation error returned by +// DownstreamTlsContext.Validate if the designated constraints aren't met. +type DownstreamTlsContextValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e DownstreamTlsContextValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDownstreamTlsContext.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = DownstreamTlsContextValidationError{} + +// Validate checks the field values on SdsSecretConfig with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *SdsSecretConfig) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Name + + if v, ok := interface{}(m.GetSdsConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return SdsSecretConfigValidationError{ + Field: "SdsConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// SdsSecretConfigValidationError is the validation error returned by +// SdsSecretConfig.Validate if the designated constraints aren't met. +type SdsSecretConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e SdsSecretConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sSdsSecretConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = SdsSecretConfigValidationError{} + +// Validate checks the field values on Secret with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Secret) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Name + + switch m.Type.(type) { + + case *Secret_TlsCertificate: + + if v, ok := interface{}(m.GetTlsCertificate()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return SecretValidationError{ + Field: "TlsCertificate", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *Secret_SessionTicketKeys: + + if v, ok := interface{}(m.GetSessionTicketKeys()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return SecretValidationError{ + Field: "SessionTicketKeys", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// SecretValidationError is the validation error returned by Secret.Validate if +// the designated constraints aren't met. +type SecretValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e SecretValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sSecret.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = SecretValidationError{} + +// Validate checks the field values on CommonTlsContext_DeprecatedV1 with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *CommonTlsContext_DeprecatedV1) Validate() error { + if m == nil { + return nil + } + + // no validation rules for AltAlpnProtocols + + return nil +} + +// CommonTlsContext_DeprecatedV1ValidationError is the validation error +// returned by CommonTlsContext_DeprecatedV1.Validate if the designated +// constraints aren't met. +type CommonTlsContext_DeprecatedV1ValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e CommonTlsContext_DeprecatedV1ValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCommonTlsContext_DeprecatedV1.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = CommonTlsContext_DeprecatedV1ValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/cds.pb.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/cds.pb.go index 0a7ddee0..1edfbc56 100644 --- a/github.com/envoyproxy/go-control-plane/envoy/api/v2/cds.pb.go +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/cds.pb.go @@ -841,6 +841,10 @@ type Cluster_CommonLbConfig struct { // .. note:: // The specified percent will be truncated to the nearest 1%. HealthyPanicThreshold *envoy_type.Percent `protobuf:"bytes,1,opt,name=healthy_panic_threshold,json=healthyPanicThreshold" json:"healthy_panic_threshold,omitempty"` + // Types that are valid to be assigned to LocalityConfigSpecifier: + // *Cluster_CommonLbConfig_ZoneAwareLbConfig_ + // *Cluster_CommonLbConfig_LocalityWeightedLbConfig_ + LocalityConfigSpecifier isCluster_CommonLbConfig_LocalityConfigSpecifier `protobuf_oneof:"locality_config_specifier"` } func (m *Cluster_CommonLbConfig) Reset() { *m = Cluster_CommonLbConfig{} } @@ -848,6 +852,31 @@ func (m *Cluster_CommonLbConfig) String() string { return proto.Compa func (*Cluster_CommonLbConfig) ProtoMessage() {} func (*Cluster_CommonLbConfig) Descriptor() ([]byte, []int) { return fileDescriptorCds, []int{0, 3} } +type isCluster_CommonLbConfig_LocalityConfigSpecifier interface { + isCluster_CommonLbConfig_LocalityConfigSpecifier() + Equal(interface{}) bool + MarshalTo([]byte) (int, error) + Size() int +} + +type Cluster_CommonLbConfig_ZoneAwareLbConfig_ struct { + ZoneAwareLbConfig *Cluster_CommonLbConfig_ZoneAwareLbConfig `protobuf:"bytes,2,opt,name=zone_aware_lb_config,json=zoneAwareLbConfig,oneof"` +} +type Cluster_CommonLbConfig_LocalityWeightedLbConfig_ struct { + LocalityWeightedLbConfig *Cluster_CommonLbConfig_LocalityWeightedLbConfig `protobuf:"bytes,3,opt,name=locality_weighted_lb_config,json=localityWeightedLbConfig,oneof"` +} + +func (*Cluster_CommonLbConfig_ZoneAwareLbConfig_) isCluster_CommonLbConfig_LocalityConfigSpecifier() {} +func (*Cluster_CommonLbConfig_LocalityWeightedLbConfig_) isCluster_CommonLbConfig_LocalityConfigSpecifier() { +} + +func (m *Cluster_CommonLbConfig) GetLocalityConfigSpecifier() isCluster_CommonLbConfig_LocalityConfigSpecifier { + if m != nil { + return m.LocalityConfigSpecifier + } + return nil +} + func (m *Cluster_CommonLbConfig) GetHealthyPanicThreshold() *envoy_type.Percent { if m != nil { return m.HealthyPanicThreshold @@ -855,6 +884,97 @@ func (m *Cluster_CommonLbConfig) GetHealthyPanicThreshold() *envoy_type.Percent return nil } +func (m *Cluster_CommonLbConfig) GetZoneAwareLbConfig() *Cluster_CommonLbConfig_ZoneAwareLbConfig { + if x, ok := m.GetLocalityConfigSpecifier().(*Cluster_CommonLbConfig_ZoneAwareLbConfig_); ok { + return x.ZoneAwareLbConfig + } + return nil +} + +func (m *Cluster_CommonLbConfig) GetLocalityWeightedLbConfig() *Cluster_CommonLbConfig_LocalityWeightedLbConfig { + if x, ok := m.GetLocalityConfigSpecifier().(*Cluster_CommonLbConfig_LocalityWeightedLbConfig_); ok { + return x.LocalityWeightedLbConfig + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*Cluster_CommonLbConfig) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _Cluster_CommonLbConfig_OneofMarshaler, _Cluster_CommonLbConfig_OneofUnmarshaler, _Cluster_CommonLbConfig_OneofSizer, []interface{}{ + (*Cluster_CommonLbConfig_ZoneAwareLbConfig_)(nil), + (*Cluster_CommonLbConfig_LocalityWeightedLbConfig_)(nil), + } +} + +func _Cluster_CommonLbConfig_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*Cluster_CommonLbConfig) + // locality_config_specifier + switch x := m.LocalityConfigSpecifier.(type) { + case *Cluster_CommonLbConfig_ZoneAwareLbConfig_: + _ = b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ZoneAwareLbConfig); err != nil { + return err + } + case *Cluster_CommonLbConfig_LocalityWeightedLbConfig_: + _ = b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.LocalityWeightedLbConfig); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("Cluster_CommonLbConfig.LocalityConfigSpecifier has unexpected type %T", x) + } + return nil +} + +func _Cluster_CommonLbConfig_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*Cluster_CommonLbConfig) + switch tag { + case 2: // locality_config_specifier.zone_aware_lb_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Cluster_CommonLbConfig_ZoneAwareLbConfig) + err := b.DecodeMessage(msg) + m.LocalityConfigSpecifier = &Cluster_CommonLbConfig_ZoneAwareLbConfig_{msg} + return true, err + case 3: // locality_config_specifier.locality_weighted_lb_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Cluster_CommonLbConfig_LocalityWeightedLbConfig) + err := b.DecodeMessage(msg) + m.LocalityConfigSpecifier = &Cluster_CommonLbConfig_LocalityWeightedLbConfig_{msg} + return true, err + default: + return false, nil + } +} + +func _Cluster_CommonLbConfig_OneofSizer(msg proto.Message) (n int) { + m := msg.(*Cluster_CommonLbConfig) + // locality_config_specifier + switch x := m.LocalityConfigSpecifier.(type) { + case *Cluster_CommonLbConfig_ZoneAwareLbConfig_: + s := proto.Size(x.ZoneAwareLbConfig) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Cluster_CommonLbConfig_LocalityWeightedLbConfig_: + s := proto.Size(x.LocalityWeightedLbConfig) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Configuration for :ref:`zone aware routing +// `. +// [#not-implemented-hide:] type Cluster_CommonLbConfig_ZoneAwareLbConfig struct { // [#not-implemented-hide:] // Configures percentage of requests that will be considered for zone aware routing @@ -894,6 +1014,23 @@ func (m *Cluster_CommonLbConfig_ZoneAwareLbConfig) GetMinClusterSize() *google_p return nil } +// Configuration for :ref:`locality weighted load balancing +// ` +// [#not-implemented-hide:] +type Cluster_CommonLbConfig_LocalityWeightedLbConfig struct { +} + +func (m *Cluster_CommonLbConfig_LocalityWeightedLbConfig) Reset() { + *m = Cluster_CommonLbConfig_LocalityWeightedLbConfig{} +} +func (m *Cluster_CommonLbConfig_LocalityWeightedLbConfig) String() string { + return proto.CompactTextString(m) +} +func (*Cluster_CommonLbConfig_LocalityWeightedLbConfig) ProtoMessage() {} +func (*Cluster_CommonLbConfig_LocalityWeightedLbConfig) Descriptor() ([]byte, []int) { + return fileDescriptorCds, []int{0, 3, 1} +} + // An extensible structure containing the address Envoy should bind to when // establishing upstream connections. type UpstreamBindConfig struct { @@ -922,6 +1059,7 @@ func init() { proto.RegisterType((*Cluster_RingHashLbConfig_DeprecatedV1)(nil), "envoy.api.v2.Cluster.RingHashLbConfig.DeprecatedV1") proto.RegisterType((*Cluster_CommonLbConfig)(nil), "envoy.api.v2.Cluster.CommonLbConfig") proto.RegisterType((*Cluster_CommonLbConfig_ZoneAwareLbConfig)(nil), "envoy.api.v2.Cluster.CommonLbConfig.ZoneAwareLbConfig") + proto.RegisterType((*Cluster_CommonLbConfig_LocalityWeightedLbConfig)(nil), "envoy.api.v2.Cluster.CommonLbConfig.LocalityWeightedLbConfig") proto.RegisterType((*UpstreamBindConfig)(nil), "envoy.api.v2.UpstreamBindConfig") proto.RegisterEnum("envoy.api.v2.Cluster_DiscoveryType", Cluster_DiscoveryType_name, Cluster_DiscoveryType_value) proto.RegisterEnum("envoy.api.v2.Cluster_LbPolicy", Cluster_LbPolicy_name, Cluster_LbPolicy_value) @@ -1300,6 +1438,75 @@ func (this *Cluster_CommonLbConfig) Equal(that interface{}) bool { if !this.HealthyPanicThreshold.Equal(that1.HealthyPanicThreshold) { return false } + if that1.LocalityConfigSpecifier == nil { + if this.LocalityConfigSpecifier != nil { + return false + } + } else if this.LocalityConfigSpecifier == nil { + return false + } else if !this.LocalityConfigSpecifier.Equal(that1.LocalityConfigSpecifier) { + return false + } + return true +} +func (this *Cluster_CommonLbConfig_ZoneAwareLbConfig_) Equal(that interface{}) bool { + if that == nil { + if this == nil { + return true + } + return false + } + + that1, ok := that.(*Cluster_CommonLbConfig_ZoneAwareLbConfig_) + if !ok { + that2, ok := that.(Cluster_CommonLbConfig_ZoneAwareLbConfig_) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + if this == nil { + return true + } + return false + } else if this == nil { + return false + } + if !this.ZoneAwareLbConfig.Equal(that1.ZoneAwareLbConfig) { + return false + } + return true +} +func (this *Cluster_CommonLbConfig_LocalityWeightedLbConfig_) Equal(that interface{}) bool { + if that == nil { + if this == nil { + return true + } + return false + } + + that1, ok := that.(*Cluster_CommonLbConfig_LocalityWeightedLbConfig_) + if !ok { + that2, ok := that.(Cluster_CommonLbConfig_LocalityWeightedLbConfig_) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + if this == nil { + return true + } + return false + } else if this == nil { + return false + } + if !this.LocalityWeightedLbConfig.Equal(that1.LocalityWeightedLbConfig) { + return false + } return true } func (this *Cluster_CommonLbConfig_ZoneAwareLbConfig) Equal(that interface{}) bool { @@ -1335,6 +1542,33 @@ func (this *Cluster_CommonLbConfig_ZoneAwareLbConfig) Equal(that interface{}) bo } return true } +func (this *Cluster_CommonLbConfig_LocalityWeightedLbConfig) Equal(that interface{}) bool { + if that == nil { + if this == nil { + return true + } + return false + } + + that1, ok := that.(*Cluster_CommonLbConfig_LocalityWeightedLbConfig) + if !ok { + that2, ok := that.(Cluster_CommonLbConfig_LocalityWeightedLbConfig) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + if this == nil { + return true + } + return false + } else if this == nil { + return false + } + return true +} func (this *UpstreamBindConfig) Equal(that interface{}) bool { if that == nil { if this == nil { @@ -2010,9 +2244,44 @@ func (m *Cluster_CommonLbConfig) MarshalTo(dAtA []byte) (int, error) { } i += n25 } + if m.LocalityConfigSpecifier != nil { + nn26, err := m.LocalityConfigSpecifier.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += nn26 + } return i, nil } +func (m *Cluster_CommonLbConfig_ZoneAwareLbConfig_) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.ZoneAwareLbConfig != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintCds(dAtA, i, uint64(m.ZoneAwareLbConfig.Size())) + n27, err := m.ZoneAwareLbConfig.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n27 + } + return i, nil +} +func (m *Cluster_CommonLbConfig_LocalityWeightedLbConfig_) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.LocalityWeightedLbConfig != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintCds(dAtA, i, uint64(m.LocalityWeightedLbConfig.Size())) + n28, err := m.LocalityWeightedLbConfig.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n28 + } + return i, nil +} func (m *Cluster_CommonLbConfig_ZoneAwareLbConfig) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -2032,22 +2301,40 @@ func (m *Cluster_CommonLbConfig_ZoneAwareLbConfig) MarshalTo(dAtA []byte) (int, dAtA[i] = 0xa i++ i = encodeVarintCds(dAtA, i, uint64(m.RoutingEnabled.Size())) - n26, err := m.RoutingEnabled.MarshalTo(dAtA[i:]) + n29, err := m.RoutingEnabled.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n26 + i += n29 } if m.MinClusterSize != nil { dAtA[i] = 0x12 i++ i = encodeVarintCds(dAtA, i, uint64(m.MinClusterSize.Size())) - n27, err := m.MinClusterSize.MarshalTo(dAtA[i:]) + n30, err := m.MinClusterSize.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n27 + i += n30 + } + return i, nil +} + +func (m *Cluster_CommonLbConfig_LocalityWeightedLbConfig) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err } + return dAtA[:n], nil +} + +func (m *Cluster_CommonLbConfig_LocalityWeightedLbConfig) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l return i, nil } @@ -2070,11 +2357,11 @@ func (m *UpstreamBindConfig) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintCds(dAtA, i, uint64(m.SourceAddress.Size())) - n28, err := m.SourceAddress.MarshalTo(dAtA[i:]) + n31, err := m.SourceAddress.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n28 + i += n31 } return i, nil } @@ -2286,9 +2573,30 @@ func (m *Cluster_CommonLbConfig) Size() (n int) { l = m.HealthyPanicThreshold.Size() n += 1 + l + sovCds(uint64(l)) } + if m.LocalityConfigSpecifier != nil { + n += m.LocalityConfigSpecifier.Size() + } return n } +func (m *Cluster_CommonLbConfig_ZoneAwareLbConfig_) Size() (n int) { + var l int + _ = l + if m.ZoneAwareLbConfig != nil { + l = m.ZoneAwareLbConfig.Size() + n += 1 + l + sovCds(uint64(l)) + } + return n +} +func (m *Cluster_CommonLbConfig_LocalityWeightedLbConfig_) Size() (n int) { + var l int + _ = l + if m.LocalityWeightedLbConfig != nil { + l = m.LocalityWeightedLbConfig.Size() + n += 1 + l + sovCds(uint64(l)) + } + return n +} func (m *Cluster_CommonLbConfig_ZoneAwareLbConfig) Size() (n int) { var l int _ = l @@ -2303,6 +2611,12 @@ func (m *Cluster_CommonLbConfig_ZoneAwareLbConfig) Size() (n int) { return n } +func (m *Cluster_CommonLbConfig_LocalityWeightedLbConfig) Size() (n int) { + var l int + _ = l + return n +} + func (m *UpstreamBindConfig) Size() (n int) { var l int _ = l @@ -3778,6 +4092,70 @@ func (m *Cluster_CommonLbConfig) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ZoneAwareLbConfig", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCds + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCds + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &Cluster_CommonLbConfig_ZoneAwareLbConfig{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.LocalityConfigSpecifier = &Cluster_CommonLbConfig_ZoneAwareLbConfig_{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LocalityWeightedLbConfig", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCds + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCds + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &Cluster_CommonLbConfig_LocalityWeightedLbConfig{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.LocalityConfigSpecifier = &Cluster_CommonLbConfig_LocalityWeightedLbConfig_{v} + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipCds(dAtA[iNdEx:]) @@ -3915,6 +4293,56 @@ func (m *Cluster_CommonLbConfig_ZoneAwareLbConfig) Unmarshal(dAtA []byte) error } return nil } +func (m *Cluster_CommonLbConfig_LocalityWeightedLbConfig) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCds + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LocalityWeightedLbConfig: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LocalityWeightedLbConfig: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipCds(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthCds + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *UpstreamBindConfig) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -4106,123 +4534,128 @@ var ( func init() { proto.RegisterFile("envoy/api/v2/cds.proto", fileDescriptorCds) } var fileDescriptorCds = []byte{ - // 1875 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x4f, 0x73, 0xdb, 0xc6, - 0x15, 0x17, 0x28, 0xda, 0x96, 0x9e, 0x44, 0x12, 0x5a, 0xd9, 0x16, 0x4c, 0xd9, 0xb2, 0xcc, 0xc6, - 0xa9, 0xc6, 0xd3, 0x21, 0x63, 0x3a, 0x49, 0x67, 0xd2, 0x4c, 0x3a, 0xfc, 0x27, 0x89, 0x09, 0x4d, - 0xaa, 0x00, 0x28, 0x4d, 0x9a, 0x7a, 0xb6, 0x4b, 0x60, 0x29, 0xa2, 0x02, 0x01, 0x14, 0xbb, 0x50, - 0xac, 0x1c, 0x73, 0xca, 0xbd, 0x97, 0xf6, 0xd0, 0x7b, 0xa7, 0x1f, 0xa1, 0xa7, 0x1e, 0x73, 0xec, - 0x4c, 0xcf, 0xfd, 0x33, 0x9e, 0xce, 0x74, 0xfa, 0x11, 0x7a, 0xeb, 0x60, 0xb1, 0xa0, 0x45, 0x0a, - 0x72, 0x9c, 0x99, 0x9e, 0x88, 0x7d, 0xef, 0xf7, 0x7e, 0xfb, 0xf6, 0xed, 0xdb, 0xb7, 0x6f, 0x09, - 0x77, 0xa9, 0x77, 0xee, 0x5f, 0xd4, 0x48, 0xe0, 0xd4, 0xce, 0xeb, 0x35, 0xcb, 0x66, 0xd5, 0x20, - 0xf4, 0xb9, 0x8f, 0xd6, 0x85, 0xbc, 0x4a, 0x02, 0xa7, 0x7a, 0x5e, 0x2f, 0x3f, 0x9c, 0x47, 0xf9, - 0x21, 0xad, 0x11, 0xdb, 0x0e, 0x29, 0x93, 0xf0, 0xf2, 0xfd, 0x39, 0x00, 0x89, 0xf8, 0xa4, 0x66, - 0xd1, 0x90, 0x67, 0x6a, 0x85, 0xf9, 0x88, 0x30, 0x2a, 0xb5, 0x8f, 0xaf, 0x6a, 0x2d, 0xdf, 0x1b, - 0x3b, 0xa7, 0x98, 0xf9, 0x51, 0x68, 0xd1, 0x4c, 0x12, 0xdb, 0x61, 0x96, 0x7f, 0x4e, 0xc3, 0x0b, - 0xa9, 0x7d, 0xe7, 0x2a, 0xc9, 0x84, 0x12, 0x97, 0x4f, 0xb0, 0x35, 0xa1, 0xd6, 0x99, 0x44, 0xed, - 0x5e, 0x45, 0x09, 0x85, 0xe5, 0xbb, 0x12, 0xf1, 0x64, 0x1e, 0xe1, 0x46, 0x8c, 0xd3, 0xb0, 0x66, - 0x39, 0xa1, 0x15, 0x39, 0x1c, 0x8f, 0x42, 0x4a, 0xce, 0x68, 0x28, 0xb1, 0x3f, 0xca, 0xc4, 0xfa, - 0x11, 0x77, 0x1d, 0x1a, 0x62, 0x9b, 0x72, 0x6a, 0x71, 0xc7, 0xf7, 0x24, 0x5a, 0x4b, 0xd0, 0xfc, - 0x22, 0xa0, 0xb5, 0x80, 0x86, 0x16, 0xf5, 0x66, 0xe1, 0x39, 0xf5, 0xfd, 0x53, 0x97, 0x0a, 0x22, - 0xe2, 0x79, 0x3e, 0x27, 0xb1, 0x59, 0x1a, 0xda, 0x1d, 0xa9, 0x15, 0xa3, 0x51, 0x34, 0xae, 0xd9, - 0x51, 0x48, 0x2e, 0xf1, 0xde, 0x5f, 0xd4, 0x33, 0x1e, 0x46, 0x16, 0xbf, 0xce, 0xfa, 0xcb, 0x90, - 0x04, 0x01, 0x0d, 0x53, 0xf6, 0xad, 0x73, 0xe2, 0x3a, 0x36, 0xe1, 0xb4, 0x96, 0x7e, 0x48, 0xc5, - 0xed, 0x53, 0xff, 0xd4, 0x17, 0x9f, 0xb5, 0xf8, 0x2b, 0x91, 0x56, 0xfe, 0xb6, 0x0d, 0xb7, 0x5a, - 0xc9, 0x42, 0xd1, 0x03, 0xc8, 0x7b, 0x64, 0x4a, 0x35, 0x65, 0x57, 0xd9, 0x5b, 0x6d, 0xae, 0xfe, - 0xe9, 0x3f, 0x7f, 0x5e, 0xce, 0x87, 0xb9, 0x5d, 0x45, 0x17, 0x62, 0xd4, 0x82, 0x7c, 0xbc, 0x56, - 0x2d, 0xb7, 0xab, 0xec, 0x15, 0xeb, 0x3f, 0xa8, 0x5e, 0x4e, 0xa8, 0xaa, 0xe4, 0xa8, 0xb6, 0xd3, - 0x6d, 0x34, 0x2f, 0x02, 0xda, 0x84, 0x98, 0xe3, 0xc6, 0xd7, 0x4a, 0x4e, 0x55, 0x74, 0x61, 0x8c, - 0x4c, 0x40, 0xd4, 0x66, 0x58, 0xc6, 0x16, 0x27, 0x79, 0xa1, 0x2d, 0xef, 0x2a, 0x7b, 0x6b, 0xf5, - 0x77, 0xb3, 0x29, 0x3b, 0x36, 0x93, 0x9f, 0x2d, 0x81, 0xd6, 0x55, 0xba, 0x20, 0x41, 0xc7, 0x50, - 0xb2, 0x7c, 0xcf, 0xa3, 0x16, 0xc7, 0xdc, 0x99, 0x52, 0x3f, 0xe2, 0x5a, 0x5e, 0x50, 0xde, 0xab, - 0x26, 0xe1, 0xaa, 0xa6, 0xe1, 0xaa, 0xb6, 0x65, 0xb0, 0x9b, 0xe8, 0xdb, 0xbf, 0x3f, 0x5c, 0xfa, - 0xed, 0x3f, 0x1e, 0x2a, 0xc2, 0xc7, 0x3f, 0x2a, 0xb9, 0x27, 0x4b, 0x7a, 0x51, 0xb2, 0x98, 0x09, - 0x09, 0x1a, 0xc3, 0xa3, 0x20, 0xf1, 0xd2, 0x4b, 0xb6, 0x1e, 0x8f, 0xa2, 0xf1, 0x98, 0x86, 0xd8, - 0x75, 0xa6, 0x71, 0xf6, 0x5c, 0x70, 0xca, 0xb4, 0x1b, 0x62, 0xa6, 0xfb, 0x57, 0x66, 0x1a, 0x76, - 0x3d, 0xfe, 0xac, 0x7e, 0x4c, 0xdc, 0x88, 0xea, 0x0f, 0x02, 0xe1, 0xab, 0x64, 0x69, 0x0a, 0x92, - 0x5e, 0xcc, 0xd1, 0x8c, 0x29, 0xd0, 0x01, 0xac, 0xba, 0x23, 0x1c, 0xf8, 0xae, 0x63, 0x5d, 0x68, - 0x37, 0x45, 0x7c, 0x77, 0xb2, 0x83, 0xd1, 0x1b, 0x1d, 0x09, 0xd4, 0x5c, 0x68, 0x57, 0x5c, 0x29, - 0x45, 0xef, 0xc1, 0x8d, 0x89, 0xcf, 0x38, 0xd3, 0x6e, 0xed, 0x2e, 0xef, 0xad, 0xd5, 0xcb, 0xf3, - 0x24, 0xf1, 0xf9, 0xa8, 0x36, 0x92, 0x73, 0xae, 0x27, 0x40, 0xd4, 0x82, 0xc2, 0xe5, 0x73, 0xc5, - 0xb4, 0x15, 0x61, 0xb9, 0x93, 0x61, 0x79, 0x28, 0x70, 0xad, 0x18, 0xa6, 0xaf, 0x4f, 0x5e, 0x0f, - 0x18, 0xfa, 0x02, 0xb6, 0xa7, 0xe4, 0x25, 0x0e, 0xe9, 0xaf, 0x23, 0xca, 0x38, 0xc3, 0xf3, 0x41, - 0xd3, 0x56, 0xdf, 0x22, 0x42, 0xda, 0x94, 0xbc, 0xd4, 0xa5, 0xfd, 0xd1, 0xe5, 0x60, 0xa1, 0x23, - 0x50, 0x17, 0x8e, 0x2b, 0xd3, 0x40, 0x30, 0x3e, 0x5e, 0x70, 0x52, 0xc6, 0xa8, 0x95, 0xa0, 0x9b, - 0x12, 0xac, 0x97, 0xac, 0x79, 0x01, 0xda, 0x87, 0x35, 0xee, 0xb2, 0xd8, 0x43, 0x4e, 0x5f, 0x72, - 0x6d, 0x2d, 0x8b, 0x2c, 0x2e, 0x79, 0xd5, 0x61, 0xc0, 0x78, 0x48, 0xc9, 0xd4, 0x74, 0x59, 0x2b, - 0x01, 0xeb, 0xc0, 0x67, 0xdf, 0xe8, 0x0b, 0xb8, 0x33, 0xe1, 0x3c, 0xc0, 0x69, 0xc9, 0xc1, 0x7e, - 0x20, 0x0e, 0xba, 0x56, 0x10, 0x8c, 0x3f, 0xcc, 0x8a, 0x21, 0xe7, 0xc1, 0xd3, 0x23, 0x89, 0x1f, - 0x24, 0x70, 0x7d, 0x33, 0x66, 0x59, 0x10, 0xa2, 0x17, 0x70, 0x37, 0x16, 0xd7, 0xaf, 0xb2, 0x17, - 0xdf, 0xc8, 0x5e, 0x5f, 0x64, 0xbf, 0x3d, 0xc9, 0x90, 0x22, 0x03, 0x54, 0xdb, 0x63, 0x38, 0xa4, - 0xe3, 0x90, 0xb2, 0x09, 0x0e, 0x09, 0xa7, 0x9a, 0xfa, 0x5d, 0x67, 0xa6, 0xb8, 0x78, 0x5e, 0x6c, - 0x8f, 0xe9, 0x09, 0x83, 0x4e, 0x38, 0x45, 0x2f, 0x60, 0x23, 0x26, 0x75, 0x7d, 0xff, 0x2c, 0x0a, - 0xf0, 0x98, 0x4c, 0x1d, 0xf7, 0x42, 0xdb, 0x10, 0xf9, 0xfc, 0xf8, 0x9a, 0x7a, 0xe1, 0xb1, 0x9e, - 0x40, 0xef, 0x0b, 0xf0, 0x5c, 0x5a, 0x97, 0xec, 0x79, 0x25, 0xfa, 0x29, 0x14, 0x12, 0x9f, 0x99, - 0xef, 0x9e, 0xc7, 0x69, 0x80, 0xbe, 0x33, 0xcb, 0xd7, 0x85, 0x87, 0x12, 0x8f, 0x0c, 0xd8, 0xb8, - 0x52, 0xcd, 0xb5, 0xcd, 0xac, 0xe2, 0x93, 0xe6, 0xd2, 0x20, 0x81, 0xb7, 0x53, 0xb4, 0xae, 0xfa, - 0x0b, 0x12, 0x64, 0x82, 0x6a, 0xb9, 0x94, 0x78, 0x51, 0x80, 0x1d, 0x8f, 0xd3, 0xf0, 0x9c, 0xb8, - 0xda, 0xed, 0xef, 0x1b, 0xc9, 0x92, 0xa4, 0xe8, 0x4a, 0x06, 0x34, 0x80, 0xdb, 0x91, 0xcc, 0x3e, - 0x3c, 0x72, 0x3c, 0x3b, 0x2d, 0x95, 0x77, 0x04, 0xf3, 0x83, 0x8c, 0x25, 0x37, 0x1d, 0xcf, 0x96, - 0x15, 0x12, 0xa5, 0xa6, 0xaf, 0x65, 0xa8, 0x0f, 0xaa, 0x3b, 0xc2, 0x2c, 0x1a, 0x31, 0xca, 0x53, - 0xb2, 0xbb, 0x82, 0xec, 0x9d, 0xeb, 0x4a, 0x8d, 0x21, 0xc0, 0x92, 0xb3, 0xe8, 0xce, 0x8d, 0xd1, - 0x09, 0x6c, 0x86, 0x8e, 0x77, 0x8a, 0x27, 0x84, 0x4d, 0xb0, 0x3b, 0x4a, 0x29, 0xb7, 0xde, 0x54, - 0xca, 0x75, 0xc7, 0x3b, 0x3d, 0x24, 0x6c, 0xd2, 0x1b, 0x25, 0x24, 0x87, 0x4b, 0xba, 0x1a, 0x2e, - 0xc8, 0xd0, 0x73, 0x50, 0x79, 0x48, 0x3c, 0x16, 0xf8, 0x21, 0xc7, 0xcc, 0xb7, 0xce, 0x28, 0xd7, - 0x34, 0xc1, 0x5a, 0xc9, 0x58, 0xb5, 0x99, 0x42, 0x0d, 0x81, 0xd4, 0x4b, 0x7c, 0x5e, 0x80, 0x7e, - 0x0c, 0x2b, 0x53, 0xca, 0x89, 0x4d, 0x38, 0xd1, 0xee, 0x09, 0x9a, 0xed, 0x0c, 0x9a, 0xe7, 0x12, - 0xa2, 0xcf, 0xc0, 0xe8, 0x05, 0xa0, 0xd9, 0xd1, 0x63, 0xd4, 0x95, 0xd9, 0x52, 0x16, 0xd9, 0x5c, - 0xcd, 0x5e, 0x9f, 0xfc, 0x4d, 0xcf, 0x9a, 0x91, 0x5a, 0xe9, 0x1b, 0xc1, 0xa2, 0x28, 0xde, 0x0f, - 0xcb, 0x9f, 0x4e, 0x7d, 0xef, 0x52, 0xf0, 0xb6, 0xdf, 0xb4, 0x1f, 0x2d, 0x81, 0x4e, 0xc3, 0x14, - 0xdf, 0x55, 0x97, 0xc7, 0xa8, 0x02, 0x05, 0xe2, 0x72, 0xcc, 0x38, 0xe1, 0x58, 0x5c, 0xe3, 0xf7, - 0xe3, 0x6b, 0x5c, 0x5f, 0x23, 0x2e, 0x37, 0x38, 0xe1, 0xfd, 0xf8, 0x0a, 0x3f, 0x85, 0xfb, 0x72, - 0xce, 0xec, 0xba, 0xf5, 0x20, 0xf3, 0x28, 0xa4, 0x95, 0x65, 0xb1, 0xb0, 0xdc, 0x4b, 0xb8, 0x32, - 0x54, 0xe5, 0x08, 0xd4, 0xc5, 0x6b, 0x1b, 0x7d, 0x02, 0x20, 0xae, 0xfe, 0x64, 0xa9, 0x8a, 0x98, - 0xea, 0x61, 0xc6, 0x54, 0x09, 0xdc, 0x10, 0xad, 0xa2, 0xbe, 0x1a, 0xdf, 0xf5, 0x89, 0xfd, 0x23, - 0x58, 0x67, 0x34, 0x3c, 0x77, 0x2c, 0x9a, 0xac, 0x2f, 0x97, 0xac, 0x4f, 0xca, 0xe2, 0xf5, 0x95, - 0x7f, 0xbf, 0x0c, 0xc5, 0xf9, 0xb4, 0x45, 0x01, 0x94, 0xc6, 0xc4, 0x75, 0x47, 0xc4, 0x3a, 0x4b, - 0x2f, 0x58, 0x45, 0x6c, 0xe1, 0x4f, 0xde, 0x26, 0xeb, 0x67, 0xc3, 0x7d, 0xc9, 0x91, 0x71, 0xfb, - 0x16, 0xc7, 0x73, 0x3a, 0xf4, 0x09, 0x14, 0x6d, 0x3a, 0x26, 0x51, 0xbc, 0x19, 0xc2, 0x56, 0x78, - 0xba, 0x56, 0xdf, 0xba, 0x52, 0x0d, 0x0c, 0xd1, 0xd8, 0xe9, 0x05, 0x09, 0x4f, 0x66, 0x42, 0xbf, - 0x04, 0x55, 0x9e, 0xd2, 0x24, 0xeb, 0xfc, 0x90, 0x69, 0xcb, 0xa2, 0xd0, 0x7d, 0xf0, 0xbd, 0x5c, - 0x36, 0xa4, 0xb5, 0x5e, 0x62, 0x73, 0x63, 0x56, 0x7e, 0x17, 0xd4, 0x45, 0x10, 0x42, 0x90, 0x3f, - 0xa3, 0x17, 0x4c, 0x53, 0x76, 0x97, 0xf7, 0x56, 0x75, 0xf1, 0x5d, 0x19, 0xc0, 0xdd, 0xec, 0xf5, - 0xa3, 0x12, 0xac, 0xf5, 0x07, 0x78, 0xbf, 0xd1, 0xeb, 0x35, 0x1b, 0xad, 0xcf, 0xd4, 0x25, 0xa4, - 0xc2, 0x7a, 0xa3, 0xff, 0x39, 0xee, 0xf4, 0xdb, 0x47, 0x83, 0x6e, 0xdf, 0x54, 0x15, 0x84, 0xa0, - 0xd8, 0xee, 0xec, 0x37, 0x86, 0x3d, 0x13, 0x1b, 0xc3, 0xa6, 0xd1, 0x31, 0xd5, 0x5c, 0xf9, 0x9b, - 0x1c, 0xa8, 0x8b, 0x35, 0x00, 0x1d, 0xc2, 0xc6, 0xd4, 0xf1, 0x9c, 0x69, 0x34, 0xc5, 0xa2, 0xa0, - 0x30, 0xe7, 0x2b, 0x2a, 0xd3, 0x23, 0xbb, 0x65, 0xf8, 0xf0, 0xfd, 0xa4, 0x65, 0x28, 0x49, 0xb3, - 0x98, 0xd1, 0x70, 0xbe, 0xa2, 0xe8, 0x17, 0x50, 0xb0, 0x69, 0x10, 0x52, 0x8b, 0x70, 0x6a, 0xe3, - 0xf3, 0xa7, 0x32, 0xf0, 0xcf, 0xde, 0xae, 0x18, 0x55, 0xdb, 0x33, 0xdb, 0xe3, 0xa7, 0xcd, 0x9c, - 0xa6, 0xe8, 0xeb, 0xf6, 0x25, 0x49, 0xb9, 0x07, 0xeb, 0x97, 0x11, 0xe8, 0x63, 0x58, 0x8f, 0x18, - 0xc5, 0x8c, 0xdb, 0xa2, 0x06, 0x4a, 0x97, 0xcb, 0x57, 0x5c, 0x6e, 0xfa, 0xbe, 0x9b, 0x38, 0x0c, - 0x11, 0xa3, 0x06, 0xb7, 0xe3, 0x49, 0xcb, 0xff, 0x55, 0xa0, 0x38, 0x7f, 0xa2, 0xd1, 0x67, 0xb0, - 0x95, 0x74, 0x55, 0x17, 0x38, 0x20, 0x9e, 0x63, 0x61, 0x3e, 0x89, 0x6f, 0x56, 0xdf, 0xb5, 0x25, - 0xf7, 0xa6, 0x5c, 0x48, 0xdc, 0x49, 0x57, 0x8f, 0x92, 0x27, 0x87, 0x7e, 0x47, 0xda, 0x1c, 0xc5, - 0x26, 0x66, 0x6a, 0x51, 0xfe, 0x9d, 0x02, 0x1b, 0x3f, 0xf7, 0x3d, 0xda, 0xf8, 0x92, 0x84, 0x74, - 0x36, 0xc5, 0xc7, 0x50, 0x0a, 0xfd, 0x88, 0xc7, 0x61, 0xa6, 0x1e, 0x19, 0xb9, 0xf4, 0x8d, 0xd4, - 0x45, 0x89, 0xed, 0x24, 0x50, 0xb4, 0x0f, 0xea, 0xd4, 0xf1, 0x66, 0xcd, 0xbb, 0xd8, 0xa8, 0xdc, - 0x5b, 0x6c, 0x54, 0x71, 0xea, 0x78, 0x32, 0xea, 0xf1, 0x3e, 0x55, 0x4e, 0xa0, 0x30, 0xf7, 0x4e, - 0x40, 0x00, 0x37, 0x0d, 0xb3, 0x61, 0x76, 0x5b, 0xea, 0x12, 0x2a, 0x02, 0x18, 0xa6, 0xde, 0x6d, - 0x99, 0xb8, 0xdd, 0x37, 0x54, 0x25, 0x4e, 0xb5, 0xde, 0xe0, 0xa0, 0xdb, 0x6a, 0xf4, 0x84, 0x20, - 0x87, 0x6e, 0xc1, 0x72, 0xa7, 0x6d, 0xa8, 0xcb, 0x71, 0xce, 0x0d, 0xf4, 0xee, 0x41, 0xb7, 0x1f, - 0xab, 0x0c, 0x53, 0xcd, 0x57, 0x7e, 0x05, 0x2b, 0x69, 0x83, 0x1c, 0xdb, 0xe9, 0x83, 0x61, 0xbf, - 0x8d, 0xf5, 0x41, 0xb3, 0xdb, 0x57, 0x97, 0xd0, 0x06, 0x14, 0x7a, 0x9d, 0x86, 0x61, 0x62, 0xbd, - 0xf3, 0xb3, 0x61, 0xc7, 0x88, 0x73, 0xb4, 0x00, 0xab, 0x7a, 0xb7, 0x7f, 0x80, 0x0f, 0x1b, 0xc6, - 0xa1, 0x9a, 0x8b, 0xdd, 0xd0, 0x1b, 0xfd, 0xf6, 0xe0, 0xb9, 0xba, 0x8c, 0x36, 0xa1, 0x74, 0x99, - 0x1c, 0xf7, 0x9a, 0x6a, 0x3e, 0x06, 0x3c, 0x6f, 0x1c, 0xf4, 0x3a, 0xc7, 0xea, 0x8d, 0xca, 0x07, - 0x50, 0x5a, 0x68, 0x5e, 0xd0, 0x0a, 0xe4, 0x1b, 0x43, 0x73, 0xa0, 0x2e, 0xa1, 0x35, 0xb8, 0x75, - 0xfc, 0x3e, 0x1e, 0xf4, 0x7b, 0x9f, 0xab, 0x8a, 0x18, 0x7c, 0x98, 0x0c, 0x72, 0x15, 0x13, 0xb4, - 0xeb, 0x6e, 0x09, 0xb4, 0x0d, 0x5b, 0x43, 0xa3, 0x83, 0x5b, 0x83, 0xfe, 0x7e, 0xf7, 0x60, 0xa8, - 0x77, 0xda, 0xf8, 0x48, 0x1f, 0x98, 0x83, 0xd6, 0xa0, 0xa7, 0x2e, 0xa5, 0xca, 0xf6, 0xe0, 0xa4, - 0x6f, 0x98, 0x7a, 0xa7, 0xf1, 0xfc, 0xb5, 0x52, 0x69, 0xae, 0x89, 0x07, 0x44, 0x52, 0x5a, 0x3f, - 0xcd, 0xaf, 0xac, 0xab, 0x85, 0x4f, 0xf3, 0x2b, 0x25, 0x55, 0xad, 0x9c, 0x00, 0x1a, 0x5e, 0xed, - 0x05, 0x1a, 0x50, 0x4c, 0x9e, 0xe2, 0x58, 0xbe, 0xfa, 0x67, 0xc9, 0x7b, 0x7d, 0x27, 0x55, 0x48, - 0x2c, 0xe4, 0xb0, 0xfe, 0x6f, 0x05, 0xb6, 0xe4, 0x42, 0x66, 0x7b, 0x69, 0x24, 0xa5, 0x18, 0x9d, - 0x40, 0xd1, 0x10, 0x53, 0x4a, 0x00, 0x43, 0x0b, 0xcf, 0x89, 0x99, 0x85, 0xec, 0xf8, 0xcb, 0x0f, - 0xaf, 0xd5, 0xb3, 0xc0, 0xf7, 0x18, 0xad, 0x2c, 0xed, 0x29, 0xef, 0x29, 0x88, 0x41, 0x61, 0x9f, - 0x72, 0x6b, 0xf2, 0xff, 0xe3, 0x7d, 0xf4, 0xf5, 0x5f, 0xff, 0xf5, 0x9b, 0xdc, 0x76, 0xe5, 0xee, - 0xdc, 0x7f, 0x10, 0x1f, 0xc9, 0x14, 0x67, 0x1f, 0x29, 0x4f, 0x9a, 0x9b, 0x7f, 0x78, 0xb5, 0xa3, - 0x7c, 0xfb, 0x6a, 0x47, 0xf9, 0xcb, 0xab, 0x1d, 0xe5, 0x9f, 0xaf, 0x76, 0x94, 0x6f, 0x14, 0x65, - 0x74, 0x53, 0x24, 0xfa, 0xb3, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xf5, 0xe3, 0x8a, 0x2c, 0x6f, - 0x11, 0x00, 0x00, + // 1959 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x4f, 0x6f, 0xdb, 0xc8, + 0x15, 0x37, 0x65, 0x25, 0xb1, 0x9f, 0x2d, 0x89, 0x1e, 0x27, 0x31, 0x23, 0x27, 0x8e, 0xa3, 0x6e, + 0xb6, 0x46, 0x50, 0xc8, 0x1b, 0x67, 0x37, 0x05, 0xb6, 0xdb, 0x2d, 0xf4, 0xcf, 0xb6, 0x76, 0x15, + 0xc9, 0x25, 0xe9, 0x18, 0xdb, 0x6d, 0x30, 0x1d, 0x91, 0x23, 0x8b, 0x35, 0x45, 0xb2, 0x9c, 0xa1, + 0x13, 0xe7, 0x50, 0xa0, 0x7b, 0xda, 0x7b, 0x2f, 0xed, 0x61, 0xef, 0x45, 0x3f, 0x42, 0x4f, 0x3d, + 0xee, 0xb1, 0x40, 0xef, 0x6d, 0x11, 0x14, 0x28, 0xfa, 0x2d, 0x0a, 0x0e, 0x87, 0x8a, 0xfe, 0xd0, + 0x59, 0x2f, 0xd0, 0x93, 0x38, 0xef, 0xfd, 0xde, 0x6f, 0xe6, 0xbd, 0x79, 0xef, 0xcd, 0x8c, 0xe0, + 0x36, 0xf5, 0xce, 0xfd, 0x8b, 0x5d, 0x12, 0x38, 0xbb, 0xe7, 0x7b, 0xbb, 0x96, 0xcd, 0xaa, 0x41, + 0xe8, 0x73, 0x1f, 0xad, 0x0a, 0x79, 0x95, 0x04, 0x4e, 0xf5, 0x7c, 0xaf, 0x7c, 0x7f, 0x1a, 0xe5, + 0x87, 0x74, 0x97, 0xd8, 0x76, 0x48, 0x99, 0x84, 0x97, 0xef, 0x4e, 0x01, 0x48, 0xc4, 0x87, 0xbb, + 0x16, 0x0d, 0x79, 0xa6, 0x56, 0x98, 0xf7, 0x09, 0xa3, 0x52, 0xfb, 0x70, 0x5e, 0x6b, 0xf9, 0xde, + 0xc0, 0x39, 0xc5, 0xcc, 0x8f, 0x42, 0x8b, 0x66, 0x92, 0xd8, 0x0e, 0xb3, 0xfc, 0x73, 0x1a, 0x5e, + 0x48, 0xed, 0x7b, 0xf3, 0x24, 0x43, 0x4a, 0x5c, 0x3e, 0xc4, 0xd6, 0x90, 0x5a, 0x67, 0x12, 0xb5, + 0x3d, 0x8f, 0x12, 0x0a, 0xcb, 0x77, 0x25, 0xe2, 0xd1, 0x34, 0xc2, 0x8d, 0x18, 0xa7, 0xe1, 0xae, + 0xe5, 0x84, 0x56, 0xe4, 0x70, 0xdc, 0x0f, 0x29, 0x39, 0xa3, 0xa1, 0xc4, 0xfe, 0x28, 0x13, 0xeb, + 0x47, 0xdc, 0x75, 0x68, 0x88, 0x6d, 0xca, 0xa9, 0xc5, 0x1d, 0xdf, 0x93, 0x68, 0x2d, 0x41, 0xf3, + 0x8b, 0x80, 0xee, 0x06, 0x34, 0xb4, 0xa8, 0x37, 0x0e, 0xcf, 0xa9, 0xef, 0x9f, 0xba, 0x54, 0x10, + 0x11, 0xcf, 0xf3, 0x39, 0x89, 0xcd, 0xd2, 0xd0, 0x6e, 0x49, 0xad, 0x18, 0xf5, 0xa3, 0xc1, 0xae, + 0x1d, 0x85, 0x64, 0x82, 0xf7, 0xee, 0xac, 0x9e, 0xf1, 0x30, 0xb2, 0xf8, 0x65, 0xd6, 0x2f, 0x43, + 0x12, 0x04, 0x34, 0x4c, 0xd9, 0x37, 0xce, 0x89, 0xeb, 0xd8, 0x84, 0xd3, 0xdd, 0xf4, 0x43, 0x2a, + 0x6e, 0x9e, 0xfa, 0xa7, 0xbe, 0xf8, 0xdc, 0x8d, 0xbf, 0x12, 0x69, 0xe5, 0x77, 0x5b, 0x70, 0xa3, + 0x91, 0x38, 0x8a, 0xee, 0x41, 0xde, 0x23, 0x23, 0xaa, 0x29, 0xdb, 0xca, 0xce, 0x72, 0x7d, 0xf9, + 0x2f, 0xff, 0xfd, 0xeb, 0x62, 0x3e, 0xcc, 0x6d, 0x2b, 0xba, 0x10, 0xa3, 0x06, 0xe4, 0x63, 0x5f, + 0xb5, 0xdc, 0xb6, 0xb2, 0x53, 0xdc, 0xfb, 0x41, 0x75, 0x32, 0xa1, 0xaa, 0x92, 0xa3, 0xda, 0x4c, + 0xb7, 0xd1, 0xbc, 0x08, 0x68, 0x1d, 0x62, 0x8e, 0x6b, 0x5f, 0x29, 0x39, 0x55, 0xd1, 0x85, 0x31, + 0x32, 0x01, 0x51, 0x9b, 0x61, 0x19, 0x5b, 0x9c, 0xe4, 0x85, 0xb6, 0xb8, 0xad, 0xec, 0xac, 0xec, + 0xbd, 0x9f, 0x4d, 0xd9, 0xb2, 0x99, 0xfc, 0x6c, 0x08, 0xb4, 0xae, 0xd2, 0x19, 0x09, 0x7a, 0x0e, + 0x25, 0xcb, 0xf7, 0x3c, 0x6a, 0x71, 0xcc, 0x9d, 0x11, 0xf5, 0x23, 0xae, 0xe5, 0x05, 0xe5, 0x9d, + 0x6a, 0x12, 0xae, 0x6a, 0x1a, 0xae, 0x6a, 0x53, 0x06, 0xbb, 0x8e, 0xbe, 0xfd, 0xc7, 0xfd, 0x85, + 0x3f, 0xfc, 0xf3, 0xbe, 0x22, 0xd6, 0xf8, 0x67, 0x25, 0xf7, 0x68, 0x41, 0x2f, 0x4a, 0x16, 0x33, + 0x21, 0x41, 0x03, 0x78, 0x10, 0x24, 0xab, 0xf4, 0x92, 0xad, 0xc7, 0xfd, 0x68, 0x30, 0xa0, 0x21, + 0x76, 0x9d, 0x51, 0x9c, 0x3d, 0x17, 0x9c, 0x32, 0xed, 0x9a, 0x98, 0xe9, 0xee, 0xdc, 0x4c, 0xc7, + 0x6d, 0x8f, 0x3f, 0xd9, 0x7b, 0x4e, 0xdc, 0x88, 0xea, 0xf7, 0x02, 0xb1, 0x56, 0xc9, 0x52, 0x17, + 0x24, 0x9d, 0x98, 0xa3, 0x1e, 0x53, 0xa0, 0x03, 0x58, 0x76, 0xfb, 0x38, 0xf0, 0x5d, 0xc7, 0xba, + 0xd0, 0xae, 0x8b, 0xf8, 0x6e, 0x65, 0x07, 0xa3, 0xd3, 0x3f, 0x12, 0xa8, 0xa9, 0xd0, 0x2e, 0xb9, + 0x52, 0x8a, 0x3e, 0x80, 0x6b, 0x43, 0x9f, 0x71, 0xa6, 0xdd, 0xd8, 0x5e, 0xdc, 0x59, 0xd9, 0x2b, + 0x4f, 0x93, 0xc4, 0xf5, 0x51, 0xad, 0x25, 0x75, 0xae, 0x27, 0x40, 0xd4, 0x80, 0xc2, 0x64, 0x5d, + 0x31, 0x6d, 0x49, 0x58, 0x6e, 0x65, 0x58, 0x1e, 0x0a, 0x5c, 0x23, 0x86, 0xe9, 0xab, 0xc3, 0xb7, + 0x03, 0x86, 0xbe, 0x84, 0xcd, 0x11, 0x79, 0x85, 0x43, 0xfa, 0x9b, 0x88, 0x32, 0xce, 0xf0, 0x74, + 0xd0, 0xb4, 0xe5, 0x2b, 0x44, 0x48, 0x1b, 0x91, 0x57, 0xba, 0xb4, 0x3f, 0x9a, 0x0c, 0x16, 0x3a, + 0x02, 0x75, 0xa6, 0x5c, 0x99, 0x06, 0x82, 0xf1, 0xe1, 0xcc, 0x22, 0x65, 0x8c, 0x1a, 0x09, 0xba, + 0x2e, 0xc1, 0x7a, 0xc9, 0x9a, 0x16, 0xa0, 0x7d, 0x58, 0xe1, 0x2e, 0x8b, 0x57, 0xc8, 0xe9, 0x2b, + 0xae, 0xad, 0x64, 0x91, 0xc5, 0x2d, 0xaf, 0x7a, 0x1c, 0x30, 0x1e, 0x52, 0x32, 0x32, 0x5d, 0xd6, + 0x48, 0xc0, 0x3a, 0xf0, 0xf1, 0x37, 0xfa, 0x12, 0x6e, 0x0d, 0x39, 0x0f, 0x70, 0xda, 0x72, 0xb0, + 0x1f, 0x88, 0x42, 0xd7, 0x0a, 0x82, 0xf1, 0x87, 0x59, 0x31, 0xe4, 0x3c, 0x78, 0x7c, 0x24, 0xf1, + 0xbd, 0x04, 0xae, 0xaf, 0xc7, 0x2c, 0x33, 0x42, 0xf4, 0x02, 0x6e, 0xc7, 0xe2, 0xbd, 0x79, 0xf6, + 0xe2, 0x3b, 0xd9, 0xf7, 0x66, 0xd9, 0x6f, 0x0e, 0x33, 0xa4, 0xc8, 0x00, 0xd5, 0xf6, 0x18, 0x0e, + 0xe9, 0x20, 0xa4, 0x6c, 0x88, 0x43, 0xc2, 0xa9, 0xa6, 0x7e, 0x57, 0xcd, 0x14, 0x67, 0xeb, 0xc5, + 0xf6, 0x98, 0x9e, 0x30, 0xe8, 0x84, 0x53, 0xf4, 0x02, 0xd6, 0x62, 0x52, 0xd7, 0xf7, 0xcf, 0xa2, + 0x00, 0x0f, 0xc8, 0xc8, 0x71, 0x2f, 0xb4, 0x35, 0x91, 0xcf, 0x0f, 0x2f, 0xe9, 0x17, 0x1e, 0xeb, + 0x08, 0xf4, 0xbe, 0x00, 0x4f, 0xa5, 0x75, 0xc9, 0x9e, 0x56, 0xa2, 0x9f, 0x41, 0x21, 0x59, 0x33, + 0xf3, 0xdd, 0xf3, 0x38, 0x0d, 0xd0, 0x77, 0x66, 0xf9, 0xaa, 0x58, 0xa1, 0xc4, 0x23, 0x03, 0xd6, + 0xe6, 0xba, 0xb9, 0xb6, 0x9e, 0xd5, 0x7c, 0xd2, 0x5c, 0xea, 0x25, 0xf0, 0x66, 0x8a, 0xd6, 0x55, + 0x7f, 0x46, 0x82, 0x4c, 0x50, 0x2d, 0x97, 0x12, 0x2f, 0x0a, 0xb0, 0xe3, 0x71, 0x1a, 0x9e, 0x13, + 0x57, 0xbb, 0xf9, 0x7d, 0x23, 0x59, 0x92, 0x14, 0x6d, 0xc9, 0x80, 0x7a, 0x70, 0x33, 0x92, 0xd9, + 0x87, 0xfb, 0x8e, 0x67, 0xa7, 0xad, 0xf2, 0x96, 0x60, 0xbe, 0x97, 0xe1, 0x72, 0xdd, 0xf1, 0x6c, + 0xd9, 0x21, 0x51, 0x6a, 0xfa, 0x56, 0x86, 0xba, 0xa0, 0xba, 0x7d, 0xcc, 0xa2, 0x3e, 0xa3, 0x3c, + 0x25, 0xbb, 0x2d, 0xc8, 0xde, 0xbb, 0xac, 0xd5, 0x18, 0x02, 0x2c, 0x39, 0x8b, 0xee, 0xd4, 0x18, + 0x9d, 0xc0, 0x7a, 0xe8, 0x78, 0xa7, 0x78, 0x48, 0xd8, 0x10, 0xbb, 0xfd, 0x94, 0x72, 0xe3, 0x5d, + 0xad, 0x5c, 0x77, 0xbc, 0xd3, 0x43, 0xc2, 0x86, 0x9d, 0x7e, 0x42, 0x72, 0xb8, 0xa0, 0xab, 0xe1, + 0x8c, 0x0c, 0x3d, 0x03, 0x95, 0x87, 0xc4, 0x63, 0x81, 0x1f, 0x72, 0xcc, 0x7c, 0xeb, 0x8c, 0x72, + 0x4d, 0x13, 0xac, 0x95, 0x0c, 0xaf, 0xcd, 0x14, 0x6a, 0x08, 0xa4, 0x5e, 0xe2, 0xd3, 0x02, 0xf4, + 0x63, 0x58, 0x1a, 0x51, 0x4e, 0x6c, 0xc2, 0x89, 0x76, 0x47, 0xd0, 0x6c, 0x66, 0xd0, 0x3c, 0x93, + 0x10, 0x7d, 0x0c, 0x46, 0x2f, 0x00, 0x8d, 0x4b, 0x8f, 0x51, 0x57, 0x66, 0x4b, 0x59, 0x64, 0x73, + 0x35, 0xdb, 0x3f, 0xf9, 0x9b, 0xd6, 0x9a, 0x91, 0x5a, 0xe9, 0x6b, 0xc1, 0xac, 0x28, 0xde, 0x0f, + 0xcb, 0x1f, 0x8d, 0x7c, 0x6f, 0x22, 0x78, 0x9b, 0xef, 0xda, 0x8f, 0x86, 0x40, 0xa7, 0x61, 0x8a, + 0xcf, 0xaa, 0xc9, 0x31, 0xaa, 0x40, 0x81, 0xb8, 0x1c, 0x33, 0x4e, 0x38, 0x16, 0xc7, 0xf8, 0xdd, + 0xf8, 0x18, 0xd7, 0x57, 0x88, 0xcb, 0x0d, 0x4e, 0x78, 0x37, 0x3e, 0xc2, 0x4f, 0xe1, 0xae, 0x9c, + 0x33, 0xbb, 0x6f, 0xdd, 0xcb, 0x2c, 0x85, 0xb4, 0xb3, 0xcc, 0x36, 0x96, 0x3b, 0x09, 0x57, 0x86, + 0xaa, 0x1c, 0x81, 0x3a, 0x7b, 0x6c, 0xa3, 0x4f, 0x01, 0xc4, 0xd1, 0x9f, 0xb8, 0xaa, 0x88, 0xa9, + 0xee, 0x67, 0x4c, 0x95, 0xc0, 0x0d, 0x71, 0x55, 0xd4, 0x97, 0xe3, 0xb3, 0x3e, 0xb1, 0x7f, 0x00, + 0xab, 0x8c, 0x86, 0xe7, 0x8e, 0x45, 0x13, 0xff, 0x72, 0x89, 0x7f, 0x52, 0x16, 0xfb, 0x57, 0xfe, + 0x66, 0x11, 0x8a, 0xd3, 0x69, 0x8b, 0x02, 0x28, 0x0d, 0x88, 0xeb, 0xf6, 0x89, 0x75, 0x96, 0x1e, + 0xb0, 0x8a, 0xd8, 0xc2, 0x9f, 0x5c, 0x25, 0xeb, 0xc7, 0xc3, 0x7d, 0xc9, 0x91, 0x71, 0xfa, 0x16, + 0x07, 0x53, 0x3a, 0xf4, 0x29, 0x14, 0x6d, 0x3a, 0x20, 0x51, 0xbc, 0x19, 0xc2, 0x56, 0xac, 0x74, + 0x65, 0x6f, 0x63, 0xae, 0x1b, 0x18, 0xe2, 0x62, 0xa7, 0x17, 0x24, 0x3c, 0x99, 0x09, 0xfd, 0x0a, + 0x54, 0x59, 0xa5, 0x49, 0xd6, 0xf9, 0x21, 0xd3, 0x16, 0x45, 0xa3, 0xfb, 0xe8, 0x7b, 0x2d, 0xd9, + 0x90, 0xd6, 0x7a, 0x89, 0x4d, 0x8d, 0x59, 0xf9, 0x7d, 0x50, 0x67, 0x41, 0x08, 0x41, 0xfe, 0x8c, + 0x5e, 0x30, 0x4d, 0xd9, 0x5e, 0xdc, 0x59, 0xd6, 0xc5, 0x77, 0xa5, 0x07, 0xb7, 0xb3, 0xfd, 0x47, + 0x25, 0x58, 0xe9, 0xf6, 0xf0, 0x7e, 0xad, 0xd3, 0xa9, 0xd7, 0x1a, 0x9f, 0xab, 0x0b, 0x48, 0x85, + 0xd5, 0x5a, 0xf7, 0x0b, 0xdc, 0xea, 0x36, 0x8f, 0x7a, 0xed, 0xae, 0xa9, 0x2a, 0x08, 0x41, 0xb1, + 0xd9, 0xda, 0xaf, 0x1d, 0x77, 0x4c, 0x6c, 0x1c, 0xd7, 0x8d, 0x96, 0xa9, 0xe6, 0xca, 0x5f, 0xe7, + 0x40, 0x9d, 0xed, 0x01, 0xe8, 0x10, 0xd6, 0x46, 0x8e, 0xe7, 0x8c, 0xa2, 0x11, 0x16, 0x0d, 0x85, + 0x39, 0xaf, 0xa9, 0x4c, 0x8f, 0xec, 0x2b, 0xc3, 0xd3, 0x0f, 0x93, 0x2b, 0x43, 0x49, 0x9a, 0xc5, + 0x8c, 0x86, 0xf3, 0x9a, 0xa2, 0x5f, 0x42, 0xc1, 0xa6, 0x41, 0x48, 0x2d, 0xc2, 0xa9, 0x8d, 0xcf, + 0x1f, 0xcb, 0xc0, 0x3f, 0xb9, 0x5a, 0x33, 0xaa, 0x36, 0xc7, 0xb6, 0xcf, 0x1f, 0xd7, 0x73, 0x9a, + 0xa2, 0xaf, 0xda, 0x13, 0x92, 0x72, 0x07, 0x56, 0x27, 0x11, 0xe8, 0x13, 0x58, 0x8d, 0x18, 0xc5, + 0x8c, 0xdb, 0xa2, 0x07, 0xca, 0x25, 0x97, 0xe7, 0x96, 0x5c, 0xf7, 0x7d, 0x37, 0x59, 0x30, 0x44, + 0x8c, 0x1a, 0xdc, 0x8e, 0x27, 0x2d, 0x7f, 0x93, 0x87, 0xe2, 0x74, 0x45, 0xa3, 0xcf, 0x61, 0x23, + 0xb9, 0x55, 0x5d, 0xe0, 0x80, 0x78, 0x8e, 0x85, 0xf9, 0x30, 0x3e, 0x59, 0x7d, 0xd7, 0x96, 0xdc, + 0xeb, 0xd2, 0x91, 0xf8, 0x26, 0x5d, 0x3d, 0x4a, 0x9e, 0x1c, 0xfa, 0x2d, 0x69, 0x73, 0x14, 0x9b, + 0x98, 0xa9, 0x05, 0x72, 0xe0, 0xe6, 0x6b, 0xdf, 0xa3, 0x98, 0xbc, 0x24, 0x21, 0x9d, 0x68, 0x31, + 0x49, 0x48, 0x9e, 0x5e, 0xa5, 0xc5, 0x54, 0x7f, 0xe1, 0x7b, 0xb4, 0x16, 0xdb, 0x4f, 0xf4, 0xeb, + 0xb5, 0xd7, 0xb3, 0x42, 0xf4, 0x5b, 0xd8, 0x74, 0x7d, 0x8b, 0xb8, 0x0e, 0xbf, 0xc0, 0x2f, 0xa9, + 0x73, 0x3a, 0x8c, 0xa3, 0xff, 0x76, 0xc6, 0xe4, 0x72, 0xff, 0xd3, 0x2b, 0xcd, 0xd8, 0x91, 0x3c, + 0x27, 0x92, 0x66, 0x62, 0x62, 0xcd, 0xbd, 0x44, 0x57, 0xfe, 0xa3, 0x02, 0x6b, 0x73, 0x4b, 0x45, + 0x9f, 0x40, 0x29, 0xf4, 0x23, 0x1e, 0x67, 0x14, 0xf5, 0x48, 0xdf, 0xa5, 0xef, 0x8c, 0x62, 0x51, + 0x62, 0x5b, 0x09, 0x14, 0xed, 0x83, 0x3a, 0x72, 0xbc, 0xf1, 0x3b, 0x45, 0xe4, 0x64, 0xee, 0x0a, + 0x39, 0x59, 0x1c, 0x39, 0x9e, 0xf4, 0x2d, 0x4e, 0xc9, 0x72, 0x19, 0xb4, 0xcb, 0x7c, 0xaa, 0x6f, + 0xc2, 0x9d, 0x71, 0xdc, 0xd2, 0x07, 0x72, 0x40, 0x2d, 0x67, 0xe0, 0xd0, 0xb0, 0x72, 0x02, 0x85, + 0xa9, 0xb7, 0x14, 0x02, 0xb8, 0x6e, 0x98, 0x35, 0xb3, 0xdd, 0x50, 0x17, 0x50, 0x11, 0xc0, 0x30, + 0xf5, 0x76, 0xc3, 0xc4, 0xcd, 0xae, 0xa1, 0x2a, 0x71, 0x39, 0x76, 0x7a, 0x07, 0xed, 0x46, 0xad, + 0x23, 0x04, 0x39, 0x74, 0x03, 0x16, 0x5b, 0x4d, 0x43, 0x5d, 0x8c, 0xeb, 0xb2, 0xa7, 0xb7, 0x0f, + 0xda, 0xdd, 0x58, 0x65, 0x98, 0x6a, 0xbe, 0xf2, 0x6b, 0x58, 0x4a, 0x1f, 0x11, 0xb1, 0x9d, 0xde, + 0x3b, 0xee, 0x36, 0xb1, 0xde, 0xab, 0xb7, 0xbb, 0xea, 0x02, 0x5a, 0x83, 0x42, 0xa7, 0x55, 0x33, + 0x4c, 0xac, 0xb7, 0x7e, 0x7e, 0xdc, 0x32, 0xe2, 0x3a, 0x2e, 0xc0, 0xb2, 0xde, 0xee, 0x1e, 0xe0, + 0xc3, 0x9a, 0x71, 0xa8, 0xe6, 0xe2, 0x65, 0xe8, 0xb5, 0x6e, 0xb3, 0xf7, 0x4c, 0x5d, 0x44, 0xeb, + 0x50, 0x9a, 0x24, 0xc7, 0x9d, 0xba, 0x9a, 0x8f, 0x01, 0xcf, 0x6a, 0x07, 0x9d, 0xd6, 0x73, 0xf5, + 0x5a, 0xe5, 0x23, 0x28, 0xcd, 0x5c, 0xf0, 0xd0, 0x12, 0xe4, 0x6b, 0xc7, 0x66, 0x4f, 0x5d, 0x40, + 0x2b, 0x70, 0xe3, 0xf9, 0x87, 0xb8, 0xd7, 0xed, 0x7c, 0xa1, 0x2a, 0x62, 0xf0, 0x34, 0x19, 0xe4, + 0x2a, 0x26, 0x68, 0x97, 0x9d, 0xa4, 0x68, 0x13, 0x36, 0x8e, 0x8d, 0x16, 0x6e, 0xf4, 0xba, 0xfb, + 0xed, 0x83, 0x63, 0xbd, 0xd5, 0xc4, 0x47, 0x7a, 0xcf, 0xec, 0x35, 0x7a, 0x1d, 0x75, 0x21, 0x55, + 0x36, 0x7b, 0x27, 0x5d, 0xc3, 0xd4, 0x5b, 0xb5, 0x67, 0x6f, 0x95, 0x4a, 0x7d, 0x45, 0x3c, 0xb2, + 0x92, 0x40, 0x7f, 0x96, 0x5f, 0x5a, 0x55, 0x0b, 0x9f, 0xe5, 0x97, 0x4a, 0xaa, 0x5a, 0x39, 0x01, + 0x74, 0x3c, 0x7f, 0x5f, 0xaa, 0x41, 0x31, 0xf9, 0xbb, 0x02, 0xcb, 0x7f, 0x46, 0xc6, 0x05, 0x7e, + 0xf9, 0x6d, 0xb3, 0x90, 0x58, 0xc8, 0xe1, 0xde, 0x7f, 0x14, 0xd8, 0x90, 0x8e, 0x8c, 0xf7, 0xd2, + 0x48, 0x8e, 0x2b, 0x74, 0x02, 0x45, 0x43, 0x4c, 0x29, 0x01, 0x0c, 0xcd, 0x3c, 0xb9, 0xc6, 0x16, + 0xf2, 0x55, 0x54, 0xbe, 0x7f, 0xa9, 0x9e, 0x05, 0xbe, 0xc7, 0x68, 0x65, 0x61, 0x47, 0xf9, 0x40, + 0x41, 0x0c, 0x0a, 0xfb, 0x94, 0x5b, 0xc3, 0xff, 0x1f, 0xef, 0x83, 0xaf, 0xfe, 0xfe, 0xef, 0xdf, + 0xe7, 0x36, 0x2b, 0xb7, 0xa7, 0xfe, 0xa7, 0xf9, 0x58, 0xd6, 0x06, 0xfb, 0x58, 0x79, 0x54, 0x5f, + 0xff, 0xd3, 0x9b, 0x2d, 0xe5, 0xdb, 0x37, 0x5b, 0xca, 0xdf, 0xde, 0x6c, 0x29, 0xff, 0x7a, 0xb3, + 0xa5, 0x7c, 0xad, 0x28, 0xfd, 0xeb, 0xa2, 0x42, 0x9e, 0xfc, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x9f, + 0xca, 0x29, 0x6d, 0x93, 0x12, 0x00, 0x00, } diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/cds.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/cds.pb.validate.go new file mode 100644 index 00000000..60c73cf2 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/cds.pb.validate.go @@ -0,0 +1,877 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/cds.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Cluster with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Cluster) Validate() error { + if m == nil { + return nil + } + + if len(m.GetName()) < 1 { + return ClusterValidationError{ + Field: "Name", + Reason: "value length must be at least 1 bytes", + } + } + + // no validation rules for AltStatName + + if _, ok := Cluster_DiscoveryType_name[int32(m.GetType())]; !ok { + return ClusterValidationError{ + Field: "Type", + Reason: "value must be one of the defined enum values", + } + } + + if v, ok := interface{}(m.GetEdsClusterConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "EdsClusterConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if true { + dur := m.GetConnectTimeout() + + gt := time.Duration(0*time.Second + 0*time.Nanosecond) + + if dur <= gt { + return ClusterValidationError{ + Field: "ConnectTimeout", + Reason: "value must be greater than 0s", + } + } + + } + + if v, ok := interface{}(m.GetPerConnectionBufferLimitBytes()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "PerConnectionBufferLimitBytes", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if _, ok := Cluster_LbPolicy_name[int32(m.GetLbPolicy())]; !ok { + return ClusterValidationError{ + Field: "LbPolicy", + Reason: "value must be one of the defined enum values", + } + } + + for idx, item := range m.GetHosts() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: fmt.Sprintf("Hosts[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetHealthChecks() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: fmt.Sprintf("HealthChecks[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetMaxRequestsPerConnection()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "MaxRequestsPerConnection", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetCircuitBreakers()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "CircuitBreakers", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetTlsContext()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "TlsContext", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetCommonHttpProtocolOptions()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "CommonHttpProtocolOptions", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetHttpProtocolOptions()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "HttpProtocolOptions", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetHttp2ProtocolOptions()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "Http2ProtocolOptions", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if d := m.GetDnsRefreshRate(); d != nil { + dur := *d + + gt := time.Duration(0*time.Second + 0*time.Nanosecond) + + if dur <= gt { + return ClusterValidationError{ + Field: "DnsRefreshRate", + Reason: "value must be greater than 0s", + } + } + + } + + if _, ok := Cluster_DnsLookupFamily_name[int32(m.GetDnsLookupFamily())]; !ok { + return ClusterValidationError{ + Field: "DnsLookupFamily", + Reason: "value must be one of the defined enum values", + } + } + + for idx, item := range m.GetDnsResolvers() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: fmt.Sprintf("DnsResolvers[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetOutlierDetection()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "OutlierDetection", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if d := m.GetCleanupInterval(); d != nil { + dur := *d + + gt := time.Duration(0*time.Second + 0*time.Nanosecond) + + if dur <= gt { + return ClusterValidationError{ + Field: "CleanupInterval", + Reason: "value must be greater than 0s", + } + } + + } + + if v, ok := interface{}(m.GetUpstreamBindConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "UpstreamBindConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetLbSubsetConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "LbSubsetConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetCommonLbConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "CommonLbConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetTransportSocket()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "TransportSocket", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetMetadata()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "Metadata", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for ProtocolSelection + + switch m.LbConfig.(type) { + + case *Cluster_RingHashLbConfig_: + + if v, ok := interface{}(m.GetRingHashLbConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterValidationError{ + Field: "RingHashLbConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// ClusterValidationError is the validation error returned by Cluster.Validate +// if the designated constraints aren't met. +type ClusterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ClusterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCluster.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ClusterValidationError{} + +// Validate checks the field values on UpstreamBindConfig with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *UpstreamBindConfig) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetSourceAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return UpstreamBindConfigValidationError{ + Field: "SourceAddress", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// UpstreamBindConfigValidationError is the validation error returned by +// UpstreamBindConfig.Validate if the designated constraints aren't met. +type UpstreamBindConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e UpstreamBindConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sUpstreamBindConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = UpstreamBindConfigValidationError{} + +// Validate checks the field values on Cluster_EdsClusterConfig with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *Cluster_EdsClusterConfig) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetEdsConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Cluster_EdsClusterConfigValidationError{ + Field: "EdsConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for ServiceName + + return nil +} + +// Cluster_EdsClusterConfigValidationError is the validation error returned by +// Cluster_EdsClusterConfig.Validate if the designated constraints aren't met. +type Cluster_EdsClusterConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Cluster_EdsClusterConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCluster_EdsClusterConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Cluster_EdsClusterConfigValidationError{} + +// Validate checks the field values on Cluster_LbSubsetConfig with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *Cluster_LbSubsetConfig) Validate() error { + if m == nil { + return nil + } + + if _, ok := Cluster_LbSubsetConfig_LbSubsetFallbackPolicy_name[int32(m.GetFallbackPolicy())]; !ok { + return Cluster_LbSubsetConfigValidationError{ + Field: "FallbackPolicy", + Reason: "value must be one of the defined enum values", + } + } + + if v, ok := interface{}(m.GetDefaultSubset()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Cluster_LbSubsetConfigValidationError{ + Field: "DefaultSubset", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetSubsetSelectors() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Cluster_LbSubsetConfigValidationError{ + Field: fmt.Sprintf("SubsetSelectors[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// Cluster_LbSubsetConfigValidationError is the validation error returned by +// Cluster_LbSubsetConfig.Validate if the designated constraints aren't met. +type Cluster_LbSubsetConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Cluster_LbSubsetConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCluster_LbSubsetConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Cluster_LbSubsetConfigValidationError{} + +// Validate checks the field values on Cluster_RingHashLbConfig with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *Cluster_RingHashLbConfig) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetMinimumRingSize()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Cluster_RingHashLbConfigValidationError{ + Field: "MinimumRingSize", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetDeprecatedV1()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Cluster_RingHashLbConfigValidationError{ + Field: "DeprecatedV1", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// Cluster_RingHashLbConfigValidationError is the validation error returned by +// Cluster_RingHashLbConfig.Validate if the designated constraints aren't met. +type Cluster_RingHashLbConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Cluster_RingHashLbConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCluster_RingHashLbConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Cluster_RingHashLbConfigValidationError{} + +// Validate checks the field values on Cluster_CommonLbConfig with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *Cluster_CommonLbConfig) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetHealthyPanicThreshold()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Cluster_CommonLbConfigValidationError{ + Field: "HealthyPanicThreshold", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + switch m.LocalityConfigSpecifier.(type) { + + case *Cluster_CommonLbConfig_ZoneAwareLbConfig_: + + if v, ok := interface{}(m.GetZoneAwareLbConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Cluster_CommonLbConfigValidationError{ + Field: "ZoneAwareLbConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *Cluster_CommonLbConfig_LocalityWeightedLbConfig_: + + if v, ok := interface{}(m.GetLocalityWeightedLbConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Cluster_CommonLbConfigValidationError{ + Field: "LocalityWeightedLbConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// Cluster_CommonLbConfigValidationError is the validation error returned by +// Cluster_CommonLbConfig.Validate if the designated constraints aren't met. +type Cluster_CommonLbConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Cluster_CommonLbConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCluster_CommonLbConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Cluster_CommonLbConfigValidationError{} + +// Validate checks the field values on Cluster_LbSubsetConfig_LbSubsetSelector +// with the rules defined in the proto definition for this message. If any +// rules are violated, an error is returned. +func (m *Cluster_LbSubsetConfig_LbSubsetSelector) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// Cluster_LbSubsetConfig_LbSubsetSelectorValidationError is the validation +// error returned by Cluster_LbSubsetConfig_LbSubsetSelector.Validate if the +// designated constraints aren't met. +type Cluster_LbSubsetConfig_LbSubsetSelectorValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Cluster_LbSubsetConfig_LbSubsetSelectorValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCluster_LbSubsetConfig_LbSubsetSelector.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Cluster_LbSubsetConfig_LbSubsetSelectorValidationError{} + +// Validate checks the field values on Cluster_RingHashLbConfig_DeprecatedV1 +// with the rules defined in the proto definition for this message. If any +// rules are violated, an error is returned. +func (m *Cluster_RingHashLbConfig_DeprecatedV1) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetUseStdHash()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Cluster_RingHashLbConfig_DeprecatedV1ValidationError{ + Field: "UseStdHash", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// Cluster_RingHashLbConfig_DeprecatedV1ValidationError is the validation error +// returned by Cluster_RingHashLbConfig_DeprecatedV1.Validate if the +// designated constraints aren't met. +type Cluster_RingHashLbConfig_DeprecatedV1ValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Cluster_RingHashLbConfig_DeprecatedV1ValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCluster_RingHashLbConfig_DeprecatedV1.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Cluster_RingHashLbConfig_DeprecatedV1ValidationError{} + +// Validate checks the field values on Cluster_CommonLbConfig_ZoneAwareLbConfig +// with the rules defined in the proto definition for this message. If any +// rules are violated, an error is returned. +func (m *Cluster_CommonLbConfig_ZoneAwareLbConfig) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetRoutingEnabled()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Cluster_CommonLbConfig_ZoneAwareLbConfigValidationError{ + Field: "RoutingEnabled", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetMinClusterSize()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Cluster_CommonLbConfig_ZoneAwareLbConfigValidationError{ + Field: "MinClusterSize", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// Cluster_CommonLbConfig_ZoneAwareLbConfigValidationError is the validation +// error returned by Cluster_CommonLbConfig_ZoneAwareLbConfig.Validate if the +// designated constraints aren't met. +type Cluster_CommonLbConfig_ZoneAwareLbConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Cluster_CommonLbConfig_ZoneAwareLbConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCluster_CommonLbConfig_ZoneAwareLbConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Cluster_CommonLbConfig_ZoneAwareLbConfigValidationError{} + +// Validate checks the field values on +// Cluster_CommonLbConfig_LocalityWeightedLbConfig with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *Cluster_CommonLbConfig_LocalityWeightedLbConfig) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// Cluster_CommonLbConfig_LocalityWeightedLbConfigValidationError is the +// validation error returned by +// Cluster_CommonLbConfig_LocalityWeightedLbConfig.Validate if the designated +// constraints aren't met. +type Cluster_CommonLbConfig_LocalityWeightedLbConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Cluster_CommonLbConfig_LocalityWeightedLbConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCluster_CommonLbConfig_LocalityWeightedLbConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Cluster_CommonLbConfig_LocalityWeightedLbConfigValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster/circuit_breaker.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster/circuit_breaker.pb.validate.go new file mode 100644 index 00000000..20b3ac13 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster/circuit_breaker.pb.validate.go @@ -0,0 +1,176 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/cluster/circuit_breaker.proto +// DO NOT EDIT!!! + +package cluster + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on CircuitBreakers with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *CircuitBreakers) Validate() error { + if m == nil { + return nil + } + + for idx, item := range m.GetThresholds() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CircuitBreakersValidationError{ + Field: fmt.Sprintf("Thresholds[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// CircuitBreakersValidationError is the validation error returned by +// CircuitBreakers.Validate if the designated constraints aren't met. +type CircuitBreakersValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e CircuitBreakersValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCircuitBreakers.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = CircuitBreakersValidationError{} + +// Validate checks the field values on CircuitBreakers_Thresholds with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *CircuitBreakers_Thresholds) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Priority + + if v, ok := interface{}(m.GetMaxConnections()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CircuitBreakers_ThresholdsValidationError{ + Field: "MaxConnections", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetMaxPendingRequests()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CircuitBreakers_ThresholdsValidationError{ + Field: "MaxPendingRequests", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetMaxRequests()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CircuitBreakers_ThresholdsValidationError{ + Field: "MaxRequests", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetMaxRetries()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CircuitBreakers_ThresholdsValidationError{ + Field: "MaxRetries", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// CircuitBreakers_ThresholdsValidationError is the validation error returned +// by CircuitBreakers_Thresholds.Validate if the designated constraints aren't met. +type CircuitBreakers_ThresholdsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e CircuitBreakers_ThresholdsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCircuitBreakers_Thresholds.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = CircuitBreakers_ThresholdsValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster/outlier_detection.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster/outlier_detection.pb.validate.go new file mode 100644 index 00000000..5e9c820e --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster/outlier_detection.pb.validate.go @@ -0,0 +1,213 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/cluster/outlier_detection.proto +// DO NOT EDIT!!! + +package cluster + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on OutlierDetection with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *OutlierDetection) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetConsecutive_5Xx()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return OutlierDetectionValidationError{ + Field: "Consecutive_5Xx", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if d := m.GetInterval(); d != nil { + dur, err := types.DurationFromProto(d) + if err != nil { + return OutlierDetectionValidationError{ + Field: "Interval", + Reason: "value is not a valid duration", + Cause: err, + } + } + + gt := time.Duration(0*time.Second + 0*time.Nanosecond) + + if dur <= gt { + return OutlierDetectionValidationError{ + Field: "Interval", + Reason: "value must be greater than 0s", + } + } + + } + + if d := m.GetBaseEjectionTime(); d != nil { + dur, err := types.DurationFromProto(d) + if err != nil { + return OutlierDetectionValidationError{ + Field: "BaseEjectionTime", + Reason: "value is not a valid duration", + Cause: err, + } + } + + gt := time.Duration(0*time.Second + 0*time.Nanosecond) + + if dur <= gt { + return OutlierDetectionValidationError{ + Field: "BaseEjectionTime", + Reason: "value must be greater than 0s", + } + } + + } + + if wrapper := m.GetMaxEjectionPercent(); wrapper != nil { + + if wrapper.GetValue() > 100 { + return OutlierDetectionValidationError{ + Field: "MaxEjectionPercent", + Reason: "value must be less than or equal to 100", + } + } + + } + + if wrapper := m.GetEnforcingConsecutive_5Xx(); wrapper != nil { + + if wrapper.GetValue() > 100 { + return OutlierDetectionValidationError{ + Field: "EnforcingConsecutive_5Xx", + Reason: "value must be less than or equal to 100", + } + } + + } + + if wrapper := m.GetEnforcingSuccessRate(); wrapper != nil { + + if wrapper.GetValue() > 100 { + return OutlierDetectionValidationError{ + Field: "EnforcingSuccessRate", + Reason: "value must be less than or equal to 100", + } + } + + } + + if v, ok := interface{}(m.GetSuccessRateMinimumHosts()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return OutlierDetectionValidationError{ + Field: "SuccessRateMinimumHosts", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetSuccessRateRequestVolume()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return OutlierDetectionValidationError{ + Field: "SuccessRateRequestVolume", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetSuccessRateStdevFactor()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return OutlierDetectionValidationError{ + Field: "SuccessRateStdevFactor", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetConsecutiveGatewayFailure()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return OutlierDetectionValidationError{ + Field: "ConsecutiveGatewayFailure", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if wrapper := m.GetEnforcingConsecutiveGatewayFailure(); wrapper != nil { + + if wrapper.GetValue() > 100 { + return OutlierDetectionValidationError{ + Field: "EnforcingConsecutiveGatewayFailure", + Reason: "value must be less than or equal to 100", + } + } + + } + + return nil +} + +// OutlierDetectionValidationError is the validation error returned by +// OutlierDetection.Validate if the designated constraints aren't met. +type OutlierDetectionValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e OutlierDetectionValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sOutlierDetection.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = OutlierDetectionValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/address.pb.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/address.pb.go index 127689e4..5eff9c60 100644 --- a/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/address.pb.go +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/address.pb.go @@ -272,10 +272,14 @@ func _SocketAddress_OneofSizer(msg proto.Message) (n int) { type BindConfig struct { // The address to bind to when creating a socket. SourceAddress SocketAddress `protobuf:"bytes,1,opt,name=source_address,json=sourceAddress" json:"source_address"` - // [#not-implemented-hide:] Whether to set the IP_FREEBIND option when creating the socket. If - // set, allows the source_address specified to be an address that is not configured on the system - // running Envoy. Defaults to false. - Freebind bool `protobuf:"varint,2,opt,name=freebind,proto3" json:"freebind,omitempty"` + // [#not-implemented-hide:] Whether to set the *IP_FREEBIND* option when + // creating the socket. When this flag is set to true, allows the + // :ref:`source_address ` + // to be an IP address that is not configured on the system running Envoy. + // When this flag is set to false, the option *IP_FREEBIND* is disabled on the + // socket. When this flag is not set (default), the socket is not modified, + // i.e. the option is neither enabled nor disabled. + Freebind *google_protobuf.BoolValue `protobuf:"bytes,2,opt,name=freebind" json:"freebind,omitempty"` } func (m *BindConfig) Reset() { *m = BindConfig{} } @@ -290,11 +294,11 @@ func (m *BindConfig) GetSourceAddress() SocketAddress { return SocketAddress{} } -func (m *BindConfig) GetFreebind() bool { +func (m *BindConfig) GetFreebind() *google_protobuf.BoolValue { if m != nil { return m.Freebind } - return false + return nil } // Addresses specify either a logical or physical address and port, which are @@ -626,7 +630,7 @@ func (this *BindConfig) Equal(that interface{}) bool { if !this.SourceAddress.Equal(&that1.SourceAddress) { return false } - if this.Freebind != that1.Freebind { + if !this.Freebind.Equal(that1.Freebind) { return false } return true @@ -874,15 +878,15 @@ func (m *BindConfig) MarshalTo(dAtA []byte) (int, error) { return 0, err } i += n2 - if m.Freebind { - dAtA[i] = 0x10 + if m.Freebind != nil { + dAtA[i] = 0x12 i++ - if m.Freebind { - dAtA[i] = 1 - } else { - dAtA[i] = 0 + i = encodeVarintAddress(dAtA, i, uint64(m.Freebind.Size())) + n3, err := m.Freebind.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err } - i++ + i += n3 } return i, nil } @@ -903,11 +907,11 @@ func (m *Address) MarshalTo(dAtA []byte) (int, error) { var l int _ = l if m.Address != nil { - nn3, err := m.Address.MarshalTo(dAtA[i:]) + nn4, err := m.Address.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += nn3 + i += nn4 } return i, nil } @@ -918,11 +922,11 @@ func (m *Address_SocketAddress) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintAddress(dAtA, i, uint64(m.SocketAddress.Size())) - n4, err := m.SocketAddress.MarshalTo(dAtA[i:]) + n5, err := m.SocketAddress.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n4 + i += n5 } return i, nil } @@ -932,11 +936,11 @@ func (m *Address_Pipe) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintAddress(dAtA, i, uint64(m.Pipe.Size())) - n5, err := m.Pipe.MarshalTo(dAtA[i:]) + n6, err := m.Pipe.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n5 + i += n6 } return i, nil } @@ -965,11 +969,11 @@ func (m *CidrRange) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintAddress(dAtA, i, uint64(m.PrefixLen.Size())) - n6, err := m.PrefixLen.MarshalTo(dAtA[i:]) + n7, err := m.PrefixLen.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n6 + i += n7 } return i, nil } @@ -1034,8 +1038,9 @@ func (m *BindConfig) Size() (n int) { _ = l l = m.SourceAddress.Size() n += 1 + l + sovAddress(uint64(l)) - if m.Freebind { - n += 2 + if m.Freebind != nil { + l = m.Freebind.Size() + n += 1 + l + sovAddress(uint64(l)) } return n } @@ -1429,10 +1434,10 @@ func (m *BindConfig) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 2: - if wireType != 0 { + if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Freebind", wireType) } - var v int + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowAddress @@ -1442,12 +1447,25 @@ func (m *BindConfig) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= (int(b) & 0x7F) << shift + msglen |= (int(b) & 0x7F) << shift if b < 0x80 { break } } - m.Freebind = bool(v != 0) + if msglen < 0 { + return ErrInvalidLengthAddress + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Freebind == nil { + m.Freebind = &google_protobuf.BoolValue{} + } + if err := m.Freebind.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipAddress(dAtA[iNdEx:]) @@ -1803,41 +1821,41 @@ var ( func init() { proto.RegisterFile("envoy/api/v2/core/address.proto", fileDescriptorAddress) } var fileDescriptorAddress = []byte{ - // 564 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0xc1, 0x8a, 0xd3, 0x40, - 0x18, 0xce, 0xb4, 0xd9, 0xdd, 0xf6, 0x5f, 0x5b, 0x6a, 0x10, 0x36, 0x14, 0xcd, 0x96, 0x2c, 0x42, - 0x15, 0x4c, 0x24, 0xeb, 0x0b, 0x98, 0x0a, 0x76, 0x41, 0x24, 0x46, 0x57, 0x8f, 0x61, 0x9a, 0x4c, - 0xe3, 0x60, 0x9a, 0x19, 0xa6, 0x69, 0xd4, 0x9b, 0x7a, 0x10, 0xf1, 0xee, 0x13, 0x78, 0xf1, 0x11, - 0xc4, 0xd3, 0x1e, 0xf7, 0xe0, 0xc1, 0x27, 0x10, 0xe9, 0x6d, 0xdf, 0x42, 0x66, 0x92, 0x14, 0x75, - 0x05, 0xf1, 0xf6, 0xe7, 0xfb, 0xbf, 0xff, 0xcb, 0x37, 0xdf, 0xfc, 0x03, 0xfb, 0x24, 0x2f, 0xd9, - 0x4b, 0x17, 0x73, 0xea, 0x96, 0x9e, 0x1b, 0x33, 0x41, 0x5c, 0x9c, 0x24, 0x82, 0x2c, 0x97, 0x0e, - 0x17, 0xac, 0x60, 0xc6, 0x45, 0x45, 0x70, 0x30, 0xa7, 0x4e, 0xe9, 0x39, 0x92, 0x30, 0xb4, 0x52, - 0xc6, 0xd2, 0x8c, 0xb8, 0x8a, 0x30, 0x5b, 0xcd, 0xdd, 0xe7, 0x02, 0x73, 0x4e, 0x44, 0x3d, 0x32, - 0xdc, 0x2b, 0x71, 0x46, 0x13, 0x5c, 0x10, 0xb7, 0x29, 0xea, 0xc6, 0xa5, 0x94, 0xa5, 0x4c, 0x95, - 0xae, 0xac, 0x2a, 0xd4, 0xbe, 0x0a, 0x7a, 0x40, 0x39, 0x31, 0xae, 0x80, 0xce, 0x71, 0xf1, 0xd4, - 0x44, 0x23, 0x34, 0xee, 0xfa, 0xdd, 0x2f, 0x67, 0x27, 0x6d, 0x5d, 0xb4, 0x46, 0x28, 0x54, 0xb0, - 0xfd, 0xb5, 0x05, 0xbd, 0x87, 0x2c, 0x7e, 0x46, 0x8a, 0xdb, 0x95, 0x41, 0xe3, 0x01, 0x74, 0x94, - 0x42, 0xcc, 0x32, 0x35, 0xd4, 0xf7, 0xae, 0x39, 0xe7, 0xdc, 0x3a, 0xbf, 0xcd, 0x38, 0x41, 0x3d, - 0xe0, 0x83, 0xd4, 0xdf, 0x7a, 0x83, 0x5a, 0x03, 0x14, 0x6e, 0x64, 0x8c, 0x03, 0xd8, 0xa9, 0x8f, - 0x6f, 0xb6, 0xfe, 0xb4, 0xd1, 0x74, 0x8c, 0x7d, 0x00, 0xce, 0x44, 0x11, 0x95, 0x38, 0x5b, 0x11, - 0xb3, 0x3d, 0x42, 0xe3, 0xde, 0x54, 0x0b, 0xbb, 0x12, 0x7b, 0x2c, 0x21, 0x49, 0xc8, 0xf1, 0x82, - 0x24, 0x91, 0x84, 0x4c, 0x5d, 0x0a, 0x49, 0x82, 0xc2, 0x02, 0x26, 0x0a, 0xe3, 0x00, 0x7a, 0x82, - 0x2c, 0x59, 0x56, 0x12, 0x11, 0x49, 0xd4, 0xdc, 0x92, 0x9c, 0xf0, 0x42, 0x03, 0xde, 0xc7, 0x0b, - 0xa9, 0xb2, 0x4b, 0x79, 0x79, 0x2b, 0x8a, 0xd9, 0x82, 0xe3, 0xc2, 0xdc, 0x1e, 0xa1, 0x71, 0x27, - 0x04, 0x09, 0x4d, 0x14, 0x62, 0xdb, 0xd0, 0x69, 0x8e, 0x63, 0xec, 0x40, 0xfb, 0xd1, 0x24, 0x18, - 0x68, 0xb2, 0x38, 0xbe, 0x13, 0x0c, 0xd0, 0x50, 0x7f, 0xf7, 0xd1, 0xd2, 0xfc, 0x3d, 0xe8, 0x2b, - 0xaf, 0x4b, 0x4e, 0x62, 0x3a, 0xa7, 0x44, 0x18, 0x5b, 0x9f, 0xcf, 0x4e, 0xda, 0xc8, 0x7e, 0x8d, - 0x00, 0x7c, 0x9a, 0x27, 0x13, 0x96, 0xcf, 0x69, 0x6a, 0x3c, 0x81, 0xfe, 0x92, 0xad, 0x44, 0x4c, - 0xa2, 0xe6, 0xfc, 0x32, 0xd1, 0x5d, 0x6f, 0xf4, 0xaf, 0x44, 0xfd, 0xfe, 0xe9, 0xf7, 0x7d, 0x4d, - 0x85, 0xf9, 0x5e, 0x85, 0xd9, 0xab, 0x74, 0x9a, 0x4b, 0x1a, 0x42, 0x67, 0x2e, 0x08, 0x99, 0xd1, - 0x3c, 0x51, 0x91, 0x76, 0xc2, 0xcd, 0xb7, 0xfd, 0x01, 0xc1, 0x4e, 0xc3, 0x3b, 0x92, 0x06, 0xa4, - 0xee, 0xff, 0x1a, 0x98, 0x6a, 0xf2, 0x97, 0xbf, 0xee, 0xc5, 0x0d, 0xd0, 0x39, 0xe5, 0x44, 0xfd, - 0x6e, 0xd7, 0xdb, 0xfb, 0x8b, 0x80, 0xdc, 0xb7, 0xa9, 0x16, 0x2a, 0x9a, 0x3f, 0xd8, 0xdc, 0x79, - 0x93, 0xcd, 0x5b, 0x04, 0xdd, 0x09, 0x4d, 0x44, 0x88, 0xf3, 0x94, 0x18, 0x37, 0xa1, 0x5f, 0xf7, - 0x23, 0x2e, 0xc8, 0x9c, 0xbe, 0x38, 0xbf, 0xa1, 0xbd, 0x9a, 0x10, 0xa8, 0xbe, 0x71, 0x17, 0xa0, - 0x62, 0x46, 0x19, 0xc9, 0x6b, 0x1b, 0x97, 0x9d, 0xea, 0xd5, 0x38, 0xcd, 0xab, 0x71, 0x8e, 0x8f, - 0xf2, 0xe2, 0xd0, 0x53, 0x1b, 0x53, 0x6f, 0xe3, 0xf5, 0xb6, 0xf9, 0x0a, 0x85, 0xdd, 0x6a, 0xf6, - 0x1e, 0xc9, 0xfd, 0xc1, 0xa7, 0xb5, 0x85, 0x4e, 0xd7, 0x16, 0xfa, 0xb6, 0xb6, 0xd0, 0x8f, 0xb5, - 0x85, 0x66, 0xdb, 0x6a, 0xfc, 0xf0, 0x67, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x0a, 0x6c, 0xbb, - 0xb8, 0x03, 0x00, 0x00, + // 571 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x52, 0xc1, 0x8b, 0xd3, 0x4e, + 0x18, 0xcd, 0xb4, 0xd9, 0xdd, 0xf6, 0xdb, 0x5f, 0x4b, 0x7f, 0x41, 0xd8, 0x50, 0x34, 0x5b, 0xb2, + 0x08, 0xab, 0x60, 0x22, 0x59, 0xf1, 0x6e, 0x2a, 0xd8, 0x05, 0x91, 0x18, 0x5d, 0x3d, 0x86, 0x69, + 0x32, 0x8d, 0x83, 0x69, 0x66, 0x98, 0xa6, 0x51, 0x6f, 0xe2, 0x41, 0xc4, 0xbb, 0x47, 0x4f, 0x5e, + 0xfc, 0x13, 0xc4, 0xd3, 0x1e, 0xf7, 0xe0, 0xc1, 0xbf, 0x40, 0xa4, 0xb7, 0xfd, 0x2f, 0x64, 0x26, + 0x49, 0x51, 0x2b, 0x88, 0xb7, 0x8f, 0xf7, 0xbd, 0xef, 0xe5, 0xcd, 0xcb, 0x83, 0x7d, 0x92, 0x97, + 0xec, 0x85, 0x8b, 0x39, 0x75, 0x4b, 0xcf, 0x8d, 0x99, 0x20, 0x2e, 0x4e, 0x12, 0x41, 0x16, 0x0b, + 0x87, 0x0b, 0x56, 0x30, 0xe3, 0x7f, 0x45, 0x70, 0x30, 0xa7, 0x4e, 0xe9, 0x39, 0x92, 0x30, 0xb4, + 0x52, 0xc6, 0xd2, 0x8c, 0xb8, 0x8a, 0x30, 0x5d, 0xce, 0xdc, 0x67, 0x02, 0x73, 0x4e, 0x44, 0x7d, + 0x32, 0xdc, 0x2b, 0x71, 0x46, 0x13, 0x5c, 0x10, 0xb7, 0x19, 0xea, 0xc5, 0x85, 0x94, 0xa5, 0x4c, + 0x8d, 0xae, 0x9c, 0x2a, 0xd4, 0xbe, 0x0c, 0x7a, 0x40, 0x39, 0x31, 0x2e, 0x81, 0xce, 0x71, 0xf1, + 0xc4, 0x44, 0x23, 0x74, 0xd8, 0xf5, 0xbb, 0x9f, 0xcf, 0x4f, 0xdb, 0xba, 0x68, 0x8d, 0x50, 0xa8, + 0x60, 0xfb, 0x4b, 0x0b, 0x7a, 0x0f, 0x58, 0xfc, 0x94, 0x14, 0xb7, 0x2a, 0x83, 0xc6, 0x7d, 0xe8, + 0x28, 0x85, 0x98, 0x65, 0xea, 0xa8, 0xef, 0x5d, 0x71, 0x36, 0xdc, 0x3a, 0xbf, 0xdc, 0x38, 0x41, + 0x7d, 0xe0, 0x83, 0xd4, 0xdf, 0x7a, 0x85, 0x5a, 0x03, 0x14, 0xae, 0x65, 0x8c, 0x03, 0xd8, 0xa9, + 0x9f, 0x6f, 0xb6, 0x7e, 0xb7, 0xd1, 0x6c, 0x8c, 0x7d, 0x00, 0xce, 0x44, 0x11, 0x95, 0x38, 0x5b, + 0x12, 0xb3, 0x3d, 0x42, 0x87, 0xbd, 0x89, 0x16, 0x76, 0x25, 0xf6, 0x48, 0x42, 0x92, 0x90, 0xe3, + 0x39, 0x49, 0x22, 0x09, 0x99, 0xba, 0x14, 0x92, 0x04, 0x85, 0x05, 0x4c, 0x14, 0xc6, 0x01, 0xf4, + 0x04, 0x59, 0xb0, 0xac, 0x24, 0x22, 0x92, 0xa8, 0xb9, 0x25, 0x39, 0xe1, 0x7f, 0x0d, 0x78, 0x0f, + 0xcf, 0xa5, 0xca, 0x2e, 0xe5, 0xe5, 0x8d, 0x28, 0x66, 0x73, 0x8e, 0x0b, 0x73, 0x7b, 0x84, 0x0e, + 0x3b, 0x21, 0x48, 0x68, 0xac, 0x10, 0xdb, 0x86, 0x4e, 0xf3, 0x1c, 0x63, 0x07, 0xda, 0x0f, 0xc7, + 0xc1, 0x40, 0x93, 0xc3, 0xc9, 0xed, 0x60, 0x80, 0x86, 0xfa, 0x9b, 0x0f, 0x96, 0xe6, 0xef, 0x41, + 0x5f, 0x79, 0x5d, 0x70, 0x12, 0xd3, 0x19, 0x25, 0xc2, 0xd8, 0xfa, 0x74, 0x7e, 0xda, 0x46, 0xf6, + 0x7b, 0x04, 0xe0, 0xd3, 0x3c, 0x19, 0xb3, 0x7c, 0x46, 0x53, 0xe3, 0x31, 0xf4, 0x17, 0x6c, 0x29, + 0x62, 0x12, 0x35, 0xef, 0x97, 0x89, 0xee, 0x7a, 0xa3, 0xbf, 0x25, 0xea, 0xf7, 0xcf, 0xbe, 0xed, + 0x6b, 0x2a, 0xcc, 0xb7, 0x2a, 0xcc, 0x5e, 0xa5, 0xd3, 0xfc, 0xa4, 0x9b, 0xd0, 0x99, 0x09, 0x42, + 0xa6, 0x34, 0x4f, 0x54, 0xa4, 0xbb, 0xde, 0xd0, 0xa9, 0xfa, 0xe3, 0x34, 0xfd, 0x71, 0x7c, 0xc6, + 0x32, 0x95, 0x5c, 0xb8, 0xe6, 0xda, 0xef, 0x10, 0xec, 0x34, 0x1a, 0xc7, 0xd2, 0x9c, 0xfc, 0xe6, + 0xbf, 0x9a, 0x9b, 0x68, 0xd2, 0xce, 0xcf, 0x9d, 0xb9, 0x06, 0x3a, 0xa7, 0x9c, 0xd4, 0x56, 0xf6, + 0xfe, 0x20, 0x20, 0xbb, 0x38, 0xd1, 0x42, 0x45, 0xf3, 0x07, 0xeb, 0x3e, 0x34, 0xb9, 0xbd, 0x46, + 0xd0, 0x1d, 0xd3, 0x44, 0x84, 0x38, 0x4f, 0x89, 0x71, 0x1d, 0xfa, 0xf5, 0x3e, 0xe2, 0x82, 0xcc, + 0xe8, 0xf3, 0xcd, 0xf6, 0xf6, 0x6a, 0x42, 0xa0, 0xf6, 0xc6, 0x1d, 0x80, 0x8a, 0x19, 0x65, 0x24, + 0xaf, 0x6d, 0x5c, 0xdc, 0x48, 0xe4, 0xe4, 0x38, 0x2f, 0x8e, 0x3c, 0x95, 0x49, 0xdd, 0xd4, 0xab, + 0x6d, 0xf3, 0x25, 0x0a, 0xbb, 0xd5, 0xed, 0x5d, 0x92, 0xfb, 0x83, 0x8f, 0x2b, 0x0b, 0x9d, 0xad, + 0x2c, 0xf4, 0x75, 0x65, 0xa1, 0xef, 0x2b, 0x0b, 0x4d, 0xb7, 0xd5, 0xf9, 0xd1, 0x8f, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x60, 0x2d, 0x0c, 0xc4, 0xd4, 0x03, 0x00, 0x00, } diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/address.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/address.pb.validate.go new file mode 100644 index 00000000..a2269f98 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/address.pb.validate.go @@ -0,0 +1,354 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/core/address.proto +// DO NOT EDIT!!! + +package core + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Pipe with the rules defined in the proto +// definition for this message. If any rules are violated, an error is returned. +func (m *Pipe) Validate() error { + if m == nil { + return nil + } + + if len(m.GetPath()) < 1 { + return PipeValidationError{ + Field: "Path", + Reason: "value length must be at least 1 bytes", + } + } + + return nil +} + +// PipeValidationError is the validation error returned by Pipe.Validate if the +// designated constraints aren't met. +type PipeValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e PipeValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sPipe.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = PipeValidationError{} + +// Validate checks the field values on SocketAddress with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *SocketAddress) Validate() error { + if m == nil { + return nil + } + + if _, ok := SocketAddress_Protocol_name[int32(m.GetProtocol())]; !ok { + return SocketAddressValidationError{ + Field: "Protocol", + Reason: "value must be one of the defined enum values", + } + } + + if len(m.GetAddress()) < 1 { + return SocketAddressValidationError{ + Field: "Address", + Reason: "value length must be at least 1 bytes", + } + } + + // no validation rules for ResolverName + + // no validation rules for Ipv4Compat + + switch m.PortSpecifier.(type) { + + case *SocketAddress_PortValue: + // no validation rules for PortValue + + case *SocketAddress_NamedPort: + // no validation rules for NamedPort + + default: + return SocketAddressValidationError{ + Field: "PortSpecifier", + Reason: "value is required", + } + + } + + return nil +} + +// SocketAddressValidationError is the validation error returned by +// SocketAddress.Validate if the designated constraints aren't met. +type SocketAddressValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e SocketAddressValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sSocketAddress.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = SocketAddressValidationError{} + +// Validate checks the field values on BindConfig with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *BindConfig) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetSourceAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BindConfigValidationError{ + Field: "SourceAddress", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetFreebind()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BindConfigValidationError{ + Field: "Freebind", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// BindConfigValidationError is the validation error returned by +// BindConfig.Validate if the designated constraints aren't met. +type BindConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e BindConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sBindConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = BindConfigValidationError{} + +// Validate checks the field values on Address with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Address) Validate() error { + if m == nil { + return nil + } + + switch m.Address.(type) { + + case *Address_SocketAddress: + + if v, ok := interface{}(m.GetSocketAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AddressValidationError{ + Field: "SocketAddress", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *Address_Pipe: + + if v, ok := interface{}(m.GetPipe()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AddressValidationError{ + Field: "Pipe", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + default: + return AddressValidationError{ + Field: "Address", + Reason: "value is required", + } + + } + + return nil +} + +// AddressValidationError is the validation error returned by Address.Validate +// if the designated constraints aren't met. +type AddressValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AddressValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAddress.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AddressValidationError{} + +// Validate checks the field values on CidrRange with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *CidrRange) Validate() error { + if m == nil { + return nil + } + + if len(m.GetAddressPrefix()) < 1 { + return CidrRangeValidationError{ + Field: "AddressPrefix", + Reason: "value length must be at least 1 bytes", + } + } + + if wrapper := m.GetPrefixLen(); wrapper != nil { + + if wrapper.GetValue() > 128 { + return CidrRangeValidationError{ + Field: "PrefixLen", + Reason: "value must be less than or equal to 128", + } + } + + } + + return nil +} + +// CidrRangeValidationError is the validation error returned by +// CidrRange.Validate if the designated constraints aren't met. +type CidrRangeValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e CidrRangeValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCidrRange.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = CidrRangeValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/base.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/base.pb.validate.go new file mode 100644 index 00000000..54d7a9ad --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/base.pb.validate.go @@ -0,0 +1,488 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/core/base.proto +// DO NOT EDIT!!! + +package core + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Locality with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Locality) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Region + + // no validation rules for Zone + + // no validation rules for SubZone + + return nil +} + +// LocalityValidationError is the validation error returned by +// Locality.Validate if the designated constraints aren't met. +type LocalityValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e LocalityValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sLocality.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = LocalityValidationError{} + +// Validate checks the field values on Node with the rules defined in the proto +// definition for this message. If any rules are violated, an error is returned. +func (m *Node) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Id + + // no validation rules for Cluster + + if v, ok := interface{}(m.GetMetadata()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return NodeValidationError{ + Field: "Metadata", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetLocality()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return NodeValidationError{ + Field: "Locality", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for BuildVersion + + return nil +} + +// NodeValidationError is the validation error returned by Node.Validate if the +// designated constraints aren't met. +type NodeValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e NodeValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sNode.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = NodeValidationError{} + +// Validate checks the field values on Metadata with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Metadata) Validate() error { + if m == nil { + return nil + } + + // no validation rules for FilterMetadata + + return nil +} + +// MetadataValidationError is the validation error returned by +// Metadata.Validate if the designated constraints aren't met. +type MetadataValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e MetadataValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sMetadata.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = MetadataValidationError{} + +// Validate checks the field values on RuntimeUInt32 with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *RuntimeUInt32) Validate() error { + if m == nil { + return nil + } + + // no validation rules for DefaultValue + + if len(m.GetRuntimeKey()) < 1 { + return RuntimeUInt32ValidationError{ + Field: "RuntimeKey", + Reason: "value length must be at least 1 bytes", + } + } + + return nil +} + +// RuntimeUInt32ValidationError is the validation error returned by +// RuntimeUInt32.Validate if the designated constraints aren't met. +type RuntimeUInt32ValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RuntimeUInt32ValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRuntimeUInt32.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RuntimeUInt32ValidationError{} + +// Validate checks the field values on HeaderValue with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *HeaderValue) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Key + + // no validation rules for Value + + return nil +} + +// HeaderValueValidationError is the validation error returned by +// HeaderValue.Validate if the designated constraints aren't met. +type HeaderValueValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HeaderValueValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHeaderValue.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HeaderValueValidationError{} + +// Validate checks the field values on HeaderValueOption with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *HeaderValueOption) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetHeader()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HeaderValueOptionValidationError{ + Field: "Header", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetAppend()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HeaderValueOptionValidationError{ + Field: "Append", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// HeaderValueOptionValidationError is the validation error returned by +// HeaderValueOption.Validate if the designated constraints aren't met. +type HeaderValueOptionValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HeaderValueOptionValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHeaderValueOption.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HeaderValueOptionValidationError{} + +// Validate checks the field values on DataSource with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *DataSource) Validate() error { + if m == nil { + return nil + } + + switch m.Specifier.(type) { + + case *DataSource_Filename: + + if len(m.GetFilename()) < 1 { + return DataSourceValidationError{ + Field: "Filename", + Reason: "value length must be at least 1 bytes", + } + } + + case *DataSource_InlineBytes: + + if len(m.GetInlineBytes()) < 1 { + return DataSourceValidationError{ + Field: "InlineBytes", + Reason: "value length must be at least 1 bytes", + } + } + + case *DataSource_InlineString: + + if len(m.GetInlineString()) < 1 { + return DataSourceValidationError{ + Field: "InlineString", + Reason: "value length must be at least 1 bytes", + } + } + + default: + return DataSourceValidationError{ + Field: "Specifier", + Reason: "value is required", + } + + } + + return nil +} + +// DataSourceValidationError is the validation error returned by +// DataSource.Validate if the designated constraints aren't met. +type DataSourceValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e DataSourceValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDataSource.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = DataSourceValidationError{} + +// Validate checks the field values on TransportSocket with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *TransportSocket) Validate() error { + if m == nil { + return nil + } + + if len(m.GetName()) < 1 { + return TransportSocketValidationError{ + Field: "Name", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TransportSocketValidationError{ + Field: "Config", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// TransportSocketValidationError is the validation error returned by +// TransportSocket.Validate if the designated constraints aren't met. +type TransportSocketValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TransportSocketValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTransportSocket.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TransportSocketValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/config_source.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/config_source.pb.validate.go new file mode 100644 index 00000000..2e26b3b1 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/config_source.pb.validate.go @@ -0,0 +1,230 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/core/config_source.proto +// DO NOT EDIT!!! + +package core + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on ApiConfigSource with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *ApiConfigSource) Validate() error { + if m == nil { + return nil + } + + if _, ok := ApiConfigSource_ApiType_name[int32(m.GetApiType())]; !ok { + return ApiConfigSourceValidationError{ + Field: "ApiType", + Reason: "value must be one of the defined enum values", + } + } + + for idx, item := range m.GetGrpcServices() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ApiConfigSourceValidationError{ + Field: fmt.Sprintf("GrpcServices[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetRefreshDelay()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ApiConfigSourceValidationError{ + Field: "RefreshDelay", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// ApiConfigSourceValidationError is the validation error returned by +// ApiConfigSource.Validate if the designated constraints aren't met. +type ApiConfigSourceValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ApiConfigSourceValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sApiConfigSource.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ApiConfigSourceValidationError{} + +// Validate checks the field values on AggregatedConfigSource with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *AggregatedConfigSource) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// AggregatedConfigSourceValidationError is the validation error returned by +// AggregatedConfigSource.Validate if the designated constraints aren't met. +type AggregatedConfigSourceValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AggregatedConfigSourceValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAggregatedConfigSource.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AggregatedConfigSourceValidationError{} + +// Validate checks the field values on ConfigSource with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *ConfigSource) Validate() error { + if m == nil { + return nil + } + + switch m.ConfigSourceSpecifier.(type) { + + case *ConfigSource_Path: + // no validation rules for Path + + case *ConfigSource_ApiConfigSource: + + if v, ok := interface{}(m.GetApiConfigSource()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ConfigSourceValidationError{ + Field: "ApiConfigSource", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *ConfigSource_Ads: + + if v, ok := interface{}(m.GetAds()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ConfigSourceValidationError{ + Field: "Ads", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + default: + return ConfigSourceValidationError{ + Field: "ConfigSourceSpecifier", + Reason: "value is required", + } + + } + + return nil +} + +// ConfigSourceValidationError is the validation error returned by +// ConfigSource.Validate if the designated constraints aren't met. +type ConfigSourceValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ConfigSourceValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sConfigSource.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ConfigSourceValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/grpc_service.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/grpc_service.pb.validate.go new file mode 100644 index 00000000..e8d0fdef --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/grpc_service.pb.validate.go @@ -0,0 +1,404 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/core/grpc_service.proto +// DO NOT EDIT!!! + +package core + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on GrpcService with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *GrpcService) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GrpcServiceValidationError{ + Field: "Timeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetCredentials() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GrpcServiceValidationError{ + Field: fmt.Sprintf("Credentials[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetInitialMetadata() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GrpcServiceValidationError{ + Field: fmt.Sprintf("InitialMetadata[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + switch m.TargetSpecifier.(type) { + + case *GrpcService_EnvoyGrpc_: + + if v, ok := interface{}(m.GetEnvoyGrpc()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GrpcServiceValidationError{ + Field: "EnvoyGrpc", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *GrpcService_GoogleGrpc_: + + if v, ok := interface{}(m.GetGoogleGrpc()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GrpcServiceValidationError{ + Field: "GoogleGrpc", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + default: + return GrpcServiceValidationError{ + Field: "TargetSpecifier", + Reason: "value is required", + } + + } + + return nil +} + +// GrpcServiceValidationError is the validation error returned by +// GrpcService.Validate if the designated constraints aren't met. +type GrpcServiceValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e GrpcServiceValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGrpcService.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = GrpcServiceValidationError{} + +// Validate checks the field values on GrpcService_EnvoyGrpc with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *GrpcService_EnvoyGrpc) Validate() error { + if m == nil { + return nil + } + + if len(m.GetClusterName()) < 1 { + return GrpcService_EnvoyGrpcValidationError{ + Field: "ClusterName", + Reason: "value length must be at least 1 bytes", + } + } + + return nil +} + +// GrpcService_EnvoyGrpcValidationError is the validation error returned by +// GrpcService_EnvoyGrpc.Validate if the designated constraints aren't met. +type GrpcService_EnvoyGrpcValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e GrpcService_EnvoyGrpcValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGrpcService_EnvoyGrpc.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = GrpcService_EnvoyGrpcValidationError{} + +// Validate checks the field values on GrpcService_GoogleGrpc with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *GrpcService_GoogleGrpc) Validate() error { + if m == nil { + return nil + } + + if len(m.GetTargetUri()) < 1 { + return GrpcService_GoogleGrpcValidationError{ + Field: "TargetUri", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetSslCredentials()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GrpcService_GoogleGrpcValidationError{ + Field: "SslCredentials", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if len(m.GetStatPrefix()) < 1 { + return GrpcService_GoogleGrpcValidationError{ + Field: "StatPrefix", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GrpcService_GoogleGrpcValidationError{ + Field: "Config", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// GrpcService_GoogleGrpcValidationError is the validation error returned by +// GrpcService_GoogleGrpc.Validate if the designated constraints aren't met. +type GrpcService_GoogleGrpcValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e GrpcService_GoogleGrpcValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGrpcService_GoogleGrpc.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = GrpcService_GoogleGrpcValidationError{} + +// Validate checks the field values on GrpcService_Credentials with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *GrpcService_Credentials) Validate() error { + if m == nil { + return nil + } + + switch m.CredentialSpecifier.(type) { + + case *GrpcService_Credentials_AccessToken: + // no validation rules for AccessToken + + default: + return GrpcService_CredentialsValidationError{ + Field: "CredentialSpecifier", + Reason: "value is required", + } + + } + + return nil +} + +// GrpcService_CredentialsValidationError is the validation error returned by +// GrpcService_Credentials.Validate if the designated constraints aren't met. +type GrpcService_CredentialsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e GrpcService_CredentialsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGrpcService_Credentials.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = GrpcService_CredentialsValidationError{} + +// Validate checks the field values on GrpcService_GoogleGrpc_SslCredentials +// with the rules defined in the proto definition for this message. If any +// rules are violated, an error is returned. +func (m *GrpcService_GoogleGrpc_SslCredentials) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetRootCerts()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GrpcService_GoogleGrpc_SslCredentialsValidationError{ + Field: "RootCerts", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetPrivateKey()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GrpcService_GoogleGrpc_SslCredentialsValidationError{ + Field: "PrivateKey", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetCertChain()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GrpcService_GoogleGrpc_SslCredentialsValidationError{ + Field: "CertChain", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// GrpcService_GoogleGrpc_SslCredentialsValidationError is the validation error +// returned by GrpcService_GoogleGrpc_SslCredentials.Validate if the +// designated constraints aren't met. +type GrpcService_GoogleGrpc_SslCredentialsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e GrpcService_GoogleGrpc_SslCredentialsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGrpcService_GoogleGrpc_SslCredentials.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = GrpcService_GoogleGrpc_SslCredentialsValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/health_check.pb.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/health_check.pb.go index 552758de..9a70d709 100644 --- a/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/health_check.pb.go +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/health_check.pb.go @@ -87,6 +87,14 @@ type HealthCheck struct { // *HealthCheck_RedisHealthCheck_ // *HealthCheck_GrpcHealthCheck_ HealthChecker isHealthCheck_HealthChecker `protobuf_oneof:"health_checker"` + // The "no traffic interval" is a special health check interval that is used when a cluster has + // never had traffic routed to it. This lower interval allows cluster information to be kept up to + // date, without sending a potentially large amount of active health checking traffic for no + // reason. Once a cluster has been used for traffic routing, Envoy will shift back to using the + // standard health check interval that is defined. + // + // The default value for "no traffic interval" is 60 seconds. + NoTrafficInterval *google_protobuf2.Duration `protobuf:"bytes,12,opt,name=no_traffic_interval,json=noTrafficInterval" json:"no_traffic_interval,omitempty"` } func (m *HealthCheck) Reset() { *m = HealthCheck{} } @@ -203,6 +211,13 @@ func (m *HealthCheck) GetGrpcHealthCheck() *HealthCheck_GrpcHealthCheck { return nil } +func (m *HealthCheck) GetNoTrafficInterval() *google_protobuf2.Duration { + if m != nil { + return m.NoTrafficInterval + } + return nil +} + // XXX_OneofFuncs is for the internal use of the proto package. func (*HealthCheck) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _HealthCheck_OneofMarshaler, _HealthCheck_OneofUnmarshaler, _HealthCheck_OneofSizer, []interface{}{ @@ -637,6 +652,9 @@ func (this *HealthCheck) Equal(that interface{}) bool { } else if !this.HealthChecker.Equal(that1.HealthChecker) { return false } + if !this.NoTrafficInterval.Equal(that1.NoTrafficInterval) { + return false + } return true } func (this *HealthCheck_HttpHealthCheck_) Equal(that interface{}) bool { @@ -1087,6 +1105,16 @@ func (m *HealthCheck) MarshalTo(dAtA []byte) (int, error) { } i += nn8 } + if m.NoTrafficInterval != nil { + dAtA[i] = 0x62 + i++ + i = encodeVarintHealthCheck(dAtA, i, uint64(m.NoTrafficInterval.Size())) + n9, err := m.NoTrafficInterval.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n9 + } return i, nil } @@ -1096,11 +1124,11 @@ func (m *HealthCheck_HttpHealthCheck_) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x42 i++ i = encodeVarintHealthCheck(dAtA, i, uint64(m.HttpHealthCheck.Size())) - n9, err := m.HttpHealthCheck.MarshalTo(dAtA[i:]) + n10, err := m.HttpHealthCheck.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n9 + i += n10 } return i, nil } @@ -1110,11 +1138,11 @@ func (m *HealthCheck_TcpHealthCheck_) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x4a i++ i = encodeVarintHealthCheck(dAtA, i, uint64(m.TcpHealthCheck.Size())) - n10, err := m.TcpHealthCheck.MarshalTo(dAtA[i:]) + n11, err := m.TcpHealthCheck.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n10 + i += n11 } return i, nil } @@ -1124,11 +1152,11 @@ func (m *HealthCheck_RedisHealthCheck_) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x52 i++ i = encodeVarintHealthCheck(dAtA, i, uint64(m.RedisHealthCheck.Size())) - n11, err := m.RedisHealthCheck.MarshalTo(dAtA[i:]) + n12, err := m.RedisHealthCheck.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n11 + i += n12 } return i, nil } @@ -1138,11 +1166,11 @@ func (m *HealthCheck_GrpcHealthCheck_) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x5a i++ i = encodeVarintHealthCheck(dAtA, i, uint64(m.GrpcHealthCheck.Size())) - n12, err := m.GrpcHealthCheck.MarshalTo(dAtA[i:]) + n13, err := m.GrpcHealthCheck.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n12 + i += n13 } return i, nil } @@ -1162,11 +1190,11 @@ func (m *HealthCheck_Payload) MarshalTo(dAtA []byte) (int, error) { var l int _ = l if m.Payload != nil { - nn13, err := m.Payload.MarshalTo(dAtA[i:]) + nn14, err := m.Payload.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += nn13 + i += nn14 } return i, nil } @@ -1220,21 +1248,21 @@ func (m *HealthCheck_HttpHealthCheck) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintHealthCheck(dAtA, i, uint64(m.Send.Size())) - n14, err := m.Send.MarshalTo(dAtA[i:]) + n15, err := m.Send.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n14 + i += n15 } if m.Receive != nil { dAtA[i] = 0x22 i++ i = encodeVarintHealthCheck(dAtA, i, uint64(m.Receive.Size())) - n15, err := m.Receive.MarshalTo(dAtA[i:]) + n16, err := m.Receive.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n15 + i += n16 } if len(m.ServiceName) > 0 { dAtA[i] = 0x2a @@ -1264,11 +1292,11 @@ func (m *HealthCheck_TcpHealthCheck) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintHealthCheck(dAtA, i, uint64(m.Send.Size())) - n16, err := m.Send.MarshalTo(dAtA[i:]) + n17, err := m.Send.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n16 + i += n17 } if len(m.Receive) > 0 { for _, msg := range m.Receive { @@ -1376,6 +1404,10 @@ func (m *HealthCheck) Size() (n int) { if m.HealthChecker != nil { n += m.HealthChecker.Size() } + if m.NoTrafficInterval != nil { + l = m.NoTrafficInterval.Size() + n += 1 + l + sovHealthCheck(uint64(l)) + } return n } @@ -1903,6 +1935,39 @@ func (m *HealthCheck) Unmarshal(dAtA []byte) error { } m.HealthChecker = &HealthCheck_GrpcHealthCheck_{v} iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NoTrafficInterval", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowHealthCheck + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthHealthCheck + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.NoTrafficInterval == nil { + m.NoTrafficInterval = &google_protobuf2.Duration{} + } + if err := m.NoTrafficInterval.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipHealthCheck(dAtA[iNdEx:]) @@ -2616,51 +2681,52 @@ var ( func init() { proto.RegisterFile("envoy/api/v2/core/health_check.proto", fileDescriptorHealthCheck) } var fileDescriptorHealthCheck = []byte{ - // 727 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0xcd, 0x6e, 0xd3, 0x4a, - 0x14, 0xc7, 0x33, 0x49, 0xda, 0x24, 0x27, 0xb9, 0x89, 0x3b, 0xf7, 0x4a, 0xf5, 0x8d, 0x20, 0x14, + // 752 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x93, 0xc1, 0x6e, 0xd3, 0x4a, + 0x14, 0x86, 0xe3, 0x24, 0x6d, 0x92, 0x93, 0xdc, 0xc4, 0x99, 0x5e, 0xa9, 0xbe, 0xd1, 0x25, 0x14, 0x54, 0x21, 0x84, 0x84, 0x2d, 0xa5, 0x48, 0x48, 0x6c, 0xa0, 0x69, 0xab, 0x26, 0x40, 0xd3, 0xca, - 0x24, 0x45, 0x95, 0x90, 0xac, 0xa9, 0x33, 0xc4, 0xa6, 0xae, 0xc7, 0x1a, 0x4f, 0x02, 0x79, 0x09, - 0x9e, 0x03, 0x21, 0xb1, 0x47, 0xac, 0xba, 0x64, 0xc9, 0x23, 0xa0, 0x48, 0x2c, 0xfa, 0x16, 0xc8, - 0x13, 0x3b, 0x4a, 0xe2, 0x45, 0x02, 0xec, 0xce, 0x9c, 0x99, 0xff, 0xef, 0x7c, 0xf8, 0x1c, 0xc3, - 0x36, 0xf5, 0x86, 0x6c, 0xa4, 0x13, 0xdf, 0xd1, 0x87, 0x75, 0xdd, 0x62, 0x9c, 0xea, 0x36, 0x25, - 0xae, 0xb0, 0x4d, 0xcb, 0xa6, 0xd6, 0x85, 0xe6, 0x73, 0x26, 0x18, 0xde, 0x90, 0xaf, 0x34, 0xe2, - 0x3b, 0xda, 0xb0, 0xae, 0x85, 0xaf, 0xaa, 0xb5, 0x3e, 0x63, 0x7d, 0x97, 0xea, 0xf2, 0xc1, 0xf9, - 0xe0, 0x8d, 0xde, 0x1b, 0x70, 0x22, 0x1c, 0xe6, 0x4d, 0x24, 0xc9, 0xfb, 0x77, 0x9c, 0xf8, 0x3e, - 0xe5, 0x41, 0x74, 0xbf, 0x39, 0x24, 0xae, 0xd3, 0x23, 0x82, 0xea, 0xb1, 0x11, 0x5d, 0xfc, 0xd7, - 0x67, 0x7d, 0x26, 0x4d, 0x3d, 0xb4, 0x26, 0xde, 0x3b, 0x9f, 0x8b, 0x50, 0x6c, 0xca, 0xc4, 0xf6, - 0xc2, 0xbc, 0xf0, 0x13, 0xc8, 0x09, 0xe7, 0x92, 0xb2, 0x81, 0x50, 0xd1, 0x16, 0xba, 0x57, 0xac, - 0xff, 0xaf, 0x4d, 0x02, 0x6a, 0x71, 0x40, 0x6d, 0x3f, 0x4a, 0xa8, 0x01, 0x5f, 0xaf, 0xaf, 0x32, - 0x6b, 0x9f, 0x50, 0x3a, 0x8f, 0x8c, 0x58, 0x85, 0x77, 0x21, 0xef, 0x78, 0x82, 0xf2, 0x21, 0x71, - 0xd5, 0xf4, 0xef, 0x10, 0xa6, 0x32, 0xdc, 0x80, 0x4a, 0x6c, 0x9b, 0x6f, 0x1d, 0x21, 0x28, 0x57, - 0x33, 0x4b, 0x48, 0x46, 0x39, 0x56, 0x3c, 0x93, 0x02, 0x7c, 0x04, 0xff, 0x0e, 0xbc, 0x49, 0xc7, - 0x47, 0xa6, 0xb0, 0x39, 0x0d, 0x6c, 0xe6, 0xf6, 0xd4, 0xac, 0xe4, 0xdc, 0x48, 0x70, 0xba, 0x2d, - 0x4f, 0xec, 0xd4, 0x4f, 0x89, 0x3b, 0xa0, 0x06, 0x9e, 0x0a, 0x3b, 0xb1, 0x0e, 0xb7, 0x60, 0x23, - 0x09, 0x5b, 0x5b, 0x01, 0xa6, 0x24, 0x50, 0x8f, 0x20, 0x4f, 0x5c, 0x61, 0xfa, 0x8c, 0x0b, 0x75, - 0x7d, 0x05, 0x42, 0x8e, 0xb8, 0xe2, 0x84, 0x71, 0x81, 0x0f, 0x40, 0xe1, 0x74, 0x10, 0x50, 0xd3, - 0x62, 0x9e, 0x47, 0xad, 0xb0, 0x6c, 0x35, 0x27, 0x01, 0xd5, 0x04, 0xa0, 0xc1, 0x98, 0x3b, 0x91, - 0x57, 0xa4, 0x66, 0x6f, 0x2a, 0xc1, 0xaf, 0x61, 0xc3, 0x16, 0xc2, 0x37, 0x67, 0xc7, 0x51, 0xcd, - 0x4b, 0x8e, 0xa6, 0x25, 0xe6, 0x51, 0x9b, 0x19, 0x0e, 0xad, 0x29, 0x84, 0x3f, 0x73, 0x6e, 0xa6, - 0x8c, 0x8a, 0x3d, 0xef, 0xc2, 0x67, 0xa0, 0x08, 0x6b, 0x01, 0x5e, 0x90, 0xf0, 0x07, 0x4b, 0xe0, - 0x1d, 0x6b, 0x81, 0x5d, 0x16, 0x73, 0x1e, 0x6c, 0x02, 0xe6, 0xb4, 0xe7, 0x04, 0xf3, 0x70, 0x90, - 0x70, 0x7d, 0x09, 0xdc, 0x08, 0x85, 0xf3, 0x78, 0x85, 0x2f, 0xf8, 0xc2, 0xce, 0xf4, 0xb9, 0x6f, - 0xcd, 0xf3, 0x8b, 0x2b, 0x75, 0xe6, 0x90, 0xfb, 0xd6, 0x42, 0x67, 0xfa, 0xf3, 0xae, 0xea, 0x29, - 0xe4, 0x4e, 0xc8, 0xc8, 0x65, 0xa4, 0x87, 0x6f, 0x41, 0x56, 0xd0, 0xf7, 0x93, 0x0d, 0x2b, 0x34, - 0x0a, 0xe1, 0x12, 0x64, 0x79, 0x7a, 0x0b, 0x35, 0x53, 0x86, 0xbc, 0xc0, 0x2a, 0xac, 0x9f, 0x3b, - 0x1e, 0xe1, 0x23, 0xb9, 0x42, 0xa5, 0x66, 0xca, 0x88, 0xce, 0x0d, 0x05, 0x72, 0x7e, 0x44, 0x59, - 0xfb, 0x72, 0x7d, 0x95, 0x41, 0xd5, 0x9f, 0x08, 0x2a, 0x0b, 0x1f, 0x06, 0x63, 0xc8, 0xda, 0x2c, - 0x88, 0x02, 0x18, 0xd2, 0xc6, 0x37, 0x21, 0xeb, 0x13, 0x61, 0x4b, 0xe2, 0x6c, 0x50, 0x43, 0xba, - 0xf1, 0x63, 0xc8, 0x06, 0xd4, 0xeb, 0x45, 0x9b, 0x76, 0x77, 0x49, 0xbd, 0x51, 0x25, 0x86, 0xd4, - 0xe0, 0xa7, 0x90, 0xe3, 0xd4, 0xa2, 0xce, 0x90, 0x46, 0x0b, 0xb6, 0xaa, 0x3c, 0x96, 0xe1, 0xdb, - 0x50, 0x0a, 0x28, 0x1f, 0x3a, 0x16, 0x35, 0x3d, 0x72, 0x49, 0xe5, 0x6a, 0x15, 0x8c, 0x62, 0xe4, - 0x6b, 0x93, 0x4b, 0x5a, 0xfd, 0x80, 0xa0, 0x3c, 0x3f, 0x23, 0xd3, 0x9c, 0xd1, 0xdf, 0xe5, 0x9c, - 0xde, 0xca, 0xfc, 0x41, 0xce, 0xd5, 0x6d, 0x50, 0x16, 0xc7, 0x0a, 0x2b, 0x90, 0xb9, 0xa0, 0xa3, - 0xa8, 0xef, 0xa1, 0x59, 0x7d, 0x08, 0x95, 0x85, 0xe1, 0x48, 0x14, 0x8b, 0x12, 0xc5, 0x36, 0x36, - 0xa1, 0x3c, 0x3b, 0x85, 0x94, 0x47, 0x5f, 0xfb, 0xbe, 0x01, 0xa5, 0x09, 0xea, 0xa5, 0x20, 0x62, - 0x10, 0xe0, 0x22, 0xe4, 0xba, 0xed, 0xe7, 0xed, 0xe3, 0x57, 0x6d, 0x25, 0x15, 0x1e, 0x9a, 0x07, - 0xbb, 0x2f, 0x3a, 0xcd, 0x33, 0x05, 0xe1, 0x7f, 0xa0, 0xd0, 0x6d, 0xc7, 0xc7, 0x34, 0x2e, 0x41, - 0x7e, 0xdf, 0xd8, 0x6d, 0xb5, 0x5b, 0xed, 0x43, 0x25, 0x13, 0xbe, 0xec, 0xb4, 0x8e, 0x0e, 0x8e, - 0xbb, 0x1d, 0x25, 0xdb, 0x50, 0x3e, 0x8e, 0x6b, 0xe8, 0xdb, 0xb8, 0x86, 0xbe, 0x8f, 0x6b, 0xe8, - 0xc7, 0xb8, 0x86, 0xce, 0xd7, 0xe5, 0x8f, 0x64, 0xe7, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb2, - 0x65, 0x6a, 0x6a, 0xc6, 0x06, 0x00, 0x00, + 0x24, 0x45, 0x95, 0x90, 0xac, 0xa9, 0x33, 0x8d, 0x4d, 0x5d, 0x8f, 0x35, 0x9e, 0x04, 0xf2, 0x12, + 0x3c, 0x07, 0xe2, 0x09, 0x10, 0xab, 0x2e, 0x59, 0xf2, 0x08, 0x28, 0x12, 0x8b, 0xbe, 0x01, 0x4b, + 0xe4, 0xb1, 0x1d, 0x25, 0xf1, 0x22, 0x01, 0x76, 0x67, 0xce, 0xcc, 0xff, 0xcd, 0x99, 0x33, 0xff, + 0x81, 0x6d, 0xe2, 0x8e, 0xe8, 0x58, 0xc3, 0x9e, 0xad, 0x8d, 0x1a, 0x9a, 0x49, 0x19, 0xd1, 0x2c, + 0x82, 0x1d, 0x6e, 0x19, 0xa6, 0x45, 0xcc, 0x4b, 0xd5, 0x63, 0x94, 0x53, 0x54, 0x15, 0xa7, 0x54, + 0xec, 0xd9, 0xea, 0xa8, 0xa1, 0x06, 0xa7, 0x6a, 0xf5, 0x01, 0xa5, 0x03, 0x87, 0x68, 0xe2, 0xc0, + 0xf9, 0xf0, 0x42, 0xeb, 0x0f, 0x19, 0xe6, 0x36, 0x75, 0x43, 0x49, 0x72, 0xff, 0x1d, 0xc3, 0x9e, + 0x47, 0x98, 0x1f, 0xed, 0x6f, 0x8e, 0xb0, 0x63, 0xf7, 0x31, 0x27, 0x5a, 0x1c, 0x44, 0x1b, 0xff, + 0x0e, 0xe8, 0x80, 0x8a, 0x50, 0x0b, 0xa2, 0x30, 0x7b, 0xf7, 0x67, 0x11, 0x8a, 0x2d, 0x51, 0xd8, + 0x5e, 0x50, 0x17, 0x7a, 0x0a, 0x39, 0x6e, 0x5f, 0x11, 0x3a, 0xe4, 0x8a, 0xb4, 0x25, 0xdd, 0x2f, + 0x36, 0xfe, 0x53, 0xc3, 0x0b, 0xd5, 0xf8, 0x42, 0x75, 0x3f, 0x2a, 0xa8, 0x09, 0x5f, 0x6e, 0xae, + 0x33, 0x6b, 0x9f, 0xa4, 0x74, 0x5e, 0xd2, 0x63, 0x15, 0xda, 0x85, 0xbc, 0xed, 0x72, 0xc2, 0x46, + 0xd8, 0x51, 0xd2, 0xbf, 0x43, 0x98, 0xca, 0x50, 0x13, 0x2a, 0x71, 0x6c, 0xbc, 0xb5, 0x39, 0x27, + 0x4c, 0xc9, 0x2c, 0x21, 0xe9, 0xe5, 0x58, 0xf1, 0x5c, 0x08, 0xd0, 0x11, 0x6c, 0x0c, 0xdd, 0xb0, + 0xe3, 0x63, 0x83, 0x5b, 0x8c, 0xf8, 0x16, 0x75, 0xfa, 0x4a, 0x56, 0x70, 0xfe, 0x4f, 0x70, 0x7a, + 0x6d, 0x97, 0xef, 0x34, 0x4e, 0xb1, 0x33, 0x24, 0x3a, 0x9a, 0x0a, 0xbb, 0xb1, 0x0e, 0xb5, 0xa1, + 0x9a, 0x84, 0xad, 0xad, 0x00, 0x93, 0x13, 0xa8, 0xc7, 0x90, 0xc7, 0x0e, 0x37, 0x3c, 0xca, 0xb8, + 0xb2, 0xbe, 0x02, 0x21, 0x87, 0x1d, 0x7e, 0x42, 0x19, 0x47, 0x07, 0x20, 0x33, 0x32, 0xf4, 0x89, + 0x61, 0x52, 0xd7, 0x25, 0x66, 0xf0, 0x6c, 0x25, 0x27, 0x00, 0xb5, 0x04, 0xa0, 0x49, 0xa9, 0x13, + 0xca, 0x2b, 0x42, 0xb3, 0x37, 0x95, 0xa0, 0x37, 0x50, 0xb5, 0x38, 0xf7, 0x8c, 0x59, 0x3b, 0x2a, + 0x79, 0xc1, 0x51, 0xd5, 0x84, 0x1f, 0xd5, 0x19, 0x73, 0xa8, 0x2d, 0xce, 0xbd, 0x99, 0x75, 0x2b, + 0xa5, 0x57, 0xac, 0xf9, 0x14, 0x3a, 0x03, 0x99, 0x9b, 0x0b, 0xf0, 0x82, 0x80, 0x3f, 0x5c, 0x02, + 0xef, 0x9a, 0x0b, 0xec, 0x32, 0x9f, 0xcb, 0x20, 0x03, 0x10, 0x23, 0x7d, 0xdb, 0x9f, 0x87, 0x83, + 0x80, 0x6b, 0x4b, 0xe0, 0x7a, 0x20, 0x9c, 0xc7, 0xcb, 0x6c, 0x21, 0x17, 0x74, 0x66, 0xc0, 0x3c, + 0x73, 0x9e, 0x5f, 0x5c, 0xa9, 0x33, 0x87, 0xcc, 0x33, 0x17, 0x3a, 0x33, 0x98, 0x4f, 0xa1, 0x36, + 0x6c, 0xb8, 0xd4, 0xe0, 0x0c, 0x5f, 0x5c, 0xd8, 0xa6, 0x31, 0x9d, 0x91, 0xd2, 0x32, 0x67, 0x57, + 0x5d, 0xda, 0x0d, 0x45, 0xed, 0x48, 0x53, 0x3b, 0x85, 0xdc, 0x09, 0x1e, 0x3b, 0x14, 0xf7, 0xd1, + 0x6d, 0xc8, 0x72, 0xf2, 0x3e, 0x1c, 0xd6, 0x42, 0xb3, 0x10, 0xcc, 0x53, 0x96, 0xa5, 0xb7, 0xa4, + 0x56, 0x4a, 0x17, 0x1b, 0x48, 0x81, 0xf5, 0x73, 0xdb, 0xc5, 0x6c, 0x2c, 0xa6, 0xb1, 0xd4, 0x4a, + 0xe9, 0xd1, 0xba, 0x29, 0x43, 0xce, 0x8b, 0x28, 0x6b, 0x9f, 0x6f, 0xae, 0x33, 0x52, 0xed, 0x87, + 0x04, 0x95, 0x85, 0x3f, 0x46, 0x08, 0xb2, 0x16, 0xf5, 0xa3, 0x0b, 0x74, 0x11, 0xa3, 0x5b, 0x90, + 0xf5, 0x30, 0xb7, 0x04, 0x71, 0xf6, 0x52, 0x5d, 0xa4, 0xd1, 0x13, 0xc8, 0xfa, 0xc4, 0xed, 0x47, + 0x43, 0x7b, 0x6f, 0x49, 0xeb, 0xa2, 0x97, 0xe8, 0x42, 0x83, 0x9e, 0x41, 0x8e, 0x11, 0x93, 0xd8, + 0x23, 0x12, 0xcd, 0xea, 0xaa, 0xf2, 0x58, 0x86, 0xee, 0x40, 0xc9, 0x27, 0x6c, 0x64, 0x9b, 0xc4, + 0x70, 0xf1, 0x15, 0x11, 0x53, 0x5a, 0xd0, 0x8b, 0x51, 0xae, 0x83, 0xaf, 0x48, 0xed, 0x83, 0x04, + 0xe5, 0x79, 0xbb, 0x4d, 0x6b, 0x96, 0xfe, 0xae, 0xe6, 0xf4, 0x56, 0xe6, 0x0f, 0x6a, 0xae, 0x6d, + 0x83, 0xbc, 0xe8, 0x50, 0x24, 0x43, 0xe6, 0x92, 0x8c, 0xa3, 0xbe, 0x07, 0x61, 0xed, 0x11, 0x54, + 0x16, 0x7c, 0x96, 0x78, 0xac, 0x94, 0x78, 0x6c, 0x73, 0x13, 0xca, 0xb3, 0x86, 0x26, 0x2c, 0xfa, + 0xed, 0x07, 0x3a, 0x94, 0x42, 0xd4, 0x2b, 0x8e, 0xf9, 0xd0, 0x47, 0x45, 0xc8, 0xf5, 0x3a, 0x2f, + 0x3a, 0xc7, 0xaf, 0x3b, 0x72, 0x2a, 0x58, 0xb4, 0x0e, 0x76, 0x5f, 0x76, 0x5b, 0x67, 0xb2, 0x84, + 0xfe, 0x81, 0x42, 0xaf, 0x13, 0x2f, 0xd3, 0xa8, 0x04, 0xf9, 0x7d, 0x7d, 0xb7, 0xdd, 0x69, 0x77, + 0x0e, 0xe5, 0x4c, 0x70, 0xb2, 0xdb, 0x3e, 0x3a, 0x38, 0xee, 0x75, 0xe5, 0x6c, 0x53, 0xfe, 0x38, + 0xa9, 0x4b, 0x5f, 0x27, 0x75, 0xe9, 0xdb, 0xa4, 0x2e, 0x7d, 0x9f, 0xd4, 0xa5, 0xf3, 0x75, 0xe1, + 0xe8, 0x9d, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x63, 0x59, 0x31, 0x3a, 0x11, 0x07, 0x00, 0x00, } diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/health_check.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/health_check.pb.validate.go new file mode 100644 index 00000000..6efadf6a --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/health_check.pb.validate.go @@ -0,0 +1,504 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/core/health_check.proto +// DO NOT EDIT!!! + +package core + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on HealthCheck with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *HealthCheck) Validate() error { + if m == nil { + return nil + } + + if m.GetTimeout() == nil { + return HealthCheckValidationError{ + Field: "Timeout", + Reason: "value is required", + } + } + + if m.GetInterval() == nil { + return HealthCheckValidationError{ + Field: "Interval", + Reason: "value is required", + } + } + + if v, ok := interface{}(m.GetIntervalJitter()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckValidationError{ + Field: "IntervalJitter", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetUnhealthyThreshold()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckValidationError{ + Field: "UnhealthyThreshold", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetHealthyThreshold()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckValidationError{ + Field: "HealthyThreshold", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetAltPort()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckValidationError{ + Field: "AltPort", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetReuseConnection()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckValidationError{ + Field: "ReuseConnection", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetNoTrafficInterval()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckValidationError{ + Field: "NoTrafficInterval", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + switch m.HealthChecker.(type) { + + case *HealthCheck_HttpHealthCheck_: + + if v, ok := interface{}(m.GetHttpHealthCheck()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckValidationError{ + Field: "HttpHealthCheck", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *HealthCheck_TcpHealthCheck_: + + if v, ok := interface{}(m.GetTcpHealthCheck()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckValidationError{ + Field: "TcpHealthCheck", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *HealthCheck_RedisHealthCheck_: + + if v, ok := interface{}(m.GetRedisHealthCheck()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckValidationError{ + Field: "RedisHealthCheck", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *HealthCheck_GrpcHealthCheck_: + + if v, ok := interface{}(m.GetGrpcHealthCheck()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckValidationError{ + Field: "GrpcHealthCheck", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + default: + return HealthCheckValidationError{ + Field: "HealthChecker", + Reason: "value is required", + } + + } + + return nil +} + +// HealthCheckValidationError is the validation error returned by +// HealthCheck.Validate if the designated constraints aren't met. +type HealthCheckValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HealthCheckValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHealthCheck.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HealthCheckValidationError{} + +// Validate checks the field values on HealthCheck_Payload with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HealthCheck_Payload) Validate() error { + if m == nil { + return nil + } + + switch m.Payload.(type) { + + case *HealthCheck_Payload_Text: + + if len(m.GetText()) < 1 { + return HealthCheck_PayloadValidationError{ + Field: "Text", + Reason: "value length must be at least 1 bytes", + } + } + + case *HealthCheck_Payload_Binary: + // no validation rules for Binary + + default: + return HealthCheck_PayloadValidationError{ + Field: "Payload", + Reason: "value is required", + } + + } + + return nil +} + +// HealthCheck_PayloadValidationError is the validation error returned by +// HealthCheck_Payload.Validate if the designated constraints aren't met. +type HealthCheck_PayloadValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HealthCheck_PayloadValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHealthCheck_Payload.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HealthCheck_PayloadValidationError{} + +// Validate checks the field values on HealthCheck_HttpHealthCheck with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HealthCheck_HttpHealthCheck) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Host + + if len(m.GetPath()) < 1 { + return HealthCheck_HttpHealthCheckValidationError{ + Field: "Path", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetSend()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheck_HttpHealthCheckValidationError{ + Field: "Send", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetReceive()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheck_HttpHealthCheckValidationError{ + Field: "Receive", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for ServiceName + + return nil +} + +// HealthCheck_HttpHealthCheckValidationError is the validation error returned +// by HealthCheck_HttpHealthCheck.Validate if the designated constraints +// aren't met. +type HealthCheck_HttpHealthCheckValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HealthCheck_HttpHealthCheckValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHealthCheck_HttpHealthCheck.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HealthCheck_HttpHealthCheckValidationError{} + +// Validate checks the field values on HealthCheck_TcpHealthCheck with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HealthCheck_TcpHealthCheck) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetSend()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheck_TcpHealthCheckValidationError{ + Field: "Send", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetReceive() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheck_TcpHealthCheckValidationError{ + Field: fmt.Sprintf("Receive[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// HealthCheck_TcpHealthCheckValidationError is the validation error returned +// by HealthCheck_TcpHealthCheck.Validate if the designated constraints aren't met. +type HealthCheck_TcpHealthCheckValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HealthCheck_TcpHealthCheckValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHealthCheck_TcpHealthCheck.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HealthCheck_TcpHealthCheckValidationError{} + +// Validate checks the field values on HealthCheck_RedisHealthCheck with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HealthCheck_RedisHealthCheck) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Key + + return nil +} + +// HealthCheck_RedisHealthCheckValidationError is the validation error returned +// by HealthCheck_RedisHealthCheck.Validate if the designated constraints +// aren't met. +type HealthCheck_RedisHealthCheckValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HealthCheck_RedisHealthCheckValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHealthCheck_RedisHealthCheck.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HealthCheck_RedisHealthCheckValidationError{} + +// Validate checks the field values on HealthCheck_GrpcHealthCheck with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HealthCheck_GrpcHealthCheck) Validate() error { + if m == nil { + return nil + } + + // no validation rules for ServiceName + + return nil +} + +// HealthCheck_GrpcHealthCheckValidationError is the validation error returned +// by HealthCheck_GrpcHealthCheck.Validate if the designated constraints +// aren't met. +type HealthCheck_GrpcHealthCheckValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HealthCheck_GrpcHealthCheckValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHealthCheck_GrpcHealthCheck.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HealthCheck_GrpcHealthCheckValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/http_uri.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/http_uri.pb.validate.go new file mode 100644 index 00000000..df226927 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/http_uri.pb.validate.go @@ -0,0 +1,102 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/core/http_uri.proto +// DO NOT EDIT!!! + +package core + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on HttpUri with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *HttpUri) Validate() error { + if m == nil { + return nil + } + + if len(m.GetUri()) < 1 { + return HttpUriValidationError{ + Field: "Uri", + Reason: "value length must be at least 1 bytes", + } + } + + switch m.HttpUpstreamType.(type) { + + case *HttpUri_Cluster: + + if len(m.GetCluster()) < 1 { + return HttpUriValidationError{ + Field: "Cluster", + Reason: "value length must be at least 1 bytes", + } + } + + default: + return HttpUriValidationError{ + Field: "HttpUpstreamType", + Reason: "value is required", + } + + } + + return nil +} + +// HttpUriValidationError is the validation error returned by HttpUri.Validate +// if the designated constraints aren't met. +type HttpUriValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HttpUriValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHttpUri.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HttpUriValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/protocol.pb.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/protocol.pb.go index 6a54fd45..9bb75422 100644 --- a/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/protocol.pb.go +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/protocol.pb.go @@ -33,7 +33,6 @@ func (*TcpProtocolOptions) ProtoMessage() {} func (*TcpProtocolOptions) Descriptor() ([]byte, []int) { return fileDescriptorProtocol, []int{0} } type HttpProtocolOptions struct { - // [#not-implemented-hide:] // The idle timeout for upstream connection pool connections. The idle timeout is defined as the // period in which there are no active requests. If not set, there is no idle timeout. When the // idle timeout is reached the connection will be closed. Note that request based timeouts mean @@ -59,13 +58,11 @@ type Http1ProtocolOptions struct { // envoy as their HTTP proxy. In Unix, for example, this is typically done by setting the // *http_proxy* environment variable. AllowAbsoluteUrl *google_protobuf.BoolValue `protobuf:"bytes,1,opt,name=allow_absolute_url,json=allowAbsoluteUrl" json:"allow_absolute_url,omitempty"` - // [#not-implemented-hide:] // Handle incoming HTTP/1.0 and HTTP 0.9 requests. // This is off by default, and not fully standards compliant. There is support for pre-HTTP/1.1 // style connect logic, dechunking, and handling lack of client host iff // *default_host_for_http_10* is configured. AcceptHttp_10 bool `protobuf:"varint,2,opt,name=accept_http_10,json=acceptHttp10,proto3" json:"accept_http_10,omitempty"` - // [#not-implemented-hide:] // A default host for HTTP/1.0 requests. This is highly suggested if *accept_http_10* is true as // Envoy does not otherwise support HTTP/1.0 without a Host header. // This is a no-op if *accept_http_10* is not true. diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/protocol.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/protocol.pb.validate.go new file mode 100644 index 00000000..37c70e27 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/core/protocol.pb.validate.go @@ -0,0 +1,322 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/core/protocol.proto +// DO NOT EDIT!!! + +package core + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on TcpProtocolOptions with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *TcpProtocolOptions) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// TcpProtocolOptionsValidationError is the validation error returned by +// TcpProtocolOptions.Validate if the designated constraints aren't met. +type TcpProtocolOptionsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TcpProtocolOptionsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTcpProtocolOptions.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TcpProtocolOptionsValidationError{} + +// Validate checks the field values on HttpProtocolOptions with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HttpProtocolOptions) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetIdleTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpProtocolOptionsValidationError{ + Field: "IdleTimeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// HttpProtocolOptionsValidationError is the validation error returned by +// HttpProtocolOptions.Validate if the designated constraints aren't met. +type HttpProtocolOptionsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HttpProtocolOptionsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHttpProtocolOptions.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HttpProtocolOptionsValidationError{} + +// Validate checks the field values on Http1ProtocolOptions with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *Http1ProtocolOptions) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetAllowAbsoluteUrl()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Http1ProtocolOptionsValidationError{ + Field: "AllowAbsoluteUrl", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for AcceptHttp_10 + + // no validation rules for DefaultHostForHttp_10 + + return nil +} + +// Http1ProtocolOptionsValidationError is the validation error returned by +// Http1ProtocolOptions.Validate if the designated constraints aren't met. +type Http1ProtocolOptionsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Http1ProtocolOptionsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHttp1ProtocolOptions.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Http1ProtocolOptionsValidationError{} + +// Validate checks the field values on Http2ProtocolOptions with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *Http2ProtocolOptions) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetHpackTableSize()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Http2ProtocolOptionsValidationError{ + Field: "HpackTableSize", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if wrapper := m.GetMaxConcurrentStreams(); wrapper != nil { + + if val := wrapper.GetValue(); val < 1 || val > 2147483647 { + return Http2ProtocolOptionsValidationError{ + Field: "MaxConcurrentStreams", + Reason: "value must be inside range [1, 2147483647]", + } + } + + } + + if wrapper := m.GetInitialStreamWindowSize(); wrapper != nil { + + if val := wrapper.GetValue(); val < 65535 || val > 2147483647 { + return Http2ProtocolOptionsValidationError{ + Field: "InitialStreamWindowSize", + Reason: "value must be inside range [65535, 2147483647]", + } + } + + } + + if wrapper := m.GetInitialConnectionWindowSize(); wrapper != nil { + + if val := wrapper.GetValue(); val < 65535 || val > 2147483647 { + return Http2ProtocolOptionsValidationError{ + Field: "InitialConnectionWindowSize", + Reason: "value must be inside range [65535, 2147483647]", + } + } + + } + + return nil +} + +// Http2ProtocolOptionsValidationError is the validation error returned by +// Http2ProtocolOptions.Validate if the designated constraints aren't met. +type Http2ProtocolOptionsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Http2ProtocolOptionsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHttp2ProtocolOptions.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Http2ProtocolOptionsValidationError{} + +// Validate checks the field values on GrpcProtocolOptions with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *GrpcProtocolOptions) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetHttp2ProtocolOptions()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GrpcProtocolOptionsValidationError{ + Field: "Http2ProtocolOptions", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// GrpcProtocolOptionsValidationError is the validation error returned by +// GrpcProtocolOptions.Validate if the designated constraints aren't met. +type GrpcProtocolOptionsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e GrpcProtocolOptionsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGrpcProtocolOptions.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = GrpcProtocolOptionsValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/discovery.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/discovery.pb.validate.go new file mode 100644 index 00000000..f87cc94d --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/discovery.pb.validate.go @@ -0,0 +1,168 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/discovery.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on DiscoveryRequest with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *DiscoveryRequest) Validate() error { + if m == nil { + return nil + } + + // no validation rules for VersionInfo + + if v, ok := interface{}(m.GetNode()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return DiscoveryRequestValidationError{ + Field: "Node", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for TypeUrl + + // no validation rules for ResponseNonce + + if v, ok := interface{}(m.GetErrorDetail()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return DiscoveryRequestValidationError{ + Field: "ErrorDetail", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// DiscoveryRequestValidationError is the validation error returned by +// DiscoveryRequest.Validate if the designated constraints aren't met. +type DiscoveryRequestValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e DiscoveryRequestValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDiscoveryRequest.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = DiscoveryRequestValidationError{} + +// Validate checks the field values on DiscoveryResponse with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *DiscoveryResponse) Validate() error { + if m == nil { + return nil + } + + // no validation rules for VersionInfo + + for idx, item := range m.GetResources() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return DiscoveryResponseValidationError{ + Field: fmt.Sprintf("Resources[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + // no validation rules for Canary + + // no validation rules for TypeUrl + + // no validation rules for Nonce + + return nil +} + +// DiscoveryResponseValidationError is the validation error returned by +// DiscoveryResponse.Validate if the designated constraints aren't met. +type DiscoveryResponseValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e DiscoveryResponseValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDiscoveryResponse.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = DiscoveryResponseValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/eds.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/eds.pb.validate.go new file mode 100644 index 00000000..70a63925 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/eds.pb.validate.go @@ -0,0 +1,159 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/eds.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on ClusterLoadAssignment with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *ClusterLoadAssignment) Validate() error { + if m == nil { + return nil + } + + if len(m.GetClusterName()) < 1 { + return ClusterLoadAssignmentValidationError{ + Field: "ClusterName", + Reason: "value length must be at least 1 bytes", + } + } + + for idx, item := range m.GetEndpoints() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterLoadAssignmentValidationError{ + Field: fmt.Sprintf("Endpoints[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetPolicy()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterLoadAssignmentValidationError{ + Field: "Policy", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// ClusterLoadAssignmentValidationError is the validation error returned by +// ClusterLoadAssignment.Validate if the designated constraints aren't met. +type ClusterLoadAssignmentValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ClusterLoadAssignmentValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClusterLoadAssignment.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ClusterLoadAssignmentValidationError{} + +// Validate checks the field values on ClusterLoadAssignment_Policy with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *ClusterLoadAssignment_Policy) Validate() error { + if m == nil { + return nil + } + + if val := m.GetDropOverload(); val < 0 || val > 100 { + return ClusterLoadAssignment_PolicyValidationError{ + Field: "DropOverload", + Reason: "value must be inside range [0, 100]", + } + } + + return nil +} + +// ClusterLoadAssignment_PolicyValidationError is the validation error returned +// by ClusterLoadAssignment_Policy.Validate if the designated constraints +// aren't met. +type ClusterLoadAssignment_PolicyValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ClusterLoadAssignment_PolicyValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClusterLoadAssignment_Policy.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ClusterLoadAssignment_PolicyValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint/endpoint.pb.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint/endpoint.pb.go index d05f0851..98fdffb2 100644 --- a/github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint/endpoint.pb.go +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint/endpoint.pb.go @@ -136,11 +136,11 @@ type LocalityLbEndpoints struct { // localities at the same priority level to produce the effective percentage // of traffic for the locality. // - // Weights must be specified for either all localities in a given priority - // level or none. - // - // If unspecified, each locality is presumed to have equal weight in a - // cluster. + // Locality weights are only considered when :ref:`locality weighted load + // balancing ` is + // configured. These weights are ignored otherwise. If no weights are + // specificed when locality weighted load balancing is enabled, the cluster is + // assumed to have a weight of 1. // // .. attention:: // diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint/endpoint.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint/endpoint.pb.validate.go new file mode 100644 index 00000000..03f8a5be --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint/endpoint.pb.validate.go @@ -0,0 +1,240 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/endpoint/endpoint.proto +// DO NOT EDIT!!! + +package endpoint + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Endpoint with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Endpoint) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return EndpointValidationError{ + Field: "Address", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// EndpointValidationError is the validation error returned by +// Endpoint.Validate if the designated constraints aren't met. +type EndpointValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e EndpointValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sEndpoint.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = EndpointValidationError{} + +// Validate checks the field values on LbEndpoint with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *LbEndpoint) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetEndpoint()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return LbEndpointValidationError{ + Field: "Endpoint", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for HealthStatus + + if v, ok := interface{}(m.GetMetadata()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return LbEndpointValidationError{ + Field: "Metadata", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if wrapper := m.GetLoadBalancingWeight(); wrapper != nil { + + if val := wrapper.GetValue(); val < 1 || val > 128 { + return LbEndpointValidationError{ + Field: "LoadBalancingWeight", + Reason: "value must be inside range [1, 128]", + } + } + + } + + return nil +} + +// LbEndpointValidationError is the validation error returned by +// LbEndpoint.Validate if the designated constraints aren't met. +type LbEndpointValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e LbEndpointValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sLbEndpoint.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = LbEndpointValidationError{} + +// Validate checks the field values on LocalityLbEndpoints with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *LocalityLbEndpoints) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetLocality()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return LocalityLbEndpointsValidationError{ + Field: "Locality", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetLbEndpoints() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return LocalityLbEndpointsValidationError{ + Field: fmt.Sprintf("LbEndpoints[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if wrapper := m.GetLoadBalancingWeight(); wrapper != nil { + + if val := wrapper.GetValue(); val < 1 || val > 128 { + return LocalityLbEndpointsValidationError{ + Field: "LoadBalancingWeight", + Reason: "value must be inside range [1, 128]", + } + } + + } + + // no validation rules for Priority + + return nil +} + +// LocalityLbEndpointsValidationError is the validation error returned by +// LocalityLbEndpoints.Validate if the designated constraints aren't met. +type LocalityLbEndpointsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e LocalityLbEndpointsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sLocalityLbEndpoints.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = LocalityLbEndpointsValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint/load_report.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint/load_report.pb.validate.go new file mode 100644 index 00000000..45bea01a --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint/load_report.pb.validate.go @@ -0,0 +1,231 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/endpoint/load_report.proto +// DO NOT EDIT!!! + +package endpoint + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on UpstreamLocalityStats with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *UpstreamLocalityStats) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetLocality()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return UpstreamLocalityStatsValidationError{ + Field: "Locality", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for TotalSuccessfulRequests + + // no validation rules for TotalRequestsInProgress + + // no validation rules for TotalErrorRequests + + for idx, item := range m.GetLoadMetricStats() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return UpstreamLocalityStatsValidationError{ + Field: fmt.Sprintf("LoadMetricStats[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + // no validation rules for Priority + + return nil +} + +// UpstreamLocalityStatsValidationError is the validation error returned by +// UpstreamLocalityStats.Validate if the designated constraints aren't met. +type UpstreamLocalityStatsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e UpstreamLocalityStatsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sUpstreamLocalityStats.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = UpstreamLocalityStatsValidationError{} + +// Validate checks the field values on EndpointLoadMetricStats with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *EndpointLoadMetricStats) Validate() error { + if m == nil { + return nil + } + + // no validation rules for MetricName + + // no validation rules for NumRequestsFinishedWithMetric + + // no validation rules for TotalMetricValue + + return nil +} + +// EndpointLoadMetricStatsValidationError is the validation error returned by +// EndpointLoadMetricStats.Validate if the designated constraints aren't met. +type EndpointLoadMetricStatsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e EndpointLoadMetricStatsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sEndpointLoadMetricStats.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = EndpointLoadMetricStatsValidationError{} + +// Validate checks the field values on ClusterStats with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *ClusterStats) Validate() error { + if m == nil { + return nil + } + + if len(m.GetClusterName()) < 1 { + return ClusterStatsValidationError{ + Field: "ClusterName", + Reason: "value length must be at least 1 bytes", + } + } + + if len(m.GetUpstreamLocalityStats()) < 1 { + return ClusterStatsValidationError{ + Field: "UpstreamLocalityStats", + Reason: "value must contain at least 1 item(s)", + } + } + + for idx, item := range m.GetUpstreamLocalityStats() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterStatsValidationError{ + Field: fmt.Sprintf("UpstreamLocalityStats[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + // no validation rules for TotalDroppedRequests + + return nil +} + +// ClusterStatsValidationError is the validation error returned by +// ClusterStats.Validate if the designated constraints aren't met. +type ClusterStatsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ClusterStatsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClusterStats.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ClusterStatsValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/lds.pb.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/lds.pb.go index 3020d533..ecae1c7e 100644 --- a/github.com/envoyproxy/go-control-plane/envoy/api/v2/lds.pb.go +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/lds.pb.go @@ -110,15 +110,29 @@ type Listener struct { // filters are processed sequentially right after a socket has been accepted by the listener, and // before a connection is created. ListenerFilters []envoy_api_v2_listener.ListenerFilter `protobuf:"bytes,9,rep,name=listener_filters,json=listenerFilters" json:"listener_filters"` - // Whether the listener should be set as a transparent socket. When this flag is set to true, - // connections can be redirected to the listener using an *iptables* *TPROXY* target, in which - // case the original source and destination addresses and ports are preserved on accepted - // connections. Requires Envoy to run with the *CAP_NET_ADMIN* capability. Defaults to false. - Transparent bool `protobuf:"varint,10,opt,name=transparent,proto3" json:"transparent,omitempty"` - // [#not-implemented-hide:] Whether the listener should set the IP_FREEBIND socket option. When - // this flag is set to true listeners can be bound to an IP address that is not configured on the - // system running Envoy. Defaults to false. - Freebind bool `protobuf:"varint,11,opt,name=freebind,proto3" json:"freebind,omitempty"` + // [#not-implemented-hide:] + // Whether the listener should be set as a transparent socket. + // When this flag is set to true, connections can be redirected to the listener using an + // *iptables* *TPROXY* target, in which case the original source and destination addresses and + // ports are preserved on accepted connections. This flag should be used in combination with + // :ref:`an original_dst ` :ref:`listener filter + // ` to mark the connections' local addresses as + // "restored." This can be used to hand off each redirected connection to another listener + // associated with the connection's destination address. Direct connections to the socket without + // using *TPROXY* cannot be distinguished from connections redirected using *TPROXY* and are + // therefore treated as if they were redirected. + // When this flag is set to false, the listener's socket is explicitly reset as non-transparent. + // Setting this flag requires Envoy to run with the *CAP_NET_ADMIN* capability. + // When this flag is not set (default), the socket is not modified, i.e. the transparent option + // is neither set nor reset. + Transparent *google_protobuf.BoolValue `protobuf:"bytes,10,opt,name=transparent" json:"transparent,omitempty"` + // [#not-implemented-hide:] Whether the listener should set the *IP_FREEBIND* + // socket option. When this flag is set to true, listeners can be bound to an + // IP address that is not configured on the system running Envoy. When this + // flag is set to false, the option *IP_FREEBIND* is disabled on the socket. + // When this flag is not set (default), the socket is not modified, i.e. the + // option is neither enabled nor disabled. + Freebind *google_protobuf.BoolValue `protobuf:"bytes,11,opt,name=freebind" json:"freebind,omitempty"` } func (m *Listener) Reset() { *m = Listener{} } @@ -189,18 +203,18 @@ func (m *Listener) GetListenerFilters() []envoy_api_v2_listener.ListenerFilter { return nil } -func (m *Listener) GetTransparent() bool { +func (m *Listener) GetTransparent() *google_protobuf.BoolValue { if m != nil { return m.Transparent } - return false + return nil } -func (m *Listener) GetFreebind() bool { +func (m *Listener) GetFreebind() *google_protobuf.BoolValue { if m != nil { return m.Freebind } - return false + return nil } // [#not-implemented-hide:] @@ -295,10 +309,10 @@ func (this *Listener) Equal(that interface{}) bool { return false } } - if this.Transparent != that1.Transparent { + if !this.Transparent.Equal(that1.Transparent) { return false } - if this.Freebind != that1.Freebind { + if !this.Freebind.Equal(that1.Freebind) { return false } return true @@ -570,25 +584,25 @@ func (m *Listener) MarshalTo(dAtA []byte) (int, error) { i += n } } - if m.Transparent { - dAtA[i] = 0x50 + if m.Transparent != nil { + dAtA[i] = 0x52 i++ - if m.Transparent { - dAtA[i] = 1 - } else { - dAtA[i] = 0 + i = encodeVarintLds(dAtA, i, uint64(m.Transparent.Size())) + n6, err := m.Transparent.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err } - i++ + i += n6 } - if m.Freebind { - dAtA[i] = 0x58 + if m.Freebind != nil { + dAtA[i] = 0x5a i++ - if m.Freebind { - dAtA[i] = 1 - } else { - dAtA[i] = 0 + i = encodeVarintLds(dAtA, i, uint64(m.Freebind.Size())) + n7, err := m.Freebind.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err } - i++ + i += n7 } return i, nil } @@ -612,11 +626,11 @@ func (m *Listener_DeprecatedV1) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintLds(dAtA, i, uint64(m.BindToPort.Size())) - n6, err := m.BindToPort.MarshalTo(dAtA[i:]) + n8, err := m.BindToPort.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n6 + i += n8 } return i, nil } @@ -670,11 +684,13 @@ func (m *Listener) Size() (n int) { n += 1 + l + sovLds(uint64(l)) } } - if m.Transparent { - n += 2 + if m.Transparent != nil { + l = m.Transparent.Size() + n += 1 + l + sovLds(uint64(l)) } - if m.Freebind { - n += 2 + if m.Freebind != nil { + l = m.Freebind.Size() + n += 1 + l + sovLds(uint64(l)) } return n } @@ -1004,10 +1020,10 @@ func (m *Listener) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 10: - if wireType != 0 { + if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Transparent", wireType) } - var v int + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowLds @@ -1017,17 +1033,30 @@ func (m *Listener) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= (int(b) & 0x7F) << shift + msglen |= (int(b) & 0x7F) << shift if b < 0x80 { break } } - m.Transparent = bool(v != 0) + if msglen < 0 { + return ErrInvalidLengthLds + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Transparent == nil { + m.Transparent = &google_protobuf.BoolValue{} + } + if err := m.Transparent.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex case 11: - if wireType != 0 { + if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Freebind", wireType) } - var v int + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowLds @@ -1037,12 +1066,25 @@ func (m *Listener) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= (int(b) & 0x7F) << shift + msglen |= (int(b) & 0x7F) << shift if b < 0x80 { break } } - m.Freebind = bool(v != 0) + if msglen < 0 { + return ErrInvalidLengthLds + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Freebind == nil { + m.Freebind = &google_protobuf.BoolValue{} + } + if err := m.Freebind.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipLds(dAtA[iNdEx:]) @@ -1255,50 +1297,50 @@ var ( func init() { proto.RegisterFile("envoy/api/v2/lds.proto", fileDescriptorLds) } var fileDescriptorLds = []byte{ - // 718 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcf, 0x6f, 0x13, 0x39, - 0x18, 0xad, 0xd3, 0x5f, 0x89, 0x93, 0xa6, 0x91, 0x77, 0xb5, 0x1d, 0x65, 0xbb, 0x69, 0x36, 0xbb, - 0x2b, 0x65, 0xf7, 0x30, 0xd9, 0xa6, 0x07, 0xa4, 0x0a, 0x09, 0x35, 0x0d, 0x51, 0x2b, 0xa5, 0x14, - 0x4d, 0x7f, 0x40, 0x4f, 0x23, 0x27, 0xf3, 0x25, 0xb5, 0x34, 0xb1, 0x07, 0xdb, 0x09, 0xca, 0x95, - 0x13, 0xe2, 0x08, 0xff, 0x04, 0x7f, 0x03, 0x27, 0xc4, 0xa9, 0x47, 0x24, 0xee, 0x08, 0x45, 0x5c, - 0x10, 0xff, 0x04, 0x1a, 0x67, 0x66, 0x48, 0xd4, 0x96, 0x13, 0xb7, 0xcf, 0xdf, 0x7b, 0xdf, 0xb3, - 0xfd, 0x9e, 0x67, 0xf0, 0x6f, 0xc0, 0x47, 0x62, 0x5c, 0xa3, 0x01, 0xab, 0x8d, 0xea, 0x35, 0xdf, - 0x53, 0x76, 0x20, 0x85, 0x16, 0x24, 0x67, 0xfa, 0x36, 0x0d, 0x98, 0x3d, 0xaa, 0x17, 0xb7, 0xe6, - 0x58, 0x5d, 0x21, 0xa1, 0x46, 0x3d, 0x4f, 0x82, 0x8a, 0xe8, 0xc5, 0xcd, 0xeb, 0x84, 0x0e, 0x55, - 0x70, 0x23, 0xea, 0x31, 0xd5, 0x15, 0x23, 0x90, 0xe3, 0x08, 0xfd, 0x7b, 0xfe, 0x08, 0x4c, 0x69, - 0xe0, 0x20, 0x93, 0x22, 0xd6, 0xe8, 0x0b, 0xd1, 0xf7, 0xc1, 0xd0, 0x28, 0xe7, 0x42, 0x53, 0xcd, - 0x04, 0x8f, 0xf7, 0x2f, 0x45, 0xa8, 0x59, 0x75, 0x86, 0xbd, 0xda, 0x53, 0x49, 0x83, 0x00, 0x64, - 0x8c, 0x6f, 0x8c, 0xa8, 0xcf, 0x3c, 0xaa, 0xa1, 0x16, 0x17, 0x11, 0xf0, 0x6b, 0x5f, 0xf4, 0x85, - 0x29, 0x6b, 0x61, 0x35, 0xed, 0x56, 0xde, 0xad, 0xe0, 0x74, 0x3b, 0xda, 0x9f, 0x10, 0xbc, 0xc4, - 0xe9, 0x00, 0x2c, 0x54, 0x46, 0xd5, 0x8c, 0x63, 0x6a, 0xd2, 0xc4, 0xab, 0x91, 0x01, 0x56, 0xaa, - 0x8c, 0xaa, 0xd9, 0x7a, 0xd1, 0x9e, 0x35, 0xcc, 0x0e, 0x1d, 0xb0, 0xf7, 0xa6, 0x8c, 0x46, 0xfe, - 0xea, 0xe3, 0xd6, 0xc2, 0x9b, 0x2f, 0x6f, 0x17, 0x97, 0x5f, 0xa0, 0x54, 0x01, 0x39, 0xf1, 0x28, - 0x79, 0x84, 0xd7, 0x7a, 0xcc, 0xd7, 0x20, 0xdd, 0xee, 0x25, 0x65, 0x5c, 0x59, 0x8b, 0xe5, 0xc5, - 0x6a, 0xb6, 0x5e, 0x99, 0xd7, 0x4a, 0x8c, 0x68, 0x19, 0xee, 0x7e, 0x48, 0x9d, 0xd1, 0x7c, 0x89, - 0x52, 0x69, 0xe4, 0xe4, 0x7a, 0xdf, 0x41, 0x45, 0x0e, 0x70, 0x61, 0xa8, 0xc0, 0x15, 0x92, 0xf5, - 0x19, 0xa7, 0xbe, 0xeb, 0x29, 0x6d, 0x2d, 0x45, 0xe7, 0x9c, 0x3a, 0x65, 0xc7, 0x4e, 0xd9, 0x0d, - 0x21, 0xfc, 0x73, 0xea, 0x0f, 0xa1, 0x91, 0xb2, 0x90, 0x93, 0x1f, 0x2a, 0x38, 0x8e, 0xc6, 0x9a, - 0x4a, 0x93, 0x1e, 0xfe, 0x33, 0x08, 0xcf, 0x27, 0x38, 0x87, 0x6e, 0xe8, 0xb8, 0xdb, 0x19, 0xf6, - 0x7a, 0x20, 0x5d, 0x9f, 0x0d, 0x98, 0x76, 0x3b, 0x63, 0x0d, 0xca, 0x5a, 0x36, 0xd2, 0x9b, 0xd7, - 0xa4, 0xcf, 0x0e, 0xb9, 0xde, 0xa9, 0x1b, 0x71, 0xe7, 0x8f, 0x00, 0xe4, 0x7e, 0xa2, 0xd2, 0x30, - 0x22, 0xed, 0x50, 0xa3, 0x11, 0x4a, 0x90, 0x3b, 0x38, 0x3d, 0x00, 0x4d, 0x3d, 0xaa, 0xa9, 0xb5, - 0x62, 0xe4, 0x7e, 0xbf, 0xc1, 0xd1, 0xa3, 0x88, 0xe2, 0x24, 0x64, 0x72, 0x80, 0xd7, 0x3c, 0x08, - 0x24, 0x74, 0xa9, 0x06, 0xcf, 0x1d, 0x6d, 0x5b, 0xab, 0x66, 0xfa, 0xaf, 0xf9, 0xe9, 0x38, 0x4c, - 0xbb, 0x99, 0x70, 0xcf, 0xb7, 0x9d, 0x9c, 0x37, 0xb3, 0x22, 0xf7, 0x30, 0xf6, 0x24, 0x65, 0xdc, - 0xd5, 0xe3, 0x00, 0xac, 0x74, 0x19, 0x55, 0xf3, 0xf5, 0xf2, 0x6d, 0x32, 0x21, 0xf1, 0x74, 0x1c, - 0x80, 0x93, 0xf1, 0xe2, 0x92, 0x9c, 0xe3, 0x42, 0x9c, 0x95, 0x3b, 0x8d, 0x43, 0x59, 0x19, 0x93, - 0xe8, 0x3f, 0xb7, 0x24, 0x1a, 0xeb, 0x4d, 0x93, 0x6d, 0x2c, 0x85, 0xa1, 0x3a, 0xeb, 0xfe, 0x5c, - 0x57, 0x91, 0x32, 0xce, 0x6a, 0x49, 0xb9, 0x0a, 0xa8, 0x04, 0xae, 0x2d, 0x5c, 0x46, 0xd5, 0xb4, - 0x33, 0xdb, 0x22, 0x45, 0x9c, 0xee, 0x49, 0x80, 0x0e, 0xe3, 0x9e, 0x95, 0x35, 0x70, 0xb2, 0x2e, - 0xb6, 0x71, 0x6e, 0xf6, 0xd2, 0xe4, 0x2e, 0xce, 0x85, 0x7d, 0x57, 0x0b, 0x37, 0x10, 0x52, 0x9b, - 0x67, 0xfd, 0xc3, 0x77, 0xe1, 0xe0, 0x90, 0x7f, 0x2a, 0x1e, 0x0a, 0xa9, 0x2b, 0xff, 0xe2, 0x4c, - 0x72, 0x77, 0x92, 0xc5, 0xab, 0xcd, 0xfb, 0xad, 0xbd, 0xb3, 0xf6, 0x69, 0x61, 0x81, 0xac, 0xe3, - 0xec, 0xd1, 0x71, 0xf3, 0xb0, 0x75, 0xe1, 0x1e, 0x3f, 0x68, 0x5f, 0x14, 0x50, 0xfd, 0x2b, 0xc2, - 0x56, 0x7c, 0xc1, 0x66, 0xfc, 0xcd, 0x9f, 0x80, 0x1c, 0xb1, 0x2e, 0x90, 0xc7, 0x78, 0xfd, 0x44, - 0x4b, 0xa0, 0x83, 0x98, 0xa1, 0x48, 0x69, 0xde, 0xa4, 0x64, 0xc4, 0x81, 0x27, 0x43, 0x50, 0xba, - 0xb8, 0x75, 0x2b, 0xae, 0x02, 0xc1, 0x15, 0x54, 0x16, 0xaa, 0xe8, 0x7f, 0x44, 0x86, 0x38, 0xdf, - 0x02, 0xdd, 0xbd, 0xfc, 0x89, 0xc2, 0x95, 0x67, 0x1f, 0x3e, 0xbf, 0x4a, 0x6d, 0x56, 0x36, 0xe6, - 0x7e, 0x5f, 0xbb, 0x71, 0x4e, 0x6a, 0x17, 0xfd, 0xd7, 0xf8, 0xe5, 0xf5, 0xa4, 0x84, 0xae, 0x26, - 0x25, 0xf4, 0x7e, 0x52, 0x42, 0x9f, 0x26, 0x25, 0xf4, 0x1c, 0xa1, 0xce, 0x8a, 0x71, 0x73, 0xe7, - 0x5b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa7, 0xe5, 0xa3, 0x48, 0x66, 0x05, 0x00, 0x00, + // 716 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xcf, 0x6b, 0x13, 0x4d, + 0x18, 0xc7, 0x3b, 0xe9, 0xaf, 0x64, 0x92, 0xa6, 0x61, 0xde, 0x97, 0xb7, 0x4b, 0xde, 0x9a, 0xc6, + 0xa8, 0x10, 0x3d, 0x6c, 0x6c, 0x0a, 0x0a, 0xa5, 0x20, 0x4d, 0x63, 0x68, 0x21, 0xb5, 0xb2, 0xfd, + 0xa1, 0x3d, 0x2d, 0x93, 0xec, 0x93, 0x74, 0x60, 0x33, 0xb3, 0xce, 0x4c, 0x22, 0xb9, 0x7a, 0x12, + 0x8f, 0xfa, 0x4f, 0xf8, 0x37, 0x78, 0xf2, 0xd8, 0xa3, 0xe0, 0x5d, 0x24, 0x78, 0x11, 0xff, 0x03, + 0x4f, 0xb2, 0x9b, 0xdd, 0x35, 0xa1, 0xad, 0xbd, 0x78, 0x7b, 0xf6, 0x79, 0xbe, 0xcf, 0x67, 0x86, + 0xef, 0x97, 0x1d, 0xfc, 0x1f, 0xf0, 0x81, 0x18, 0x56, 0xa8, 0xc7, 0x2a, 0x83, 0x6a, 0xc5, 0x75, + 0x94, 0xe9, 0x49, 0xa1, 0x05, 0xc9, 0x04, 0x7d, 0x93, 0x7a, 0xcc, 0x1c, 0x54, 0xf3, 0x6b, 0x53, + 0xaa, 0xb6, 0x90, 0x50, 0xa1, 0x8e, 0x23, 0x41, 0x85, 0xf2, 0xfc, 0xea, 0x45, 0x41, 0x8b, 0x2a, + 0xb8, 0x74, 0xea, 0x30, 0xd5, 0x16, 0x03, 0x90, 0xc3, 0x70, 0x7a, 0x7b, 0xfa, 0x0a, 0x4c, 0x69, + 0xe0, 0x20, 0xe3, 0x22, 0x62, 0x74, 0x85, 0xe8, 0xba, 0x10, 0xc8, 0x28, 0xe7, 0x42, 0x53, 0xcd, + 0x04, 0x8f, 0xce, 0x2f, 0x84, 0xd3, 0xe0, 0xab, 0xd5, 0xef, 0x54, 0x5e, 0x4a, 0xea, 0x79, 0x20, + 0xa3, 0xf9, 0xca, 0x80, 0xba, 0xcc, 0xa1, 0x1a, 0x2a, 0x51, 0x11, 0x0e, 0xfe, 0xed, 0x8a, 0xae, + 0x08, 0xca, 0x8a, 0x5f, 0x8d, 0xbb, 0xa5, 0x9f, 0x0b, 0x38, 0xd9, 0x0c, 0xcf, 0x27, 0x04, 0xcf, + 0x71, 0xda, 0x03, 0x03, 0x15, 0x51, 0x39, 0x65, 0x05, 0x35, 0xa9, 0xe3, 0xc5, 0xd0, 0x00, 0x23, + 0x51, 0x44, 0xe5, 0x74, 0x35, 0x6f, 0x4e, 0x1a, 0x66, 0xfa, 0x0e, 0x98, 0xdb, 0x63, 0x45, 0x2d, + 0x7b, 0xfe, 0x65, 0x6d, 0xe6, 0xc3, 0xf7, 0x8f, 0xb3, 0xf3, 0x6f, 0x50, 0x22, 0x87, 0xac, 0x68, + 0x95, 0x3c, 0xc3, 0x4b, 0x1d, 0xe6, 0x6a, 0x90, 0x76, 0xfb, 0x8c, 0x32, 0xae, 0x8c, 0xd9, 0xe2, + 0x6c, 0x39, 0x5d, 0x2d, 0x4d, 0xb3, 0x62, 0x23, 0x1a, 0x81, 0x76, 0xc7, 0x97, 0x4e, 0x30, 0xdf, + 0xa2, 0x44, 0x12, 0x59, 0x99, 0xce, 0xef, 0xa1, 0x22, 0xbb, 0x38, 0xd7, 0x57, 0x60, 0x0b, 0xc9, + 0xba, 0x8c, 0x53, 0xd7, 0x76, 0x94, 0x36, 0xe6, 0xc2, 0x7b, 0x8e, 0x9d, 0x32, 0x23, 0xa7, 0xcc, + 0x9a, 0x10, 0xee, 0x09, 0x75, 0xfb, 0x50, 0x4b, 0x18, 0xc8, 0xca, 0xf6, 0x15, 0x1c, 0x84, 0x6b, + 0x75, 0xa5, 0x49, 0x07, 0xdf, 0xf4, 0xfc, 0xfb, 0x09, 0xce, 0xa1, 0xed, 0x3b, 0x6e, 0xb7, 0xfa, + 0x9d, 0x0e, 0x48, 0xdb, 0x65, 0x3d, 0xa6, 0xed, 0xd6, 0x50, 0x83, 0x32, 0xe6, 0x03, 0xf4, 0xea, + 0x05, 0xf4, 0xf1, 0x1e, 0xd7, 0x1b, 0xd5, 0x00, 0x6e, 0xdd, 0xf0, 0x40, 0xee, 0xc4, 0x94, 0x5a, + 0x00, 0x69, 0xfa, 0x8c, 0x9a, 0x8f, 0x20, 0x0f, 0x71, 0xb2, 0x07, 0x9a, 0x3a, 0x54, 0x53, 0x63, + 0x21, 0xc0, 0xfd, 0x7f, 0x89, 0xa3, 0xfb, 0xa1, 0xc4, 0x8a, 0xc5, 0x64, 0x17, 0x2f, 0x39, 0xe0, + 0x49, 0x68, 0x53, 0x0d, 0x8e, 0x3d, 0x58, 0x37, 0x16, 0x83, 0xed, 0x5b, 0xd3, 0xdb, 0x51, 0x98, + 0x66, 0x3d, 0xd6, 0x9e, 0xac, 0x5b, 0x19, 0x67, 0xe2, 0x8b, 0x3c, 0xc2, 0xd8, 0x91, 0x94, 0x71, + 0x5b, 0x0f, 0x3d, 0x30, 0x92, 0x45, 0x54, 0xce, 0x56, 0x8b, 0x57, 0x61, 0x7c, 0xe1, 0xd1, 0xd0, + 0x03, 0x2b, 0xe5, 0x44, 0x25, 0x39, 0xc1, 0xb9, 0x28, 0x2b, 0x7b, 0x1c, 0x87, 0x32, 0x52, 0x41, + 0xa2, 0x77, 0xae, 0x48, 0x34, 0xe2, 0x8d, 0x93, 0xad, 0xcd, 0xf9, 0xa1, 0x5a, 0xcb, 0xee, 0x54, + 0x57, 0x91, 0x2d, 0x9c, 0xd6, 0x92, 0x72, 0xe5, 0x51, 0x09, 0x5c, 0x1b, 0xf8, 0xba, 0x20, 0xad, + 0x49, 0x39, 0x79, 0x80, 0x93, 0x1d, 0x09, 0xd0, 0x62, 0xdc, 0x31, 0xd2, 0xd7, 0xae, 0xc6, 0xda, + 0x7c, 0x13, 0x67, 0x26, 0xcd, 0x22, 0x5b, 0x38, 0xe3, 0xf7, 0x6d, 0x2d, 0x6c, 0x4f, 0x48, 0x1d, + 0xfc, 0x0e, 0x7f, 0x66, 0x61, 0x5f, 0x7f, 0x24, 0x9e, 0x0a, 0xa9, 0x4b, 0x77, 0x71, 0x2a, 0xf6, + 0x8c, 0xa4, 0xf1, 0x62, 0xfd, 0x71, 0x63, 0xfb, 0xb8, 0x79, 0x94, 0x9b, 0x21, 0xcb, 0x38, 0xbd, + 0x7f, 0x50, 0xdf, 0x6b, 0x9c, 0xda, 0x07, 0x4f, 0x9a, 0xa7, 0x39, 0x54, 0xfd, 0x81, 0xb0, 0x11, + 0x19, 0x53, 0x8f, 0xde, 0x8a, 0x43, 0x90, 0x03, 0xd6, 0x06, 0xf2, 0x1c, 0x2f, 0x1f, 0x6a, 0x09, + 0xb4, 0x17, 0x29, 0x14, 0x29, 0x4c, 0x9b, 0x1b, 0xaf, 0x58, 0xf0, 0xa2, 0x0f, 0x4a, 0xe7, 0xd7, + 0xae, 0x9c, 0x2b, 0x4f, 0x70, 0x05, 0xa5, 0x99, 0x32, 0xba, 0x8f, 0x48, 0x1f, 0x67, 0x1b, 0xa0, + 0xdb, 0x67, 0x7f, 0x11, 0x5c, 0x7a, 0xf5, 0xf9, 0xdb, 0xbb, 0xc4, 0x6a, 0x69, 0x65, 0xea, 0xd9, + 0xdb, 0x8c, 0xf2, 0x55, 0x9b, 0xe8, 0x5e, 0xed, 0x9f, 0xf7, 0xa3, 0x02, 0x3a, 0x1f, 0x15, 0xd0, + 0xa7, 0x51, 0x01, 0x7d, 0x1d, 0x15, 0xd0, 0x6b, 0x84, 0x5a, 0x0b, 0x81, 0x9b, 0x1b, 0xbf, 0x02, + 0x00, 0x00, 0xff, 0xff, 0x7b, 0x51, 0x8d, 0x4f, 0x9e, 0x05, 0x00, 0x00, } diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/lds.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/lds.pb.validate.go new file mode 100644 index 00000000..274dde2b --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/lds.pb.validate.go @@ -0,0 +1,239 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/lds.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Listener with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Listener) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Name + + if v, ok := interface{}(m.GetAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ListenerValidationError{ + Field: "Address", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if len(m.GetFilterChains()) < 1 { + return ListenerValidationError{ + Field: "FilterChains", + Reason: "value must contain at least 1 item(s)", + } + } + + for idx, item := range m.GetFilterChains() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ListenerValidationError{ + Field: fmt.Sprintf("FilterChains[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetUseOriginalDst()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ListenerValidationError{ + Field: "UseOriginalDst", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetPerConnectionBufferLimitBytes()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ListenerValidationError{ + Field: "PerConnectionBufferLimitBytes", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetMetadata()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ListenerValidationError{ + Field: "Metadata", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetDeprecatedV1()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ListenerValidationError{ + Field: "DeprecatedV1", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for DrainType + + for idx, item := range m.GetListenerFilters() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ListenerValidationError{ + Field: fmt.Sprintf("ListenerFilters[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetTransparent()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ListenerValidationError{ + Field: "Transparent", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetFreebind()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ListenerValidationError{ + Field: "Freebind", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// ListenerValidationError is the validation error returned by +// Listener.Validate if the designated constraints aren't met. +type ListenerValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ListenerValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sListener.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ListenerValidationError{} + +// Validate checks the field values on Listener_DeprecatedV1 with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *Listener_DeprecatedV1) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetBindToPort()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Listener_DeprecatedV1ValidationError{ + Field: "BindToPort", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// Listener_DeprecatedV1ValidationError is the validation error returned by +// Listener_DeprecatedV1.Validate if the designated constraints aren't met. +type Listener_DeprecatedV1ValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Listener_DeprecatedV1ValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sListener_DeprecatedV1.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Listener_DeprecatedV1ValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/listener/listener.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/listener/listener.pb.validate.go new file mode 100644 index 00000000..5f79e0dd --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/listener/listener.pb.validate.go @@ -0,0 +1,422 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/listener/listener.proto +// DO NOT EDIT!!! + +package listener + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Filter with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Filter) Validate() error { + if m == nil { + return nil + } + + if len(m.GetName()) < 1 { + return FilterValidationError{ + Field: "Name", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FilterValidationError{ + Field: "Config", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetDeprecatedV1()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FilterValidationError{ + Field: "DeprecatedV1", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// FilterValidationError is the validation error returned by Filter.Validate if +// the designated constraints aren't met. +type FilterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e FilterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sFilter.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = FilterValidationError{} + +// Validate checks the field values on FilterChainMatch with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *FilterChainMatch) Validate() error { + if m == nil { + return nil + } + + for idx, item := range m.GetPrefixRanges() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FilterChainMatchValidationError{ + Field: fmt.Sprintf("PrefixRanges[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + // no validation rules for AddressSuffix + + if v, ok := interface{}(m.GetSuffixLen()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FilterChainMatchValidationError{ + Field: "SuffixLen", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetSourcePrefixRanges() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FilterChainMatchValidationError{ + Field: fmt.Sprintf("SourcePrefixRanges[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetSourcePorts() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FilterChainMatchValidationError{ + Field: fmt.Sprintf("SourcePorts[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetDestinationPort()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FilterChainMatchValidationError{ + Field: "DestinationPort", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// FilterChainMatchValidationError is the validation error returned by +// FilterChainMatch.Validate if the designated constraints aren't met. +type FilterChainMatchValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e FilterChainMatchValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sFilterChainMatch.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = FilterChainMatchValidationError{} + +// Validate checks the field values on FilterChain with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *FilterChain) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetFilterChainMatch()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FilterChainValidationError{ + Field: "FilterChainMatch", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetTlsContext()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FilterChainValidationError{ + Field: "TlsContext", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetFilters() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FilterChainValidationError{ + Field: fmt.Sprintf("Filters[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetUseProxyProto()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FilterChainValidationError{ + Field: "UseProxyProto", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetMetadata()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FilterChainValidationError{ + Field: "Metadata", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetTransportSocket()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return FilterChainValidationError{ + Field: "TransportSocket", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// FilterChainValidationError is the validation error returned by +// FilterChain.Validate if the designated constraints aren't met. +type FilterChainValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e FilterChainValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sFilterChain.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = FilterChainValidationError{} + +// Validate checks the field values on ListenerFilter with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *ListenerFilter) Validate() error { + if m == nil { + return nil + } + + if len(m.GetName()) < 1 { + return ListenerFilterValidationError{ + Field: "Name", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ListenerFilterValidationError{ + Field: "Config", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// ListenerFilterValidationError is the validation error returned by +// ListenerFilter.Validate if the designated constraints aren't met. +type ListenerFilterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ListenerFilterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sListenerFilter.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ListenerFilterValidationError{} + +// Validate checks the field values on Filter_DeprecatedV1 with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *Filter_DeprecatedV1) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Type + + return nil +} + +// Filter_DeprecatedV1ValidationError is the validation error returned by +// Filter_DeprecatedV1.Validate if the designated constraints aren't met. +type Filter_DeprecatedV1ValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Filter_DeprecatedV1ValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sFilter_DeprecatedV1.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Filter_DeprecatedV1ValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/ratelimit/ratelimit.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/ratelimit/ratelimit.pb.validate.go new file mode 100644 index 00000000..34480f7b --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/ratelimit/ratelimit.pb.validate.go @@ -0,0 +1,155 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/ratelimit/ratelimit.proto +// DO NOT EDIT!!! + +package ratelimit + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on RateLimitDescriptor with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RateLimitDescriptor) Validate() error { + if m == nil { + return nil + } + + if len(m.GetEntries()) < 1 { + return RateLimitDescriptorValidationError{ + Field: "Entries", + Reason: "value must contain at least 1 item(s)", + } + } + + for idx, item := range m.GetEntries() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimitDescriptorValidationError{ + Field: fmt.Sprintf("Entries[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// RateLimitDescriptorValidationError is the validation error returned by +// RateLimitDescriptor.Validate if the designated constraints aren't met. +type RateLimitDescriptorValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimitDescriptorValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimitDescriptor.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimitDescriptorValidationError{} + +// Validate checks the field values on RateLimitDescriptor_Entry with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RateLimitDescriptor_Entry) Validate() error { + if m == nil { + return nil + } + + if len(m.GetKey()) < 1 { + return RateLimitDescriptor_EntryValidationError{ + Field: "Key", + Reason: "value length must be at least 1 bytes", + } + } + + if len(m.GetValue()) < 1 { + return RateLimitDescriptor_EntryValidationError{ + Field: "Value", + Reason: "value length must be at least 1 bytes", + } + } + + return nil +} + +// RateLimitDescriptor_EntryValidationError is the validation error returned by +// RateLimitDescriptor_Entry.Validate if the designated constraints aren't met. +type RateLimitDescriptor_EntryValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimitDescriptor_EntryValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimitDescriptor_Entry.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimitDescriptor_EntryValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/rds.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/rds.pb.validate.go new file mode 100644 index 00000000..a7a52165 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/rds.pb.validate.go @@ -0,0 +1,134 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/rds.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on RouteConfiguration with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RouteConfiguration) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Name + + for idx, item := range m.GetVirtualHosts() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteConfigurationValidationError{ + Field: fmt.Sprintf("VirtualHosts[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetResponseHeadersToAdd() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteConfigurationValidationError{ + Field: fmt.Sprintf("ResponseHeadersToAdd[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetRequestHeadersToAdd() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteConfigurationValidationError{ + Field: fmt.Sprintf("RequestHeadersToAdd[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetValidateClusters()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteConfigurationValidationError{ + Field: "ValidateClusters", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// RouteConfigurationValidationError is the validation error returned by +// RouteConfiguration.Validate if the designated constraints aren't met. +type RouteConfigurationValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RouteConfigurationValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRouteConfiguration.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RouteConfigurationValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/route/route.pb.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/route/route.pb.go index 9f957b29..6c063230 100644 --- a/github.com/envoyproxy/go-control-plane/envoy/api/v2/route/route.pb.go +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/route/route.pb.go @@ -2417,7 +2417,6 @@ type HeaderMatcher struct { // * The regex *\d{3}* does not match the value *1234* // * The regex *\d{3}* does not match the value *123.456* Regex *google_protobuf1.BoolValue `protobuf:"bytes,3,opt,name=regex" json:"regex,omitempty"` - // [#not-implemented-hide:] // Specifies how the header match will be performed to route the request. // If header_match_specifier is absent, a request that has the // :ref:`envoy_api_msg_route.HeaderMatcher.name` header will match, regardless of the header's diff --git a/github.com/envoyproxy/go-control-plane/envoy/api/v2/route/route.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/api/v2/route/route.pb.validate.go new file mode 100644 index 00000000..cc9b4c67 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/api/v2/route/route.pb.validate.go @@ -0,0 +1,2152 @@ +// Code generated by protoc-gen-validate +// source: envoy/api/v2/route/route.proto +// DO NOT EDIT!!! + +package route + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on VirtualHost with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *VirtualHost) Validate() error { + if m == nil { + return nil + } + + if len(m.GetName()) < 1 { + return VirtualHostValidationError{ + Field: "Name", + Reason: "value length must be at least 1 bytes", + } + } + + if len(m.GetDomains()) < 1 { + return VirtualHostValidationError{ + Field: "Domains", + Reason: "value must contain at least 1 item(s)", + } + } + + for idx, item := range m.GetRoutes() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return VirtualHostValidationError{ + Field: fmt.Sprintf("Routes[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + // no validation rules for RequireTls + + for idx, item := range m.GetVirtualClusters() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return VirtualHostValidationError{ + Field: fmt.Sprintf("VirtualClusters[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetRateLimits() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return VirtualHostValidationError{ + Field: fmt.Sprintf("RateLimits[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetRequestHeadersToAdd() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return VirtualHostValidationError{ + Field: fmt.Sprintf("RequestHeadersToAdd[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetResponseHeadersToAdd() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return VirtualHostValidationError{ + Field: fmt.Sprintf("ResponseHeadersToAdd[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetCors()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return VirtualHostValidationError{ + Field: "Cors", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetAuth()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return VirtualHostValidationError{ + Field: "Auth", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// VirtualHostValidationError is the validation error returned by +// VirtualHost.Validate if the designated constraints aren't met. +type VirtualHostValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e VirtualHostValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sVirtualHost.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = VirtualHostValidationError{} + +// Validate checks the field values on Route with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Route) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetMatch()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteValidationError{ + Field: "Match", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetMetadata()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteValidationError{ + Field: "Metadata", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetDecorator()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteValidationError{ + Field: "Decorator", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetAuth()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteValidationError{ + Field: "Auth", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + switch m.Action.(type) { + + case *Route_Route: + + if v, ok := interface{}(m.GetRoute()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteValidationError{ + Field: "Route", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *Route_Redirect: + + if v, ok := interface{}(m.GetRedirect()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteValidationError{ + Field: "Redirect", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *Route_DirectResponse: + + if v, ok := interface{}(m.GetDirectResponse()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteValidationError{ + Field: "DirectResponse", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + default: + return RouteValidationError{ + Field: "Action", + Reason: "value is required", + } + + } + + return nil +} + +// RouteValidationError is the validation error returned by Route.Validate if +// the designated constraints aren't met. +type RouteValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RouteValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRoute.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RouteValidationError{} + +// Validate checks the field values on WeightedCluster with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *WeightedCluster) Validate() error { + if m == nil { + return nil + } + + if len(m.GetClusters()) < 1 { + return WeightedClusterValidationError{ + Field: "Clusters", + Reason: "value must contain at least 1 item(s)", + } + } + + for idx, item := range m.GetClusters() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return WeightedClusterValidationError{ + Field: fmt.Sprintf("Clusters[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if wrapper := m.GetTotalWeight(); wrapper != nil { + + if wrapper.GetValue() < 1 { + return WeightedClusterValidationError{ + Field: "TotalWeight", + Reason: "value must be greater than or equal to 1", + } + } + + } + + // no validation rules for RuntimeKeyPrefix + + return nil +} + +// WeightedClusterValidationError is the validation error returned by +// WeightedCluster.Validate if the designated constraints aren't met. +type WeightedClusterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e WeightedClusterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sWeightedCluster.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = WeightedClusterValidationError{} + +// Validate checks the field values on RouteMatch with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *RouteMatch) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetCaseSensitive()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteMatchValidationError{ + Field: "CaseSensitive", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetRuntime()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteMatchValidationError{ + Field: "Runtime", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetHeaders() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteMatchValidationError{ + Field: fmt.Sprintf("Headers[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetQueryParameters() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteMatchValidationError{ + Field: fmt.Sprintf("QueryParameters[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + switch m.PathSpecifier.(type) { + + case *RouteMatch_Prefix: + // no validation rules for Prefix + + case *RouteMatch_Path: + // no validation rules for Path + + case *RouteMatch_Regex: + // no validation rules for Regex + + default: + return RouteMatchValidationError{ + Field: "PathSpecifier", + Reason: "value is required", + } + + } + + return nil +} + +// RouteMatchValidationError is the validation error returned by +// RouteMatch.Validate if the designated constraints aren't met. +type RouteMatchValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RouteMatchValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRouteMatch.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RouteMatchValidationError{} + +// Validate checks the field values on CorsPolicy with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *CorsPolicy) Validate() error { + if m == nil { + return nil + } + + // no validation rules for AllowMethods + + // no validation rules for AllowHeaders + + // no validation rules for ExposeHeaders + + // no validation rules for MaxAge + + if v, ok := interface{}(m.GetAllowCredentials()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CorsPolicyValidationError{ + Field: "AllowCredentials", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetEnabled()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CorsPolicyValidationError{ + Field: "Enabled", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// CorsPolicyValidationError is the validation error returned by +// CorsPolicy.Validate if the designated constraints aren't met. +type CorsPolicyValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e CorsPolicyValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCorsPolicy.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = CorsPolicyValidationError{} + +// Validate checks the field values on RouteAction with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *RouteAction) Validate() error { + if m == nil { + return nil + } + + if _, ok := RouteAction_ClusterNotFoundResponseCode_name[int32(m.GetClusterNotFoundResponseCode())]; !ok { + return RouteActionValidationError{ + Field: "ClusterNotFoundResponseCode", + Reason: "value must be one of the defined enum values", + } + } + + if v, ok := interface{}(m.GetMetadataMatch()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteActionValidationError{ + Field: "MetadataMatch", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for PrefixRewrite + + if v, ok := interface{}(m.GetTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteActionValidationError{ + Field: "Timeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetRetryPolicy()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteActionValidationError{ + Field: "RetryPolicy", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetRequestMirrorPolicy()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteActionValidationError{ + Field: "RequestMirrorPolicy", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for Priority + + for idx, item := range m.GetRequestHeadersToAdd() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteActionValidationError{ + Field: fmt.Sprintf("RequestHeadersToAdd[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetResponseHeadersToAdd() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteActionValidationError{ + Field: fmt.Sprintf("ResponseHeadersToAdd[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetRateLimits() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteActionValidationError{ + Field: fmt.Sprintf("RateLimits[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetIncludeVhRateLimits()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteActionValidationError{ + Field: "IncludeVhRateLimits", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetHashPolicy() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteActionValidationError{ + Field: fmt.Sprintf("HashPolicy[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetUseWebsocket()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteActionValidationError{ + Field: "UseWebsocket", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetCors()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteActionValidationError{ + Field: "Cors", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + switch m.ClusterSpecifier.(type) { + + case *RouteAction_Cluster: + // no validation rules for Cluster + + case *RouteAction_ClusterHeader: + // no validation rules for ClusterHeader + + case *RouteAction_WeightedClusters: + + if v, ok := interface{}(m.GetWeightedClusters()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteActionValidationError{ + Field: "WeightedClusters", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + default: + return RouteActionValidationError{ + Field: "ClusterSpecifier", + Reason: "value is required", + } + + } + + switch m.HostRewriteSpecifier.(type) { + + case *RouteAction_HostRewrite: + // no validation rules for HostRewrite + + case *RouteAction_AutoHostRewrite: + + if v, ok := interface{}(m.GetAutoHostRewrite()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteActionValidationError{ + Field: "AutoHostRewrite", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// RouteActionValidationError is the validation error returned by +// RouteAction.Validate if the designated constraints aren't met. +type RouteActionValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RouteActionValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRouteAction.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RouteActionValidationError{} + +// Validate checks the field values on RedirectAction with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *RedirectAction) Validate() error { + if m == nil { + return nil + } + + // no validation rules for HostRedirect + + if _, ok := RedirectAction_RedirectResponseCode_name[int32(m.GetResponseCode())]; !ok { + return RedirectActionValidationError{ + Field: "ResponseCode", + Reason: "value must be one of the defined enum values", + } + } + + // no validation rules for HttpsRedirect + + // no validation rules for StripQuery + + switch m.PathRewriteSpecifier.(type) { + + case *RedirectAction_PathRedirect: + // no validation rules for PathRedirect + + case *RedirectAction_PrefixRewrite: + // no validation rules for PrefixRewrite + + } + + return nil +} + +// RedirectActionValidationError is the validation error returned by +// RedirectAction.Validate if the designated constraints aren't met. +type RedirectActionValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RedirectActionValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRedirectAction.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RedirectActionValidationError{} + +// Validate checks the field values on DirectResponseAction with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *DirectResponseAction) Validate() error { + if m == nil { + return nil + } + + if val := m.GetStatus(); val < 100 || val >= 600 { + return DirectResponseActionValidationError{ + Field: "Status", + Reason: "value must be inside range [100, 600)", + } + } + + if v, ok := interface{}(m.GetBody()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return DirectResponseActionValidationError{ + Field: "Body", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// DirectResponseActionValidationError is the validation error returned by +// DirectResponseAction.Validate if the designated constraints aren't met. +type DirectResponseActionValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e DirectResponseActionValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDirectResponseAction.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = DirectResponseActionValidationError{} + +// Validate checks the field values on Decorator with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Decorator) Validate() error { + if m == nil { + return nil + } + + if len(m.GetOperation()) < 1 { + return DecoratorValidationError{ + Field: "Operation", + Reason: "value length must be at least 1 bytes", + } + } + + return nil +} + +// DecoratorValidationError is the validation error returned by +// Decorator.Validate if the designated constraints aren't met. +type DecoratorValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e DecoratorValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDecorator.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = DecoratorValidationError{} + +// Validate checks the field values on VirtualCluster with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *VirtualCluster) Validate() error { + if m == nil { + return nil + } + + if len(m.GetPattern()) < 1 { + return VirtualClusterValidationError{ + Field: "Pattern", + Reason: "value length must be at least 1 bytes", + } + } + + if len(m.GetName()) < 1 { + return VirtualClusterValidationError{ + Field: "Name", + Reason: "value length must be at least 1 bytes", + } + } + + // no validation rules for Method + + return nil +} + +// VirtualClusterValidationError is the validation error returned by +// VirtualCluster.Validate if the designated constraints aren't met. +type VirtualClusterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e VirtualClusterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sVirtualCluster.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = VirtualClusterValidationError{} + +// Validate checks the field values on RateLimit with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *RateLimit) Validate() error { + if m == nil { + return nil + } + + if wrapper := m.GetStage(); wrapper != nil { + + if wrapper.GetValue() > 10 { + return RateLimitValidationError{ + Field: "Stage", + Reason: "value must be less than or equal to 10", + } + } + + } + + // no validation rules for DisableKey + + if len(m.GetActions()) < 1 { + return RateLimitValidationError{ + Field: "Actions", + Reason: "value must contain at least 1 item(s)", + } + } + + for idx, item := range m.GetActions() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimitValidationError{ + Field: fmt.Sprintf("Actions[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// RateLimitValidationError is the validation error returned by +// RateLimit.Validate if the designated constraints aren't met. +type RateLimitValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimitValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimit.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimitValidationError{} + +// Validate checks the field values on HeaderMatcher with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *HeaderMatcher) Validate() error { + if m == nil { + return nil + } + + if len(m.GetName()) < 1 { + return HeaderMatcherValidationError{ + Field: "Name", + Reason: "value length must be at least 1 bytes", + } + } + + // no validation rules for Value + + if v, ok := interface{}(m.GetRegex()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HeaderMatcherValidationError{ + Field: "Regex", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + switch m.HeaderMatchSpecifier.(type) { + + case *HeaderMatcher_ExactMatch: + // no validation rules for ExactMatch + + case *HeaderMatcher_RegexMatch: + // no validation rules for RegexMatch + + case *HeaderMatcher_RangeMatch: + + if v, ok := interface{}(m.GetRangeMatch()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HeaderMatcherValidationError{ + Field: "RangeMatch", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// HeaderMatcherValidationError is the validation error returned by +// HeaderMatcher.Validate if the designated constraints aren't met. +type HeaderMatcherValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HeaderMatcherValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHeaderMatcher.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HeaderMatcherValidationError{} + +// Validate checks the field values on QueryParameterMatcher with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *QueryParameterMatcher) Validate() error { + if m == nil { + return nil + } + + if len(m.GetName()) < 1 { + return QueryParameterMatcherValidationError{ + Field: "Name", + Reason: "value length must be at least 1 bytes", + } + } + + // no validation rules for Value + + if v, ok := interface{}(m.GetRegex()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return QueryParameterMatcherValidationError{ + Field: "Regex", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// QueryParameterMatcherValidationError is the validation error returned by +// QueryParameterMatcher.Validate if the designated constraints aren't met. +type QueryParameterMatcherValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e QueryParameterMatcherValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sQueryParameterMatcher.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = QueryParameterMatcherValidationError{} + +// Validate checks the field values on WeightedCluster_ClusterWeight with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *WeightedCluster_ClusterWeight) Validate() error { + if m == nil { + return nil + } + + if len(m.GetName()) < 1 { + return WeightedCluster_ClusterWeightValidationError{ + Field: "Name", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetWeight()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return WeightedCluster_ClusterWeightValidationError{ + Field: "Weight", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetMetadataMatch()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return WeightedCluster_ClusterWeightValidationError{ + Field: "MetadataMatch", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetRequestHeadersToAdd() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return WeightedCluster_ClusterWeightValidationError{ + Field: fmt.Sprintf("RequestHeadersToAdd[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetResponseHeadersToAdd() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return WeightedCluster_ClusterWeightValidationError{ + Field: fmt.Sprintf("ResponseHeadersToAdd[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// WeightedCluster_ClusterWeightValidationError is the validation error +// returned by WeightedCluster_ClusterWeight.Validate if the designated +// constraints aren't met. +type WeightedCluster_ClusterWeightValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e WeightedCluster_ClusterWeightValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sWeightedCluster_ClusterWeight.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = WeightedCluster_ClusterWeightValidationError{} + +// Validate checks the field values on RouteAction_RetryPolicy with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RouteAction_RetryPolicy) Validate() error { + if m == nil { + return nil + } + + // no validation rules for RetryOn + + if v, ok := interface{}(m.GetNumRetries()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteAction_RetryPolicyValidationError{ + Field: "NumRetries", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetPerTryTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteAction_RetryPolicyValidationError{ + Field: "PerTryTimeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// RouteAction_RetryPolicyValidationError is the validation error returned by +// RouteAction_RetryPolicy.Validate if the designated constraints aren't met. +type RouteAction_RetryPolicyValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RouteAction_RetryPolicyValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRouteAction_RetryPolicy.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RouteAction_RetryPolicyValidationError{} + +// Validate checks the field values on RouteAction_RequestMirrorPolicy with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RouteAction_RequestMirrorPolicy) Validate() error { + if m == nil { + return nil + } + + if len(m.GetCluster()) < 1 { + return RouteAction_RequestMirrorPolicyValidationError{ + Field: "Cluster", + Reason: "value length must be at least 1 bytes", + } + } + + // no validation rules for RuntimeKey + + return nil +} + +// RouteAction_RequestMirrorPolicyValidationError is the validation error +// returned by RouteAction_RequestMirrorPolicy.Validate if the designated +// constraints aren't met. +type RouteAction_RequestMirrorPolicyValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RouteAction_RequestMirrorPolicyValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRouteAction_RequestMirrorPolicy.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RouteAction_RequestMirrorPolicyValidationError{} + +// Validate checks the field values on RouteAction_HashPolicy with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RouteAction_HashPolicy) Validate() error { + if m == nil { + return nil + } + + switch m.PolicySpecifier.(type) { + + case *RouteAction_HashPolicy_Header_: + + if v, ok := interface{}(m.GetHeader()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteAction_HashPolicyValidationError{ + Field: "Header", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *RouteAction_HashPolicy_Cookie_: + + if v, ok := interface{}(m.GetCookie()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteAction_HashPolicyValidationError{ + Field: "Cookie", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *RouteAction_HashPolicy_ConnectionProperties_: + + if v, ok := interface{}(m.GetConnectionProperties()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteAction_HashPolicyValidationError{ + Field: "ConnectionProperties", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + default: + return RouteAction_HashPolicyValidationError{ + Field: "PolicySpecifier", + Reason: "value is required", + } + + } + + return nil +} + +// RouteAction_HashPolicyValidationError is the validation error returned by +// RouteAction_HashPolicy.Validate if the designated constraints aren't met. +type RouteAction_HashPolicyValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RouteAction_HashPolicyValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRouteAction_HashPolicy.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RouteAction_HashPolicyValidationError{} + +// Validate checks the field values on RouteAction_HashPolicy_Header with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RouteAction_HashPolicy_Header) Validate() error { + if m == nil { + return nil + } + + if len(m.GetHeaderName()) < 1 { + return RouteAction_HashPolicy_HeaderValidationError{ + Field: "HeaderName", + Reason: "value length must be at least 1 bytes", + } + } + + return nil +} + +// RouteAction_HashPolicy_HeaderValidationError is the validation error +// returned by RouteAction_HashPolicy_Header.Validate if the designated +// constraints aren't met. +type RouteAction_HashPolicy_HeaderValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RouteAction_HashPolicy_HeaderValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRouteAction_HashPolicy_Header.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RouteAction_HashPolicy_HeaderValidationError{} + +// Validate checks the field values on RouteAction_HashPolicy_Cookie with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RouteAction_HashPolicy_Cookie) Validate() error { + if m == nil { + return nil + } + + if len(m.GetName()) < 1 { + return RouteAction_HashPolicy_CookieValidationError{ + Field: "Name", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetTtl()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouteAction_HashPolicy_CookieValidationError{ + Field: "Ttl", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// RouteAction_HashPolicy_CookieValidationError is the validation error +// returned by RouteAction_HashPolicy_Cookie.Validate if the designated +// constraints aren't met. +type RouteAction_HashPolicy_CookieValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RouteAction_HashPolicy_CookieValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRouteAction_HashPolicy_Cookie.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RouteAction_HashPolicy_CookieValidationError{} + +// Validate checks the field values on +// RouteAction_HashPolicy_ConnectionProperties with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *RouteAction_HashPolicy_ConnectionProperties) Validate() error { + if m == nil { + return nil + } + + // no validation rules for SourceIp + + return nil +} + +// RouteAction_HashPolicy_ConnectionPropertiesValidationError is the validation +// error returned by RouteAction_HashPolicy_ConnectionProperties.Validate if +// the designated constraints aren't met. +type RouteAction_HashPolicy_ConnectionPropertiesValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RouteAction_HashPolicy_ConnectionPropertiesValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRouteAction_HashPolicy_ConnectionProperties.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RouteAction_HashPolicy_ConnectionPropertiesValidationError{} + +// Validate checks the field values on RateLimit_Action with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *RateLimit_Action) Validate() error { + if m == nil { + return nil + } + + switch m.ActionSpecifier.(type) { + + case *RateLimit_Action_SourceCluster_: + + if v, ok := interface{}(m.GetSourceCluster()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimit_ActionValidationError{ + Field: "SourceCluster", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *RateLimit_Action_DestinationCluster_: + + if v, ok := interface{}(m.GetDestinationCluster()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimit_ActionValidationError{ + Field: "DestinationCluster", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *RateLimit_Action_RequestHeaders_: + + if v, ok := interface{}(m.GetRequestHeaders()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimit_ActionValidationError{ + Field: "RequestHeaders", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *RateLimit_Action_RemoteAddress_: + + if v, ok := interface{}(m.GetRemoteAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimit_ActionValidationError{ + Field: "RemoteAddress", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *RateLimit_Action_GenericKey_: + + if v, ok := interface{}(m.GetGenericKey()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimit_ActionValidationError{ + Field: "GenericKey", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *RateLimit_Action_HeaderValueMatch_: + + if v, ok := interface{}(m.GetHeaderValueMatch()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimit_ActionValidationError{ + Field: "HeaderValueMatch", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + default: + return RateLimit_ActionValidationError{ + Field: "ActionSpecifier", + Reason: "value is required", + } + + } + + return nil +} + +// RateLimit_ActionValidationError is the validation error returned by +// RateLimit_Action.Validate if the designated constraints aren't met. +type RateLimit_ActionValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimit_ActionValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimit_Action.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimit_ActionValidationError{} + +// Validate checks the field values on RateLimit_Action_SourceCluster with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RateLimit_Action_SourceCluster) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// RateLimit_Action_SourceClusterValidationError is the validation error +// returned by RateLimit_Action_SourceCluster.Validate if the designated +// constraints aren't met. +type RateLimit_Action_SourceClusterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimit_Action_SourceClusterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimit_Action_SourceCluster.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimit_Action_SourceClusterValidationError{} + +// Validate checks the field values on RateLimit_Action_DestinationCluster with +// the rules defined in the proto definition for this message. If any rules +// are violated, an error is returned. +func (m *RateLimit_Action_DestinationCluster) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// RateLimit_Action_DestinationClusterValidationError is the validation error +// returned by RateLimit_Action_DestinationCluster.Validate if the designated +// constraints aren't met. +type RateLimit_Action_DestinationClusterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimit_Action_DestinationClusterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimit_Action_DestinationCluster.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimit_Action_DestinationClusterValidationError{} + +// Validate checks the field values on RateLimit_Action_RequestHeaders with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RateLimit_Action_RequestHeaders) Validate() error { + if m == nil { + return nil + } + + if len(m.GetHeaderName()) < 1 { + return RateLimit_Action_RequestHeadersValidationError{ + Field: "HeaderName", + Reason: "value length must be at least 1 bytes", + } + } + + if len(m.GetDescriptorKey()) < 1 { + return RateLimit_Action_RequestHeadersValidationError{ + Field: "DescriptorKey", + Reason: "value length must be at least 1 bytes", + } + } + + return nil +} + +// RateLimit_Action_RequestHeadersValidationError is the validation error +// returned by RateLimit_Action_RequestHeaders.Validate if the designated +// constraints aren't met. +type RateLimit_Action_RequestHeadersValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimit_Action_RequestHeadersValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimit_Action_RequestHeaders.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimit_Action_RequestHeadersValidationError{} + +// Validate checks the field values on RateLimit_Action_RemoteAddress with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RateLimit_Action_RemoteAddress) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// RateLimit_Action_RemoteAddressValidationError is the validation error +// returned by RateLimit_Action_RemoteAddress.Validate if the designated +// constraints aren't met. +type RateLimit_Action_RemoteAddressValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimit_Action_RemoteAddressValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimit_Action_RemoteAddress.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimit_Action_RemoteAddressValidationError{} + +// Validate checks the field values on RateLimit_Action_GenericKey with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RateLimit_Action_GenericKey) Validate() error { + if m == nil { + return nil + } + + if len(m.GetDescriptorValue()) < 1 { + return RateLimit_Action_GenericKeyValidationError{ + Field: "DescriptorValue", + Reason: "value length must be at least 1 bytes", + } + } + + return nil +} + +// RateLimit_Action_GenericKeyValidationError is the validation error returned +// by RateLimit_Action_GenericKey.Validate if the designated constraints +// aren't met. +type RateLimit_Action_GenericKeyValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimit_Action_GenericKeyValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimit_Action_GenericKey.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimit_Action_GenericKeyValidationError{} + +// Validate checks the field values on RateLimit_Action_HeaderValueMatch with +// the rules defined in the proto definition for this message. If any rules +// are violated, an error is returned. +func (m *RateLimit_Action_HeaderValueMatch) Validate() error { + if m == nil { + return nil + } + + if len(m.GetDescriptorValue()) < 1 { + return RateLimit_Action_HeaderValueMatchValidationError{ + Field: "DescriptorValue", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetExpectMatch()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimit_Action_HeaderValueMatchValidationError{ + Field: "ExpectMatch", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if len(m.GetHeaders()) < 1 { + return RateLimit_Action_HeaderValueMatchValidationError{ + Field: "Headers", + Reason: "value must contain at least 1 item(s)", + } + } + + for idx, item := range m.GetHeaders() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimit_Action_HeaderValueMatchValidationError{ + Field: fmt.Sprintf("Headers[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// RateLimit_Action_HeaderValueMatchValidationError is the validation error +// returned by RateLimit_Action_HeaderValueMatch.Validate if the designated +// constraints aren't met. +type RateLimit_Action_HeaderValueMatchValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimit_Action_HeaderValueMatchValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimit_Action_HeaderValueMatch.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimit_Action_HeaderValueMatchValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/accesslog/v2/als.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/accesslog/v2/als.pb.validate.go new file mode 100644 index 00000000..9c9a222a --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/accesslog/v2/als.pb.validate.go @@ -0,0 +1,219 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/accesslog/v2/als.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on TcpGrpcAccessLogConfig with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *TcpGrpcAccessLogConfig) Validate() error { + if m == nil { + return nil + } + + if m.GetCommonConfig() == nil { + return TcpGrpcAccessLogConfigValidationError{ + Field: "CommonConfig", + Reason: "value is required", + } + } + + if v, ok := interface{}(m.GetCommonConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TcpGrpcAccessLogConfigValidationError{ + Field: "CommonConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// TcpGrpcAccessLogConfigValidationError is the validation error returned by +// TcpGrpcAccessLogConfig.Validate if the designated constraints aren't met. +type TcpGrpcAccessLogConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TcpGrpcAccessLogConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTcpGrpcAccessLogConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TcpGrpcAccessLogConfigValidationError{} + +// Validate checks the field values on HttpGrpcAccessLogConfig with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HttpGrpcAccessLogConfig) Validate() error { + if m == nil { + return nil + } + + if m.GetCommonConfig() == nil { + return HttpGrpcAccessLogConfigValidationError{ + Field: "CommonConfig", + Reason: "value is required", + } + } + + if v, ok := interface{}(m.GetCommonConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpGrpcAccessLogConfigValidationError{ + Field: "CommonConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// HttpGrpcAccessLogConfigValidationError is the validation error returned by +// HttpGrpcAccessLogConfig.Validate if the designated constraints aren't met. +type HttpGrpcAccessLogConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HttpGrpcAccessLogConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHttpGrpcAccessLogConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HttpGrpcAccessLogConfigValidationError{} + +// Validate checks the field values on CommonGrpcAccessLogConfig with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *CommonGrpcAccessLogConfig) Validate() error { + if m == nil { + return nil + } + + if len(m.GetLogName()) < 1 { + return CommonGrpcAccessLogConfigValidationError{ + Field: "LogName", + Reason: "value length must be at least 1 bytes", + } + } + + if m.GetGrpcService() == nil { + return CommonGrpcAccessLogConfigValidationError{ + Field: "GrpcService", + Reason: "value is required", + } + } + + if v, ok := interface{}(m.GetGrpcService()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CommonGrpcAccessLogConfigValidationError{ + Field: "GrpcService", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// CommonGrpcAccessLogConfigValidationError is the validation error returned by +// CommonGrpcAccessLogConfig.Validate if the designated constraints aren't met. +type CommonGrpcAccessLogConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e CommonGrpcAccessLogConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCommonGrpcAccessLogConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = CommonGrpcAccessLogConfigValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/bootstrap/v2/bootstrap.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/bootstrap/v2/bootstrap.pb.validate.go new file mode 100644 index 00000000..e3a958af --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/bootstrap/v2/bootstrap.pb.validate.go @@ -0,0 +1,737 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/bootstrap/v2/bootstrap.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Bootstrap with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Bootstrap) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetNode()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BootstrapValidationError{ + Field: "Node", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetStaticResources()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BootstrapValidationError{ + Field: "StaticResources", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetDynamicResources()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BootstrapValidationError{ + Field: "DynamicResources", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetClusterManager()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BootstrapValidationError{ + Field: "ClusterManager", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for FlagsPath + + for idx, item := range m.GetStatsSinks() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BootstrapValidationError{ + Field: fmt.Sprintf("StatsSinks[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetStatsConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BootstrapValidationError{ + Field: "StatsConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetStatsFlushInterval()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BootstrapValidationError{ + Field: "StatsFlushInterval", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetWatchdog()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BootstrapValidationError{ + Field: "Watchdog", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetTracing()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BootstrapValidationError{ + Field: "Tracing", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetRateLimitService()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BootstrapValidationError{ + Field: "RateLimitService", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetRuntime()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BootstrapValidationError{ + Field: "Runtime", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetAdmin()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return BootstrapValidationError{ + Field: "Admin", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// BootstrapValidationError is the validation error returned by +// Bootstrap.Validate if the designated constraints aren't met. +type BootstrapValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e BootstrapValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sBootstrap.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = BootstrapValidationError{} + +// Validate checks the field values on Admin with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Admin) Validate() error { + if m == nil { + return nil + } + + if len(m.GetAccessLogPath()) < 1 { + return AdminValidationError{ + Field: "AccessLogPath", + Reason: "value length must be at least 1 bytes", + } + } + + // no validation rules for ProfilePath + + if v, ok := interface{}(m.GetAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AdminValidationError{ + Field: "Address", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// AdminValidationError is the validation error returned by Admin.Validate if +// the designated constraints aren't met. +type AdminValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AdminValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAdmin.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AdminValidationError{} + +// Validate checks the field values on ClusterManager with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *ClusterManager) Validate() error { + if m == nil { + return nil + } + + // no validation rules for LocalClusterName + + if v, ok := interface{}(m.GetOutlierDetection()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterManagerValidationError{ + Field: "OutlierDetection", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetUpstreamBindConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterManagerValidationError{ + Field: "UpstreamBindConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetLoadStatsConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterManagerValidationError{ + Field: "LoadStatsConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// ClusterManagerValidationError is the validation error returned by +// ClusterManager.Validate if the designated constraints aren't met. +type ClusterManagerValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ClusterManagerValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClusterManager.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ClusterManagerValidationError{} + +// Validate checks the field values on Watchdog with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Watchdog) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetMissTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return WatchdogValidationError{ + Field: "MissTimeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetMegamissTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return WatchdogValidationError{ + Field: "MegamissTimeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetKillTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return WatchdogValidationError{ + Field: "KillTimeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetMultikillTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return WatchdogValidationError{ + Field: "MultikillTimeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// WatchdogValidationError is the validation error returned by +// Watchdog.Validate if the designated constraints aren't met. +type WatchdogValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e WatchdogValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sWatchdog.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = WatchdogValidationError{} + +// Validate checks the field values on Runtime with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Runtime) Validate() error { + if m == nil { + return nil + } + + if len(m.GetSymlinkRoot()) < 1 { + return RuntimeValidationError{ + Field: "SymlinkRoot", + Reason: "value length must be at least 1 bytes", + } + } + + // no validation rules for Subdirectory + + // no validation rules for OverrideSubdirectory + + return nil +} + +// RuntimeValidationError is the validation error returned by Runtime.Validate +// if the designated constraints aren't met. +type RuntimeValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RuntimeValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRuntime.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RuntimeValidationError{} + +// Validate checks the field values on Bootstrap_StaticResources with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *Bootstrap_StaticResources) Validate() error { + if m == nil { + return nil + } + + for idx, item := range m.GetListeners() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Bootstrap_StaticResourcesValidationError{ + Field: fmt.Sprintf("Listeners[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetClusters() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Bootstrap_StaticResourcesValidationError{ + Field: fmt.Sprintf("Clusters[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetSecrets() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Bootstrap_StaticResourcesValidationError{ + Field: fmt.Sprintf("Secrets[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// Bootstrap_StaticResourcesValidationError is the validation error returned by +// Bootstrap_StaticResources.Validate if the designated constraints aren't met. +type Bootstrap_StaticResourcesValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Bootstrap_StaticResourcesValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sBootstrap_StaticResources.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Bootstrap_StaticResourcesValidationError{} + +// Validate checks the field values on Bootstrap_DynamicResources with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *Bootstrap_DynamicResources) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetLdsConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Bootstrap_DynamicResourcesValidationError{ + Field: "LdsConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetCdsConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Bootstrap_DynamicResourcesValidationError{ + Field: "CdsConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetAdsConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Bootstrap_DynamicResourcesValidationError{ + Field: "AdsConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetDeprecatedV1()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Bootstrap_DynamicResourcesValidationError{ + Field: "DeprecatedV1", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// Bootstrap_DynamicResourcesValidationError is the validation error returned +// by Bootstrap_DynamicResources.Validate if the designated constraints aren't met. +type Bootstrap_DynamicResourcesValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Bootstrap_DynamicResourcesValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sBootstrap_DynamicResources.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Bootstrap_DynamicResourcesValidationError{} + +// Validate checks the field values on Bootstrap_DynamicResources_DeprecatedV1 +// with the rules defined in the proto definition for this message. If any +// rules are violated, an error is returned. +func (m *Bootstrap_DynamicResources_DeprecatedV1) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetSdsConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Bootstrap_DynamicResources_DeprecatedV1ValidationError{ + Field: "SdsConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// Bootstrap_DynamicResources_DeprecatedV1ValidationError is the validation +// error returned by Bootstrap_DynamicResources_DeprecatedV1.Validate if the +// designated constraints aren't met. +type Bootstrap_DynamicResources_DeprecatedV1ValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Bootstrap_DynamicResources_DeprecatedV1ValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sBootstrap_DynamicResources_DeprecatedV1.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Bootstrap_DynamicResources_DeprecatedV1ValidationError{} + +// Validate checks the field values on ClusterManager_OutlierDetection with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *ClusterManager_OutlierDetection) Validate() error { + if m == nil { + return nil + } + + // no validation rules for EventLogPath + + return nil +} + +// ClusterManager_OutlierDetectionValidationError is the validation error +// returned by ClusterManager_OutlierDetection.Validate if the designated +// constraints aren't met. +type ClusterManager_OutlierDetectionValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ClusterManager_OutlierDetectionValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClusterManager_OutlierDetection.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ClusterManager_OutlierDetectionValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/accesslog/v2/accesslog.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/accesslog/v2/accesslog.pb.validate.go new file mode 100644 index 00000000..5b68adda --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/accesslog/v2/accesslog.pb.validate.go @@ -0,0 +1,1370 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/accesslog/v2/accesslog.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on AccessLogCommon with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *AccessLogCommon) Validate() error { + if m == nil { + return nil + } + + if m.GetSampleRate() > 1 { + return AccessLogCommonValidationError{ + Field: "SampleRate", + Reason: "value must be less than or equal to 1", + } + } + + if v, ok := interface{}(m.GetDownstreamRemoteAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "DownstreamRemoteAddress", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetDownstreamLocalAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "DownstreamLocalAddress", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetTlsProperties()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "TlsProperties", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetStartTime()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "StartTime", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetTimeToLastRxByte()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "TimeToLastRxByte", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetTimeToFirstUpstreamTxByte()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "TimeToFirstUpstreamTxByte", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetTimeToLastUpstreamTxByte()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "TimeToLastUpstreamTxByte", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetTimeToFirstUpstreamRxByte()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "TimeToFirstUpstreamRxByte", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetTimeToLastUpstreamRxByte()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "TimeToLastUpstreamRxByte", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetTimeToFirstDownstreamTxByte()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "TimeToFirstDownstreamTxByte", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetTimeToLastDownstreamTxByte()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "TimeToLastDownstreamTxByte", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetUpstreamRemoteAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "UpstreamRemoteAddress", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetUpstreamLocalAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "UpstreamLocalAddress", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for UpstreamCluster + + if v, ok := interface{}(m.GetResponseFlags()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "ResponseFlags", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetMetadata()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogCommonValidationError{ + Field: "Metadata", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// AccessLogCommonValidationError is the validation error returned by +// AccessLogCommon.Validate if the designated constraints aren't met. +type AccessLogCommonValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AccessLogCommonValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAccessLogCommon.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AccessLogCommonValidationError{} + +// Validate checks the field values on ResponseFlags with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *ResponseFlags) Validate() error { + if m == nil { + return nil + } + + // no validation rules for FailedLocalHealthcheck + + // no validation rules for NoHealthyUpstream + + // no validation rules for UpstreamRequestTimeout + + // no validation rules for LocalReset + + // no validation rules for UpstreamRemoteReset + + // no validation rules for UpstreamConnectionFailure + + // no validation rules for UpstreamConnectionTermination + + // no validation rules for UpstreamOverflow + + // no validation rules for NoRouteFound + + // no validation rules for DelayInjected + + // no validation rules for FaultInjected + + // no validation rules for RateLimited + + if v, ok := interface{}(m.GetUnauthorizedDetails()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ResponseFlagsValidationError{ + Field: "UnauthorizedDetails", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// ResponseFlagsValidationError is the validation error returned by +// ResponseFlags.Validate if the designated constraints aren't met. +type ResponseFlagsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ResponseFlagsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sResponseFlags.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ResponseFlagsValidationError{} + +// Validate checks the field values on TLSProperties with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *TLSProperties) Validate() error { + if m == nil { + return nil + } + + // no validation rules for TlsVersion + + if v, ok := interface{}(m.GetTlsCipherSuite()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TLSPropertiesValidationError{ + Field: "TlsCipherSuite", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for TlsSniHostname + + return nil +} + +// TLSPropertiesValidationError is the validation error returned by +// TLSProperties.Validate if the designated constraints aren't met. +type TLSPropertiesValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TLSPropertiesValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTLSProperties.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TLSPropertiesValidationError{} + +// Validate checks the field values on TCPAccessLogEntry with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *TCPAccessLogEntry) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetCommonProperties()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TCPAccessLogEntryValidationError{ + Field: "CommonProperties", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// TCPAccessLogEntryValidationError is the validation error returned by +// TCPAccessLogEntry.Validate if the designated constraints aren't met. +type TCPAccessLogEntryValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TCPAccessLogEntryValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTCPAccessLogEntry.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TCPAccessLogEntryValidationError{} + +// Validate checks the field values on HTTPRequestProperties with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HTTPRequestProperties) Validate() error { + if m == nil { + return nil + } + + // no validation rules for RequestMethod + + // no validation rules for Scheme + + // no validation rules for Authority + + if v, ok := interface{}(m.GetPort()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HTTPRequestPropertiesValidationError{ + Field: "Port", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for Path + + // no validation rules for UserAgent + + // no validation rules for Referer + + // no validation rules for ForwardedFor + + // no validation rules for RequestId + + // no validation rules for OriginalPath + + // no validation rules for RequestHeadersBytes + + // no validation rules for RequestBodyBytes + + // no validation rules for RequestHeaders + + return nil +} + +// HTTPRequestPropertiesValidationError is the validation error returned by +// HTTPRequestProperties.Validate if the designated constraints aren't met. +type HTTPRequestPropertiesValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HTTPRequestPropertiesValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHTTPRequestProperties.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HTTPRequestPropertiesValidationError{} + +// Validate checks the field values on HTTPResponseProperties with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HTTPResponseProperties) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetResponseCode()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HTTPResponsePropertiesValidationError{ + Field: "ResponseCode", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for ResponseHeadersBytes + + // no validation rules for ResponseBodyBytes + + // no validation rules for ResponseHeaders + + return nil +} + +// HTTPResponsePropertiesValidationError is the validation error returned by +// HTTPResponseProperties.Validate if the designated constraints aren't met. +type HTTPResponsePropertiesValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HTTPResponsePropertiesValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHTTPResponseProperties.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HTTPResponsePropertiesValidationError{} + +// Validate checks the field values on HTTPAccessLogEntry with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HTTPAccessLogEntry) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetCommonProperties()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HTTPAccessLogEntryValidationError{ + Field: "CommonProperties", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for ProtocolVersion + + if v, ok := interface{}(m.GetRequest()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HTTPAccessLogEntryValidationError{ + Field: "Request", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetResponse()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HTTPAccessLogEntryValidationError{ + Field: "Response", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// HTTPAccessLogEntryValidationError is the validation error returned by +// HTTPAccessLogEntry.Validate if the designated constraints aren't met. +type HTTPAccessLogEntryValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HTTPAccessLogEntryValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHTTPAccessLogEntry.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HTTPAccessLogEntryValidationError{} + +// Validate checks the field values on AccessLog with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *AccessLog) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Name + + if v, ok := interface{}(m.GetFilter()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogValidationError{ + Field: "Filter", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogValidationError{ + Field: "Config", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// AccessLogValidationError is the validation error returned by +// AccessLog.Validate if the designated constraints aren't met. +type AccessLogValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AccessLogValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAccessLog.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AccessLogValidationError{} + +// Validate checks the field values on AccessLogFilter with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *AccessLogFilter) Validate() error { + if m == nil { + return nil + } + + switch m.FilterSpecifier.(type) { + + case *AccessLogFilter_StatusCodeFilter: + + if v, ok := interface{}(m.GetStatusCodeFilter()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogFilterValidationError{ + Field: "StatusCodeFilter", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *AccessLogFilter_DurationFilter: + + if v, ok := interface{}(m.GetDurationFilter()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogFilterValidationError{ + Field: "DurationFilter", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *AccessLogFilter_NotHealthCheckFilter: + + if v, ok := interface{}(m.GetNotHealthCheckFilter()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogFilterValidationError{ + Field: "NotHealthCheckFilter", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *AccessLogFilter_TraceableFilter: + + if v, ok := interface{}(m.GetTraceableFilter()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogFilterValidationError{ + Field: "TraceableFilter", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *AccessLogFilter_RuntimeFilter: + + if v, ok := interface{}(m.GetRuntimeFilter()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogFilterValidationError{ + Field: "RuntimeFilter", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *AccessLogFilter_AndFilter: + + if v, ok := interface{}(m.GetAndFilter()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogFilterValidationError{ + Field: "AndFilter", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *AccessLogFilter_OrFilter: + + if v, ok := interface{}(m.GetOrFilter()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AccessLogFilterValidationError{ + Field: "OrFilter", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + default: + return AccessLogFilterValidationError{ + Field: "FilterSpecifier", + Reason: "value is required", + } + + } + + return nil +} + +// AccessLogFilterValidationError is the validation error returned by +// AccessLogFilter.Validate if the designated constraints aren't met. +type AccessLogFilterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AccessLogFilterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAccessLogFilter.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AccessLogFilterValidationError{} + +// Validate checks the field values on ComparisonFilter with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *ComparisonFilter) Validate() error { + if m == nil { + return nil + } + + if _, ok := ComparisonFilter_Op_name[int32(m.GetOp())]; !ok { + return ComparisonFilterValidationError{ + Field: "Op", + Reason: "value must be one of the defined enum values", + } + } + + if v, ok := interface{}(m.GetValue()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ComparisonFilterValidationError{ + Field: "Value", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// ComparisonFilterValidationError is the validation error returned by +// ComparisonFilter.Validate if the designated constraints aren't met. +type ComparisonFilterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ComparisonFilterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sComparisonFilter.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ComparisonFilterValidationError{} + +// Validate checks the field values on StatusCodeFilter with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *StatusCodeFilter) Validate() error { + if m == nil { + return nil + } + + if m.GetComparison() == nil { + return StatusCodeFilterValidationError{ + Field: "Comparison", + Reason: "value is required", + } + } + + if v, ok := interface{}(m.GetComparison()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StatusCodeFilterValidationError{ + Field: "Comparison", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// StatusCodeFilterValidationError is the validation error returned by +// StatusCodeFilter.Validate if the designated constraints aren't met. +type StatusCodeFilterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StatusCodeFilterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStatusCodeFilter.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StatusCodeFilterValidationError{} + +// Validate checks the field values on DurationFilter with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *DurationFilter) Validate() error { + if m == nil { + return nil + } + + if m.GetComparison() == nil { + return DurationFilterValidationError{ + Field: "Comparison", + Reason: "value is required", + } + } + + if v, ok := interface{}(m.GetComparison()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return DurationFilterValidationError{ + Field: "Comparison", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// DurationFilterValidationError is the validation error returned by +// DurationFilter.Validate if the designated constraints aren't met. +type DurationFilterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e DurationFilterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDurationFilter.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = DurationFilterValidationError{} + +// Validate checks the field values on NotHealthCheckFilter with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *NotHealthCheckFilter) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// NotHealthCheckFilterValidationError is the validation error returned by +// NotHealthCheckFilter.Validate if the designated constraints aren't met. +type NotHealthCheckFilterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e NotHealthCheckFilterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sNotHealthCheckFilter.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = NotHealthCheckFilterValidationError{} + +// Validate checks the field values on TraceableFilter with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *TraceableFilter) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// TraceableFilterValidationError is the validation error returned by +// TraceableFilter.Validate if the designated constraints aren't met. +type TraceableFilterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TraceableFilterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTraceableFilter.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TraceableFilterValidationError{} + +// Validate checks the field values on RuntimeFilter with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *RuntimeFilter) Validate() error { + if m == nil { + return nil + } + + if len(m.GetRuntimeKey()) < 1 { + return RuntimeFilterValidationError{ + Field: "RuntimeKey", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetPercentSampled()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RuntimeFilterValidationError{ + Field: "PercentSampled", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for UseIndependentRandomness + + return nil +} + +// RuntimeFilterValidationError is the validation error returned by +// RuntimeFilter.Validate if the designated constraints aren't met. +type RuntimeFilterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RuntimeFilterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRuntimeFilter.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RuntimeFilterValidationError{} + +// Validate checks the field values on AndFilter with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *AndFilter) Validate() error { + if m == nil { + return nil + } + + if len(m.GetFilters()) < 2 { + return AndFilterValidationError{ + Field: "Filters", + Reason: "value must contain at least 2 item(s)", + } + } + + for idx, item := range m.GetFilters() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AndFilterValidationError{ + Field: fmt.Sprintf("Filters[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// AndFilterValidationError is the validation error returned by +// AndFilter.Validate if the designated constraints aren't met. +type AndFilterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AndFilterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAndFilter.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AndFilterValidationError{} + +// Validate checks the field values on OrFilter with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *OrFilter) Validate() error { + if m == nil { + return nil + } + + if len(m.GetFilters()) < 2 { + return OrFilterValidationError{ + Field: "Filters", + Reason: "value must contain at least 2 item(s)", + } + } + + for idx, item := range m.GetFilters() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return OrFilterValidationError{ + Field: fmt.Sprintf("Filters[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// OrFilterValidationError is the validation error returned by +// OrFilter.Validate if the designated constraints aren't met. +type OrFilterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e OrFilterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sOrFilter.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = OrFilterValidationError{} + +// Validate checks the field values on FileAccessLog with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *FileAccessLog) Validate() error { + if m == nil { + return nil + } + + if len(m.GetPath()) < 1 { + return FileAccessLogValidationError{ + Field: "Path", + Reason: "value length must be at least 1 bytes", + } + } + + // no validation rules for Format + + return nil +} + +// FileAccessLogValidationError is the validation error returned by +// FileAccessLog.Validate if the designated constraints aren't met. +type FileAccessLogValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e FileAccessLogValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sFileAccessLog.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = FileAccessLogValidationError{} + +// Validate checks the field values on ResponseFlags_Unauthorized with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *ResponseFlags_Unauthorized) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Reason + + return nil +} + +// ResponseFlags_UnauthorizedValidationError is the validation error returned +// by ResponseFlags_Unauthorized.Validate if the designated constraints aren't met. +type ResponseFlags_UnauthorizedValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ResponseFlags_UnauthorizedValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sResponseFlags_Unauthorized.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ResponseFlags_UnauthorizedValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/fault/v2/fault.pb.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/fault/v2/fault.pb.go index 1a2cbef1..57767d29 100644 --- a/github.com/envoyproxy/go-control-plane/envoy/config/filter/fault/v2/fault.pb.go +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/fault/v2/fault.pb.go @@ -66,9 +66,9 @@ type FaultDelay struct { // An integer between 0-100 indicating the percentage of operations/connection requests // on which the delay will be injected. Percent uint32 `protobuf:"varint,2,opt,name=percent,proto3" json:"percent,omitempty"` - // Types that are valid to be assigned to FaultDelayType: + // Types that are valid to be assigned to FaultDelaySecifier: // *FaultDelay_FixedDelay - FaultDelayType isFaultDelay_FaultDelayType `protobuf_oneof:"fault_delay_type"` + FaultDelaySecifier isFaultDelay_FaultDelaySecifier `protobuf_oneof:"fault_delay_secifier"` } func (m *FaultDelay) Reset() { *m = FaultDelay{} } @@ -76,8 +76,8 @@ func (m *FaultDelay) String() string { return proto.CompactTextString func (*FaultDelay) ProtoMessage() {} func (*FaultDelay) Descriptor() ([]byte, []int) { return fileDescriptorFault, []int{0} } -type isFaultDelay_FaultDelayType interface { - isFaultDelay_FaultDelayType() +type isFaultDelay_FaultDelaySecifier interface { + isFaultDelay_FaultDelaySecifier() MarshalTo([]byte) (int, error) Size() int } @@ -86,11 +86,11 @@ type FaultDelay_FixedDelay struct { FixedDelay *time.Duration `protobuf:"bytes,3,opt,name=fixed_delay,json=fixedDelay,oneof,stdduration"` } -func (*FaultDelay_FixedDelay) isFaultDelay_FaultDelayType() {} +func (*FaultDelay_FixedDelay) isFaultDelay_FaultDelaySecifier() {} -func (m *FaultDelay) GetFaultDelayType() isFaultDelay_FaultDelayType { +func (m *FaultDelay) GetFaultDelaySecifier() isFaultDelay_FaultDelaySecifier { if m != nil { - return m.FaultDelayType + return m.FaultDelaySecifier } return nil } @@ -110,7 +110,7 @@ func (m *FaultDelay) GetPercent() uint32 { } func (m *FaultDelay) GetFixedDelay() *time.Duration { - if x, ok := m.GetFaultDelayType().(*FaultDelay_FixedDelay); ok { + if x, ok := m.GetFaultDelaySecifier().(*FaultDelay_FixedDelay); ok { return x.FixedDelay } return nil @@ -125,8 +125,8 @@ func (*FaultDelay) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) er func _FaultDelay_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { m := msg.(*FaultDelay) - // fault_delay_type - switch x := m.FaultDelayType.(type) { + // fault_delay_secifier + switch x := m.FaultDelaySecifier.(type) { case *FaultDelay_FixedDelay: _ = b.EncodeVarint(3<<3 | proto.WireBytes) dAtA, err := github_com_gogo_protobuf_types.StdDurationMarshal(*x.FixedDelay) @@ -138,7 +138,7 @@ func _FaultDelay_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { } case nil: default: - return fmt.Errorf("FaultDelay.FaultDelayType has unexpected type %T", x) + return fmt.Errorf("FaultDelay.FaultDelaySecifier has unexpected type %T", x) } return nil } @@ -146,7 +146,7 @@ func _FaultDelay_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { func _FaultDelay_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { m := msg.(*FaultDelay) switch tag { - case 3: // fault_delay_type.fixed_delay + case 3: // fault_delay_secifier.fixed_delay if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } @@ -158,7 +158,7 @@ func _FaultDelay_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buf if err2 := github_com_gogo_protobuf_types.StdDurationUnmarshal(c, x); err2 != nil { return true, err } - m.FaultDelayType = &FaultDelay_FixedDelay{c} + m.FaultDelaySecifier = &FaultDelay_FixedDelay{c} return true, err default: return false, nil @@ -167,8 +167,8 @@ func _FaultDelay_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buf func _FaultDelay_OneofSizer(msg proto.Message) (n int) { m := msg.(*FaultDelay) - // fault_delay_type - switch x := m.FaultDelayType.(type) { + // fault_delay_secifier + switch x := m.FaultDelaySecifier.(type) { case *FaultDelay_FixedDelay: s := github_com_gogo_protobuf_types.SizeOfStdDuration(*x.FixedDelay) n += proto.SizeVarint(3<<3 | proto.WireBytes) @@ -210,8 +210,8 @@ func (m *FaultDelay) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintFault(dAtA, i, uint64(m.Percent)) } - if m.FaultDelayType != nil { - nn1, err := m.FaultDelayType.MarshalTo(dAtA[i:]) + if m.FaultDelaySecifier != nil { + nn1, err := m.FaultDelaySecifier.MarshalTo(dAtA[i:]) if err != nil { return 0, err } @@ -252,8 +252,8 @@ func (m *FaultDelay) Size() (n int) { if m.Percent != 0 { n += 1 + sovFault(uint64(m.Percent)) } - if m.FaultDelayType != nil { - n += m.FaultDelayType.Size() + if m.FaultDelaySecifier != nil { + n += m.FaultDelaySecifier.Size() } return n } @@ -378,7 +378,7 @@ func (m *FaultDelay) Unmarshal(dAtA []byte) error { if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(v, dAtA[iNdEx:postIndex]); err != nil { return err } - m.FaultDelayType = &FaultDelay_FixedDelay{v} + m.FaultDelaySecifier = &FaultDelay_FixedDelay{v} iNdEx = postIndex default: iNdEx = preIndex @@ -509,26 +509,26 @@ var ( func init() { proto.RegisterFile("envoy/config/filter/fault/v2/fault.proto", fileDescriptorFault) } var fileDescriptorFault = []byte{ - // 327 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x48, 0xcd, 0x2b, 0xcb, - 0xaf, 0xd4, 0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x4f, 0xcb, 0xcc, 0x29, 0x49, 0x2d, 0xd2, - 0x4f, 0x4b, 0x2c, 0xcd, 0x29, 0xd1, 0x2f, 0x33, 0x82, 0x30, 0xf4, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, - 0x85, 0x64, 0xc0, 0x2a, 0xf5, 0x20, 0x2a, 0xf5, 0x20, 0x2a, 0xf5, 0x20, 0x0a, 0xca, 0x8c, 0xa4, - 0xe4, 0xd2, 0xf3, 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0xc1, 0x6a, 0x93, 0x4a, 0xd3, 0xf4, 0x53, 0x4a, - 0x8b, 0x12, 0x4b, 0x32, 0xf3, 0xf3, 0x20, 0xba, 0xa5, 0xc4, 0xcb, 0x12, 0x73, 0x32, 0x53, 0x12, - 0x4b, 0x52, 0xf5, 0x61, 0x0c, 0xa8, 0x84, 0x48, 0x7a, 0x7e, 0x7a, 0x3e, 0x98, 0xa9, 0x0f, 0x62, - 0x41, 0x44, 0x95, 0x26, 0x30, 0x71, 0x71, 0xb9, 0x81, 0xcc, 0x76, 0x49, 0xcd, 0x49, 0xac, 0x14, - 0x0a, 0xe7, 0x62, 0x29, 0xa9, 0x2c, 0x48, 0x95, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x33, 0x32, 0xd7, - 0xc3, 0xe7, 0x14, 0x3d, 0x84, 0x3e, 0x24, 0x66, 0x48, 0x65, 0x41, 0xaa, 0x13, 0xd7, 0xae, 0x97, - 0x07, 0x98, 0x59, 0x9b, 0x18, 0x99, 0x04, 0x18, 0x83, 0xc0, 0x06, 0x0a, 0x29, 0x73, 0xb1, 0x17, - 0xa4, 0x16, 0x25, 0xa7, 0xe6, 0x95, 0x48, 0x30, 0x29, 0x30, 0x6a, 0xf0, 0x3a, 0x71, 0x82, 0x94, - 0xb0, 0x68, 0x31, 0x49, 0xa4, 0x04, 0xc1, 0x64, 0x84, 0x7c, 0xb8, 0xb8, 0xd3, 0x32, 0x2b, 0x52, - 0x53, 0xe2, 0x53, 0x40, 0x26, 0x49, 0x30, 0x2b, 0x30, 0x6a, 0x70, 0x1b, 0x49, 0xea, 0x41, 0x7c, - 0xac, 0x07, 0xf3, 0xb1, 0x9e, 0x0b, 0xd4, 0xc7, 0x4e, 0x7c, 0x33, 0xee, 0xcb, 0x33, 0x82, 0xad, - 0x5a, 0xc5, 0xc8, 0xa4, 0xc5, 0xe0, 0xc1, 0x10, 0xc4, 0x05, 0xd6, 0x0f, 0x76, 0x88, 0x92, 0x34, - 0x17, 0x1f, 0xaa, 0xb3, 0x84, 0x38, 0xb9, 0x58, 0xdd, 0x3c, 0x23, 0x5c, 0x5d, 0x04, 0x18, 0x9c, - 0x24, 0xb9, 0x04, 0xc0, 0xfe, 0x80, 0x58, 0x15, 0x0f, 0x76, 0x23, 0xeb, 0x8e, 0x97, 0x07, 0x98, - 0x19, 0x9d, 0x04, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, - 0x28, 0xa6, 0x32, 0xa3, 0x24, 0x36, 0xb0, 0xd5, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x62, - 0x8c, 0xc1, 0xea, 0xc4, 0x01, 0x00, 0x00, + // 333 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x8f, 0x3f, 0x4b, 0xfb, 0x40, + 0x18, 0xc7, 0xfb, 0xa4, 0xed, 0xef, 0x47, 0xaf, 0x58, 0x4a, 0x28, 0x18, 0xab, 0xc6, 0x52, 0x97, + 0xd0, 0xe1, 0x0e, 0xe2, 0xe0, 0x1e, 0x6a, 0x51, 0x70, 0x2a, 0x82, 0xe2, 0x52, 0xd2, 0xe6, 0x49, + 0x38, 0x08, 0xb9, 0x10, 0xaf, 0xc1, 0xac, 0xbe, 0x06, 0x07, 0x5f, 0x83, 0xaf, 0x40, 0x9c, 0x3a, + 0x3a, 0xfa, 0x0e, 0x94, 0x6e, 0x7d, 0x17, 0x92, 0xbb, 0x06, 0x75, 0x71, 0xfb, 0x72, 0xf7, 0x79, + 0xbe, 0x7f, 0x88, 0x83, 0x49, 0x2e, 0x0a, 0xb6, 0x10, 0x49, 0xc8, 0x23, 0x16, 0xf2, 0x58, 0x62, + 0xc6, 0x42, 0x7f, 0x19, 0x4b, 0x96, 0xbb, 0x5a, 0xd0, 0x34, 0x13, 0x52, 0x98, 0x07, 0x8a, 0xa4, + 0x9a, 0xa4, 0x9a, 0xa4, 0x1a, 0xc8, 0xdd, 0xbe, 0x1d, 0x09, 0x11, 0xc5, 0xc8, 0x14, 0x3b, 0x5f, + 0x86, 0x2c, 0x58, 0x66, 0xbe, 0xe4, 0x22, 0xd1, 0xd7, 0xfd, 0xdd, 0xdc, 0x8f, 0x79, 0xe0, 0x4b, + 0x64, 0x95, 0xd8, 0x7e, 0xf4, 0x22, 0x11, 0x09, 0x25, 0x59, 0xa9, 0xf4, 0xeb, 0xf0, 0xd1, 0x20, + 0x64, 0x52, 0x7a, 0x8f, 0x31, 0xf6, 0x0b, 0xf3, 0x9a, 0x34, 0x64, 0x91, 0xa2, 0x05, 0x03, 0x70, + 0x3a, 0xee, 0x29, 0xfd, 0xab, 0x0a, 0xfd, 0xbe, 0xfb, 0x21, 0xaf, 0x8a, 0x14, 0x3d, 0xf2, 0xba, + 0x59, 0xd5, 0x9b, 0x0f, 0x60, 0x74, 0x61, 0xaa, 0x0c, 0xcd, 0x63, 0xf2, 0x3f, 0xc5, 0x6c, 0x81, + 0x89, 0xb4, 0x8c, 0x01, 0x38, 0x3b, 0x5e, 0xab, 0x44, 0x1a, 0x23, 0xc3, 0x0a, 0xa6, 0xd5, 0x8f, + 0x79, 0x49, 0xda, 0x21, 0xbf, 0xc7, 0x60, 0x16, 0x94, 0x4e, 0x56, 0x7d, 0x00, 0x4e, 0xdb, 0xdd, + 0xa3, 0x7a, 0x31, 0xad, 0x16, 0xd3, 0xf1, 0x76, 0xb1, 0xd7, 0x79, 0xfa, 0x38, 0x02, 0x15, 0xf5, + 0x0c, 0xc6, 0xa8, 0x76, 0x5e, 0x9b, 0x12, 0x75, 0xaf, 0x8a, 0x0c, 0xf7, 0x49, 0xe7, 0x77, 0x2d, + 0xb3, 0x45, 0x9a, 0x93, 0x8b, 0x9b, 0xb3, 0x71, 0xb7, 0xe6, 0x1d, 0x92, 0x9e, 0xda, 0xa1, 0xa3, + 0x66, 0x77, 0xb8, 0xe0, 0x21, 0xc7, 0xcc, 0x6c, 0xbe, 0x6c, 0x56, 0x75, 0xf0, 0xba, 0x6f, 0x6b, + 0x1b, 0xde, 0xd7, 0x36, 0x7c, 0xae, 0x6d, 0xb8, 0x35, 0x72, 0x77, 0xfe, 0x4f, 0xc5, 0x9f, 0x7c, + 0x05, 0x00, 0x00, 0xff, 0xff, 0xfa, 0xf8, 0x85, 0x3b, 0xc8, 0x01, 0x00, 0x00, } diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/fault/v2/fault.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/fault/v2/fault.pb.validate.go new file mode 100644 index 00000000..851922d7 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/fault/v2/fault.pb.validate.go @@ -0,0 +1,116 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/fault/v2/fault.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on FaultDelay with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *FaultDelay) Validate() error { + if m == nil { + return nil + } + + if _, ok := FaultDelay_FaultDelayType_name[int32(m.GetType())]; !ok { + return FaultDelayValidationError{ + Field: "Type", + Reason: "value must be one of the defined enum values", + } + } + + if m.GetPercent() > 100 { + return FaultDelayValidationError{ + Field: "Percent", + Reason: "value must be less than or equal to 100", + } + } + + switch m.FaultDelaySecifier.(type) { + + case *FaultDelay_FixedDelay: + + if d := m.GetFixedDelay(); d != nil { + dur := *d + + gt := time.Duration(0*time.Second + 0*time.Nanosecond) + + if dur <= gt { + return FaultDelayValidationError{ + Field: "FixedDelay", + Reason: "value must be greater than 0s", + } + } + + } + + default: + return FaultDelayValidationError{ + Field: "FaultDelaySecifier", + Reason: "value is required", + } + + } + + return nil +} + +// FaultDelayValidationError is the validation error returned by +// FaultDelay.Validate if the designated constraints aren't met. +type FaultDelayValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e FaultDelayValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sFaultDelay.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = FaultDelayValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/buffer/v2/buffer.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/buffer/v2/buffer.pb.validate.go new file mode 100644 index 00000000..bcb5210f --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/buffer/v2/buffer.pb.validate.go @@ -0,0 +1,108 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/http/buffer/v2/buffer.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Buffer with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Buffer) Validate() error { + if m == nil { + return nil + } + + if wrapper := m.GetMaxRequestBytes(); wrapper != nil { + + if wrapper.GetValue() <= 0 { + return BufferValidationError{ + Field: "MaxRequestBytes", + Reason: "value must be greater than 0", + } + } + + } + + if m.GetMaxRequestTime() == nil { + return BufferValidationError{ + Field: "MaxRequestTime", + Reason: "value is required", + } + } + + if d := m.GetMaxRequestTime(); d != nil { + dur := *d + + gt := time.Duration(0*time.Second + 0*time.Nanosecond) + + if dur <= gt { + return BufferValidationError{ + Field: "MaxRequestTime", + Reason: "value must be greater than 0s", + } + } + + } + + return nil +} + +// BufferValidationError is the validation error returned by Buffer.Validate if +// the designated constraints aren't met. +type BufferValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e BufferValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sBuffer.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = BufferValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/ext_authz/v2/ext_authz.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/ext_authz/v2/ext_authz.pb.validate.go new file mode 100644 index 00000000..623ac4dc --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/ext_authz/v2/ext_authz.pb.validate.go @@ -0,0 +1,88 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/http/ext_authz/v2/ext_authz.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on ExtAuthz with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *ExtAuthz) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetGrpcService()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ExtAuthzValidationError{ + Field: "GrpcService", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for FailureModeAllow + + return nil +} + +// ExtAuthzValidationError is the validation error returned by +// ExtAuthz.Validate if the designated constraints aren't met. +type ExtAuthzValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ExtAuthzValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sExtAuthz.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ExtAuthzValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/fault/v2/fault.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/fault/v2/fault.pb.validate.go new file mode 100644 index 00000000..eadca125 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/fault/v2/fault.pb.validate.go @@ -0,0 +1,180 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/http/fault/v2/fault.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on FaultAbort with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *FaultAbort) Validate() error { + if m == nil { + return nil + } + + if m.GetPercent() > 100 { + return FaultAbortValidationError{ + Field: "Percent", + Reason: "value must be less than or equal to 100", + } + } + + switch m.ErrorType.(type) { + + case *FaultAbort_HttpStatus: + + if val := m.GetHttpStatus(); val < 200 || val >= 600 { + return FaultAbortValidationError{ + Field: "HttpStatus", + Reason: "value must be inside range [200, 600)", + } + } + + default: + return FaultAbortValidationError{ + Field: "ErrorType", + Reason: "value is required", + } + + } + + return nil +} + +// FaultAbortValidationError is the validation error returned by +// FaultAbort.Validate if the designated constraints aren't met. +type FaultAbortValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e FaultAbortValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sFaultAbort.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = FaultAbortValidationError{} + +// Validate checks the field values on HTTPFault with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *HTTPFault) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetDelay()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HTTPFaultValidationError{ + Field: "Delay", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetAbort()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HTTPFaultValidationError{ + Field: "Abort", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for UpstreamCluster + + for idx, item := range m.GetHeaders() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HTTPFaultValidationError{ + Field: fmt.Sprintf("Headers[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// HTTPFaultValidationError is the validation error returned by +// HTTPFault.Validate if the designated constraints aren't met. +type HTTPFaultValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HTTPFaultValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHTTPFault.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HTTPFaultValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/gzip/v2/gzip.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/gzip/v2/gzip.pb.validate.go new file mode 100644 index 00000000..dc7f561a --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/gzip/v2/gzip.pb.validate.go @@ -0,0 +1,176 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/http/gzip/v2/gzip.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Gzip with the rules defined in the proto +// definition for this message. If any rules are violated, an error is returned. +func (m *Gzip) Validate() error { + if m == nil { + return nil + } + + if wrapper := m.GetMemoryLevel(); wrapper != nil { + + if val := wrapper.GetValue(); val < 1 || val > 9 { + return GzipValidationError{ + Field: "MemoryLevel", + Reason: "value must be inside range [1, 9]", + } + } + + } + + if wrapper := m.GetContentLength(); wrapper != nil { + + if wrapper.GetValue() < 30 { + return GzipValidationError{ + Field: "ContentLength", + Reason: "value must be greater than or equal to 30", + } + } + + } + + if _, ok := Gzip_CompressionLevel_Enum_name[int32(m.GetCompressionLevel())]; !ok { + return GzipValidationError{ + Field: "CompressionLevel", + Reason: "value must be one of the defined enum values", + } + } + + if _, ok := Gzip_CompressionStrategy_name[int32(m.GetCompressionStrategy())]; !ok { + return GzipValidationError{ + Field: "CompressionStrategy", + Reason: "value must be one of the defined enum values", + } + } + + if len(m.GetContentType()) > 50 { + return GzipValidationError{ + Field: "ContentType", + Reason: "value must contain no more than 50 item(s)", + } + } + + // no validation rules for DisableOnEtagHeader + + // no validation rules for RemoveAcceptEncodingHeader + + if wrapper := m.GetWindowBits(); wrapper != nil { + + if val := wrapper.GetValue(); val < 9 || val > 15 { + return GzipValidationError{ + Field: "WindowBits", + Reason: "value must be inside range [9, 15]", + } + } + + } + + return nil +} + +// GzipValidationError is the validation error returned by Gzip.Validate if the +// designated constraints aren't met. +type GzipValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e GzipValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGzip.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = GzipValidationError{} + +// Validate checks the field values on Gzip_CompressionLevel with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *Gzip_CompressionLevel) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// Gzip_CompressionLevelValidationError is the validation error returned by +// Gzip_CompressionLevel.Validate if the designated constraints aren't met. +type Gzip_CompressionLevelValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Gzip_CompressionLevelValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGzip_CompressionLevel.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Gzip_CompressionLevelValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/health_check/v2/health_check.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/health_check/v2/health_check.pb.validate.go new file mode 100644 index 00000000..b45db6ca --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/health_check/v2/health_check.pb.validate.go @@ -0,0 +1,113 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/http/health_check/v2/health_check.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on HealthCheck with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *HealthCheck) Validate() error { + if m == nil { + return nil + } + + if m.GetPassThroughMode() == nil { + return HealthCheckValidationError{ + Field: "PassThroughMode", + Reason: "value is required", + } + } + + if v, ok := interface{}(m.GetPassThroughMode()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckValidationError{ + Field: "PassThroughMode", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if len(m.GetEndpoint()) < 1 { + return HealthCheckValidationError{ + Field: "Endpoint", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetCacheTime()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckValidationError{ + Field: "CacheTime", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for ClusterMinHealthyPercentages + + return nil +} + +// HealthCheckValidationError is the validation error returned by +// HealthCheck.Validate if the designated constraints aren't met. +type HealthCheckValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HealthCheckValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHealthCheck.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HealthCheckValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/ip_tagging/v2/ip_tagging.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/ip_tagging/v2/ip_tagging.pb.validate.go new file mode 100644 index 00000000..e4d7f1c4 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/ip_tagging/v2/ip_tagging.pb.validate.go @@ -0,0 +1,164 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/http/ip_tagging/v2/ip_tagging.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on IPTagging with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *IPTagging) Validate() error { + if m == nil { + return nil + } + + if _, ok := IPTagging_RequestType_name[int32(m.GetRequestType())]; !ok { + return IPTaggingValidationError{ + Field: "RequestType", + Reason: "value must be one of the defined enum values", + } + } + + if len(m.GetIpTags()) < 1 { + return IPTaggingValidationError{ + Field: "IpTags", + Reason: "value must contain at least 1 item(s)", + } + } + + for idx, item := range m.GetIpTags() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return IPTaggingValidationError{ + Field: fmt.Sprintf("IpTags[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// IPTaggingValidationError is the validation error returned by +// IPTagging.Validate if the designated constraints aren't met. +type IPTaggingValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e IPTaggingValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sIPTagging.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = IPTaggingValidationError{} + +// Validate checks the field values on IPTagging_IPTag with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *IPTagging_IPTag) Validate() error { + if m == nil { + return nil + } + + // no validation rules for IpTagName + + for idx, item := range m.GetIpList() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return IPTagging_IPTagValidationError{ + Field: fmt.Sprintf("IpList[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// IPTagging_IPTagValidationError is the validation error returned by +// IPTagging_IPTag.Validate if the designated constraints aren't met. +type IPTagging_IPTagValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e IPTagging_IPTagValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sIPTagging_IPTag.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = IPTagging_IPTagValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/jwt_authn/v2alpha/config.pb.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/jwt_authn/v2alpha/config.pb.go new file mode 100644 index 00000000..1b87964d --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/jwt_authn/v2alpha/config.pb.go @@ -0,0 +1,1578 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: envoy/config/filter/http/jwt_authn/v2alpha/config.proto + +/* + Package envoy_config_filter_http_jwt_authn_v2alpha is a generated protocol buffer package. + + It is generated from these files: + envoy/config/filter/http/jwt_authn/v2alpha/config.proto + + It has these top-level messages: + JwtRule + RemoteJwks + JwtHeader + JwtAuthentication +*/ +package envoy_config_filter_http_jwt_authn_v2alpha + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" +import envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" +import envoy_api_v2_core1 "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" +import envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" +import google_protobuf3 "github.com/gogo/protobuf/types" +import _ "github.com/lyft/protoc-gen-validate/validate" + +import io "io" + +// 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.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +// This message specifies how a JSON Web Token (JWT) can be verified. JWT format is defined +// `here `_. Please see `OAuth2.0 +// `_ and `OIDC1.0 `_ for +// the authentication flow. +// +// Example: +// +// .. code-block:: yaml +// +// issuer: https://example.com +// audiences: +// - bookstore_android.apps.googleusercontent.com +// bookstore_web.apps.googleusercontent.com +// remote_jwks: +// - http_uri: +// - uri: https://example.com/.well-known/jwks.json +// cluster: example_jwks_cluster +// cache_duration: +// - seconds: 300 +// +// [#not-implemented-hide:] +type JwtRule struct { + // Identifies the principal that issued the JWT. See `here + // `_. Usually a URL or an email address. + // + // Example: https://securetoken.google.com + // Example: 1234567-compute@developer.gserviceaccount.com + // + Issuer string `protobuf:"bytes,1,opt,name=issuer,proto3" json:"issuer,omitempty"` + // The list of JWT `audiences `_. that are + // allowed to access. A JWT containing any of these audiences will be accepted. If not specified, + // will not check audiences in the token. + // + // Example: + // + // .. code-block:: yaml + // + // audiences: + // - bookstore_android.apps.googleusercontent.com + // bookstore_web.apps.googleusercontent.com + // + Audiences []string `protobuf:"bytes,2,rep,name=audiences" json:"audiences,omitempty"` + // `JSON Web Key Set `_ is needed. to validate + // signature of the JWT. This field specifies where to fetch JWKS. + // + // Types that are valid to be assigned to JwksSourceSpecifier: + // *JwtRule_RemoteJwks + // *JwtRule_LocalJwks + JwksSourceSpecifier isJwtRule_JwksSourceSpecifier `protobuf_oneof:"jwks_source_specifier"` + // If false, the JWT is removed in the request after a success verification. If true, the JWT is + // not removed in the request. Default value is false. + Forward bool `protobuf:"varint,5,opt,name=forward,proto3" json:"forward,omitempty"` + // Specify the HTTP headers to extract JWT token. For examples, following config: + // + // .. code-block:: yaml + // + // from_headers: + // - name: x-goog-iap-jwt-assertion + // + // can be used to extract token from header:: + // + // x-goog-iap-jwt-assertion: . + // + FromHeaders []*JwtHeader `protobuf:"bytes,6,rep,name=from_headers,json=fromHeaders" json:"from_headers,omitempty"` + // JWT is sent in a query parameter. `jwt_params` represents the query parameter names. + // + // For example, if config is: + // + // .. code-block:: yaml + // + // from_params: + // - jwt_token + // + // The JWT format in query parameter is:: + // + // /path?jwt_token= + // + FromParams []string `protobuf:"bytes,7,rep,name=from_params,json=fromParams" json:"from_params,omitempty"` + // This field specifies the header name to forward a successfully verified JWT payload to the + // backend. The forwarded data is:: + // + // base64_encoded(jwt_payload_in_JSON) + // + // If it is not specified, the payload will not be forwarded. + // Multiple JWTs in a request from different issuers will be supported. Multiple JWTs from the + // same issuer will not be supported. Each issuer can config this `forward_payload_header`. If + // multiple JWTs from different issuers want to forward their payloads, their + // `forward_payload_header` should be different. + ForwardPayloadHeader string `protobuf:"bytes,8,opt,name=forward_payload_header,json=forwardPayloadHeader,proto3" json:"forward_payload_header,omitempty"` +} + +func (m *JwtRule) Reset() { *m = JwtRule{} } +func (m *JwtRule) String() string { return proto.CompactTextString(m) } +func (*JwtRule) ProtoMessage() {} +func (*JwtRule) Descriptor() ([]byte, []int) { return fileDescriptorConfig, []int{0} } + +type isJwtRule_JwksSourceSpecifier interface { + isJwtRule_JwksSourceSpecifier() + MarshalTo([]byte) (int, error) + Size() int +} + +type JwtRule_RemoteJwks struct { + RemoteJwks *RemoteJwks `protobuf:"bytes,3,opt,name=remote_jwks,json=remoteJwks,oneof"` +} +type JwtRule_LocalJwks struct { + LocalJwks *envoy_api_v2_core.DataSource `protobuf:"bytes,4,opt,name=local_jwks,json=localJwks,oneof"` +} + +func (*JwtRule_RemoteJwks) isJwtRule_JwksSourceSpecifier() {} +func (*JwtRule_LocalJwks) isJwtRule_JwksSourceSpecifier() {} + +func (m *JwtRule) GetJwksSourceSpecifier() isJwtRule_JwksSourceSpecifier { + if m != nil { + return m.JwksSourceSpecifier + } + return nil +} + +func (m *JwtRule) GetIssuer() string { + if m != nil { + return m.Issuer + } + return "" +} + +func (m *JwtRule) GetAudiences() []string { + if m != nil { + return m.Audiences + } + return nil +} + +func (m *JwtRule) GetRemoteJwks() *RemoteJwks { + if x, ok := m.GetJwksSourceSpecifier().(*JwtRule_RemoteJwks); ok { + return x.RemoteJwks + } + return nil +} + +func (m *JwtRule) GetLocalJwks() *envoy_api_v2_core.DataSource { + if x, ok := m.GetJwksSourceSpecifier().(*JwtRule_LocalJwks); ok { + return x.LocalJwks + } + return nil +} + +func (m *JwtRule) GetForward() bool { + if m != nil { + return m.Forward + } + return false +} + +func (m *JwtRule) GetFromHeaders() []*JwtHeader { + if m != nil { + return m.FromHeaders + } + return nil +} + +func (m *JwtRule) GetFromParams() []string { + if m != nil { + return m.FromParams + } + return nil +} + +func (m *JwtRule) GetForwardPayloadHeader() string { + if m != nil { + return m.ForwardPayloadHeader + } + return "" +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*JwtRule) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _JwtRule_OneofMarshaler, _JwtRule_OneofUnmarshaler, _JwtRule_OneofSizer, []interface{}{ + (*JwtRule_RemoteJwks)(nil), + (*JwtRule_LocalJwks)(nil), + } +} + +func _JwtRule_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*JwtRule) + // jwks_source_specifier + switch x := m.JwksSourceSpecifier.(type) { + case *JwtRule_RemoteJwks: + _ = b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.RemoteJwks); err != nil { + return err + } + case *JwtRule_LocalJwks: + _ = b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.LocalJwks); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("JwtRule.JwksSourceSpecifier has unexpected type %T", x) + } + return nil +} + +func _JwtRule_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*JwtRule) + switch tag { + case 3: // jwks_source_specifier.remote_jwks + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RemoteJwks) + err := b.DecodeMessage(msg) + m.JwksSourceSpecifier = &JwtRule_RemoteJwks{msg} + return true, err + case 4: // jwks_source_specifier.local_jwks + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(envoy_api_v2_core.DataSource) + err := b.DecodeMessage(msg) + m.JwksSourceSpecifier = &JwtRule_LocalJwks{msg} + return true, err + default: + return false, nil + } +} + +func _JwtRule_OneofSizer(msg proto.Message) (n int) { + m := msg.(*JwtRule) + // jwks_source_specifier + switch x := m.JwksSourceSpecifier.(type) { + case *JwtRule_RemoteJwks: + s := proto.Size(x.RemoteJwks) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *JwtRule_LocalJwks: + s := proto.Size(x.LocalJwks) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// This message specifies how to fetch JWKS from remote and how to cache it. +type RemoteJwks struct { + // The HTTP URI to fetch the JWKS. For example: + // + // .. code-block:: yaml + // + // http_uri: + // - uri: https://www.googleapis.com/oauth2/v1/certs + // cluster: jwt.www.googleapis.com|443 + // + HttpUri *envoy_api_v2_core1.HttpUri `protobuf:"bytes,1,opt,name=http_uri,json=httpUri" json:"http_uri,omitempty"` + // Duration after which the cached JWKS should be expired. If not specified, default cache + // duration is 5 minutes. + CacheDuration *google_protobuf3.Duration `protobuf:"bytes,2,opt,name=cache_duration,json=cacheDuration" json:"cache_duration,omitempty"` +} + +func (m *RemoteJwks) Reset() { *m = RemoteJwks{} } +func (m *RemoteJwks) String() string { return proto.CompactTextString(m) } +func (*RemoteJwks) ProtoMessage() {} +func (*RemoteJwks) Descriptor() ([]byte, []int) { return fileDescriptorConfig, []int{1} } + +func (m *RemoteJwks) GetHttpUri() *envoy_api_v2_core1.HttpUri { + if m != nil { + return m.HttpUri + } + return nil +} + +func (m *RemoteJwks) GetCacheDuration() *google_protobuf3.Duration { + if m != nil { + return m.CacheDuration + } + return nil +} + +// This message specifies a header location to extract JWT token. +type JwtHeader struct { + // The HTTP header name. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // The value prefix. The value format is "value_prefix" + // For example, for "Authorization: Bearer ", value_prefix="Bearer " with a space at the + // end. + ValuePrefix string `protobuf:"bytes,2,opt,name=value_prefix,json=valuePrefix,proto3" json:"value_prefix,omitempty"` +} + +func (m *JwtHeader) Reset() { *m = JwtHeader{} } +func (m *JwtHeader) String() string { return proto.CompactTextString(m) } +func (*JwtHeader) ProtoMessage() {} +func (*JwtHeader) Descriptor() ([]byte, []int) { return fileDescriptorConfig, []int{2} } + +func (m *JwtHeader) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *JwtHeader) GetValuePrefix() string { + if m != nil { + return m.ValuePrefix + } + return "" +} + +// This is the Envoy HTTP filter config for JWT authentication. +// [#not-implemented-hide:] +type JwtAuthentication struct { + // List of JWT rules to valide. + Rules []*JwtRule `protobuf:"bytes,1,rep,name=rules" json:"rules,omitempty"` + // If true, the request is allowed if JWT is missing or JWT verification fails. + // Default is false, a request without JWT or failed JWT verification is not allowed. + AllowMissingOrFailed bool `protobuf:"varint,2,opt,name=allow_missing_or_failed,json=allowMissingOrFailed,proto3" json:"allow_missing_or_failed,omitempty"` + // This field lists the patterns allowed to bypass JWT verification. This only applies when + // `allow_missing_or_failed_jwt` is false. Under this config, if a request doesn't have JWT, it + // will be rejected. But some requests still needed to be forwarded without JWT, such as OPTIONS + // for CORS and some health checking paths. + // + // Examples: bypass all CORS options requests + // + // .. code-block:: yaml + // + // bypass: + // - headers: + // - name: :method + // value: OPTIONS + // - headers: + // - name: :path + // regex_match: /.* + // + // Examples: bypass /healthz check + // + // .. code-block:: yaml + // + // bypass: + // - headers: + // - name: :method + // value: GET + // - headers: + // - name: :path + // exact_match: /healthz + // + Bypass []*envoy_api_v2_route.RouteMatch `protobuf:"bytes,3,rep,name=bypass" json:"bypass,omitempty"` +} + +func (m *JwtAuthentication) Reset() { *m = JwtAuthentication{} } +func (m *JwtAuthentication) String() string { return proto.CompactTextString(m) } +func (*JwtAuthentication) ProtoMessage() {} +func (*JwtAuthentication) Descriptor() ([]byte, []int) { return fileDescriptorConfig, []int{3} } + +func (m *JwtAuthentication) GetRules() []*JwtRule { + if m != nil { + return m.Rules + } + return nil +} + +func (m *JwtAuthentication) GetAllowMissingOrFailed() bool { + if m != nil { + return m.AllowMissingOrFailed + } + return false +} + +func (m *JwtAuthentication) GetBypass() []*envoy_api_v2_route.RouteMatch { + if m != nil { + return m.Bypass + } + return nil +} + +func init() { + proto.RegisterType((*JwtRule)(nil), "envoy.config.filter.http.jwt_authn.v2alpha.JwtRule") + proto.RegisterType((*RemoteJwks)(nil), "envoy.config.filter.http.jwt_authn.v2alpha.RemoteJwks") + proto.RegisterType((*JwtHeader)(nil), "envoy.config.filter.http.jwt_authn.v2alpha.JwtHeader") + proto.RegisterType((*JwtAuthentication)(nil), "envoy.config.filter.http.jwt_authn.v2alpha.JwtAuthentication") +} +func (m *JwtRule) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *JwtRule) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Issuer) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintConfig(dAtA, i, uint64(len(m.Issuer))) + i += copy(dAtA[i:], m.Issuer) + } + if len(m.Audiences) > 0 { + for _, s := range m.Audiences { + dAtA[i] = 0x12 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + if m.JwksSourceSpecifier != nil { + nn1, err := m.JwksSourceSpecifier.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += nn1 + } + if m.Forward { + dAtA[i] = 0x28 + i++ + if m.Forward { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + } + if len(m.FromHeaders) > 0 { + for _, msg := range m.FromHeaders { + dAtA[i] = 0x32 + i++ + i = encodeVarintConfig(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.FromParams) > 0 { + for _, s := range m.FromParams { + dAtA[i] = 0x3a + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + if len(m.ForwardPayloadHeader) > 0 { + dAtA[i] = 0x42 + i++ + i = encodeVarintConfig(dAtA, i, uint64(len(m.ForwardPayloadHeader))) + i += copy(dAtA[i:], m.ForwardPayloadHeader) + } + return i, nil +} + +func (m *JwtRule_RemoteJwks) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.RemoteJwks != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintConfig(dAtA, i, uint64(m.RemoteJwks.Size())) + n2, err := m.RemoteJwks.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n2 + } + return i, nil +} +func (m *JwtRule_LocalJwks) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.LocalJwks != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintConfig(dAtA, i, uint64(m.LocalJwks.Size())) + n3, err := m.LocalJwks.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n3 + } + return i, nil +} +func (m *RemoteJwks) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RemoteJwks) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.HttpUri != nil { + dAtA[i] = 0xa + i++ + i = encodeVarintConfig(dAtA, i, uint64(m.HttpUri.Size())) + n4, err := m.HttpUri.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n4 + } + if m.CacheDuration != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintConfig(dAtA, i, uint64(m.CacheDuration.Size())) + n5, err := m.CacheDuration.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n5 + } + return i, nil +} + +func (m *JwtHeader) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *JwtHeader) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Name) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintConfig(dAtA, i, uint64(len(m.Name))) + i += copy(dAtA[i:], m.Name) + } + if len(m.ValuePrefix) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintConfig(dAtA, i, uint64(len(m.ValuePrefix))) + i += copy(dAtA[i:], m.ValuePrefix) + } + return i, nil +} + +func (m *JwtAuthentication) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *JwtAuthentication) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Rules) > 0 { + for _, msg := range m.Rules { + dAtA[i] = 0xa + i++ + i = encodeVarintConfig(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if m.AllowMissingOrFailed { + dAtA[i] = 0x10 + i++ + if m.AllowMissingOrFailed { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + } + if len(m.Bypass) > 0 { + for _, msg := range m.Bypass { + dAtA[i] = 0x1a + i++ + i = encodeVarintConfig(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func encodeVarintConfig(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *JwtRule) Size() (n int) { + var l int + _ = l + l = len(m.Issuer) + if l > 0 { + n += 1 + l + sovConfig(uint64(l)) + } + if len(m.Audiences) > 0 { + for _, s := range m.Audiences { + l = len(s) + n += 1 + l + sovConfig(uint64(l)) + } + } + if m.JwksSourceSpecifier != nil { + n += m.JwksSourceSpecifier.Size() + } + if m.Forward { + n += 2 + } + if len(m.FromHeaders) > 0 { + for _, e := range m.FromHeaders { + l = e.Size() + n += 1 + l + sovConfig(uint64(l)) + } + } + if len(m.FromParams) > 0 { + for _, s := range m.FromParams { + l = len(s) + n += 1 + l + sovConfig(uint64(l)) + } + } + l = len(m.ForwardPayloadHeader) + if l > 0 { + n += 1 + l + sovConfig(uint64(l)) + } + return n +} + +func (m *JwtRule_RemoteJwks) Size() (n int) { + var l int + _ = l + if m.RemoteJwks != nil { + l = m.RemoteJwks.Size() + n += 1 + l + sovConfig(uint64(l)) + } + return n +} +func (m *JwtRule_LocalJwks) Size() (n int) { + var l int + _ = l + if m.LocalJwks != nil { + l = m.LocalJwks.Size() + n += 1 + l + sovConfig(uint64(l)) + } + return n +} +func (m *RemoteJwks) Size() (n int) { + var l int + _ = l + if m.HttpUri != nil { + l = m.HttpUri.Size() + n += 1 + l + sovConfig(uint64(l)) + } + if m.CacheDuration != nil { + l = m.CacheDuration.Size() + n += 1 + l + sovConfig(uint64(l)) + } + return n +} + +func (m *JwtHeader) Size() (n int) { + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + sovConfig(uint64(l)) + } + l = len(m.ValuePrefix) + if l > 0 { + n += 1 + l + sovConfig(uint64(l)) + } + return n +} + +func (m *JwtAuthentication) Size() (n int) { + var l int + _ = l + if len(m.Rules) > 0 { + for _, e := range m.Rules { + l = e.Size() + n += 1 + l + sovConfig(uint64(l)) + } + } + if m.AllowMissingOrFailed { + n += 2 + } + if len(m.Bypass) > 0 { + for _, e := range m.Bypass { + l = e.Size() + n += 1 + l + sovConfig(uint64(l)) + } + } + return n +} + +func sovConfig(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozConfig(x uint64) (n int) { + return sovConfig(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *JwtRule) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: JwtRule: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: JwtRule: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Issuer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthConfig + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Issuer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Audiences", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthConfig + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Audiences = append(m.Audiences, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RemoteJwks", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthConfig + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RemoteJwks{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.JwksSourceSpecifier = &JwtRule_RemoteJwks{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LocalJwks", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthConfig + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &envoy_api_v2_core.DataSource{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.JwksSourceSpecifier = &JwtRule_LocalJwks{v} + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Forward", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.Forward = bool(v != 0) + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FromHeaders", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthConfig + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FromHeaders = append(m.FromHeaders, &JwtHeader{}) + if err := m.FromHeaders[len(m.FromHeaders)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FromParams", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthConfig + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FromParams = append(m.FromParams, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ForwardPayloadHeader", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthConfig + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ForwardPayloadHeader = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipConfig(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthConfig + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RemoteJwks) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RemoteJwks: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RemoteJwks: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HttpUri", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthConfig + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.HttpUri == nil { + m.HttpUri = &envoy_api_v2_core1.HttpUri{} + } + if err := m.HttpUri.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CacheDuration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthConfig + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.CacheDuration == nil { + m.CacheDuration = &google_protobuf3.Duration{} + } + if err := m.CacheDuration.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipConfig(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthConfig + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *JwtHeader) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: JwtHeader: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: JwtHeader: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthConfig + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValuePrefix", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthConfig + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValuePrefix = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipConfig(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthConfig + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *JwtAuthentication) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: JwtAuthentication: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: JwtAuthentication: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Rules", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthConfig + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Rules = append(m.Rules, &JwtRule{}) + if err := m.Rules[len(m.Rules)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowMissingOrFailed", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.AllowMissingOrFailed = bool(v != 0) + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Bypass", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConfig + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthConfig + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Bypass = append(m.Bypass, &envoy_api_v2_route.RouteMatch{}) + if err := m.Bypass[len(m.Bypass)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipConfig(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthConfig + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipConfig(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowConfig + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowConfig + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowConfig + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthConfig + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowConfig + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipConfig(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthConfig = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowConfig = fmt.Errorf("proto: integer overflow") +) + +func init() { + proto.RegisterFile("envoy/config/filter/http/jwt_authn/v2alpha/config.proto", fileDescriptorConfig) +} + +var fileDescriptorConfig = []byte{ + // 641 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0xad, 0x9b, 0x36, 0x89, 0x37, 0x05, 0x89, 0x55, 0xa1, 0xa6, 0x6a, 0x83, 0x9b, 0x53, 0xc4, + 0xc1, 0x96, 0x52, 0x5a, 0x6e, 0x08, 0xaa, 0x0a, 0x85, 0x48, 0x15, 0xd5, 0x22, 0x24, 0x38, 0x59, + 0x13, 0x7b, 0x1d, 0x6f, 0xeb, 0x78, 0xad, 0xdd, 0x75, 0x4c, 0x3f, 0x80, 0x7f, 0x42, 0x9c, 0x7a, + 0xe4, 0x82, 0xd4, 0x4f, 0x40, 0xbd, 0xf5, 0x2f, 0x90, 0x77, 0xed, 0x54, 0x55, 0x39, 0xd0, 0xcb, + 0x6a, 0x67, 0xde, 0xbc, 0xb7, 0xe3, 0x37, 0x63, 0xf4, 0x9a, 0x66, 0x0b, 0x7e, 0xe1, 0x87, 0x3c, + 0x8b, 0xd9, 0xcc, 0x8f, 0x59, 0xaa, 0xa8, 0xf0, 0x13, 0xa5, 0x72, 0xff, 0xac, 0x54, 0x01, 0x14, + 0x2a, 0xc9, 0xfc, 0xc5, 0x08, 0xd2, 0x3c, 0x81, 0xba, 0xc8, 0xcb, 0x05, 0x57, 0x1c, 0xbf, 0xd4, + 0x44, 0xaf, 0xce, 0x19, 0xa2, 0x57, 0x11, 0xbd, 0x25, 0xd1, 0xab, 0x89, 0xdb, 0x3b, 0xe6, 0x11, + 0xc8, 0x99, 0xbf, 0x18, 0xf9, 0x21, 0x17, 0xd4, 0x9f, 0x82, 0xa4, 0x46, 0x69, 0xdb, 0xbd, 0x8f, + 0x56, 0x3a, 0x41, 0x21, 0x58, 0x5d, 0xd1, 0xbf, 0x53, 0x21, 0x78, 0xa1, 0xa8, 0x39, 0x1b, 0x7c, + 0xc6, 0xf9, 0x2c, 0xa5, 0xbe, 0x8e, 0xa6, 0x45, 0xec, 0x47, 0x85, 0x00, 0xc5, 0x78, 0x56, 0xe3, + 0x5b, 0x0b, 0x48, 0x59, 0x04, 0x8a, 0xfa, 0xcd, 0xc5, 0x00, 0x83, 0xab, 0x16, 0xea, 0x4c, 0x4a, + 0x45, 0x8a, 0x94, 0xe2, 0x3d, 0xd4, 0x66, 0x52, 0x16, 0x54, 0x38, 0x96, 0x6b, 0x0d, 0xed, 0x23, + 0xfb, 0xe7, 0xcd, 0x65, 0x6b, 0x4d, 0xac, 0xba, 0x16, 0xa9, 0x01, 0xbc, 0x83, 0x6c, 0x28, 0x22, + 0x46, 0xb3, 0x90, 0x4a, 0x67, 0xd5, 0x6d, 0x0d, 0x6d, 0x72, 0x9b, 0xc0, 0x5f, 0x51, 0x4f, 0xd0, + 0x39, 0x57, 0x34, 0x38, 0x2b, 0xcf, 0xa5, 0xd3, 0x72, 0xad, 0x61, 0x6f, 0x74, 0xe8, 0xfd, 0xbf, + 0x4f, 0x1e, 0xd1, 0xf4, 0x49, 0x79, 0x2e, 0xc7, 0x2b, 0x04, 0x89, 0x65, 0x84, 0xdf, 0x20, 0x94, + 0xf2, 0x10, 0x52, 0xa3, 0xbc, 0xa6, 0x95, 0x77, 0x6b, 0x65, 0xc8, 0x99, 0xb7, 0x18, 0x79, 0x95, + 0x6f, 0xde, 0x31, 0x28, 0xf8, 0xc4, 0x0b, 0x11, 0xd2, 0xf1, 0x0a, 0xb1, 0x35, 0x45, 0xf3, 0x1d, + 0xd4, 0x89, 0xb9, 0x28, 0x41, 0x44, 0xce, 0xba, 0x6b, 0x0d, 0xbb, 0xa4, 0x09, 0xf1, 0x17, 0xb4, + 0x11, 0x0b, 0x3e, 0x0f, 0x12, 0x0a, 0x11, 0x15, 0xd2, 0x69, 0xbb, 0xad, 0x61, 0x6f, 0x74, 0xf0, + 0x90, 0xae, 0x27, 0xa5, 0x1a, 0x6b, 0x36, 0xe9, 0x55, 0x52, 0xe6, 0x2e, 0xf1, 0x0b, 0xa4, 0xc3, + 0x20, 0x07, 0x01, 0x73, 0xe9, 0x74, 0xb4, 0x5d, 0xa8, 0x4a, 0x9d, 0xea, 0x0c, 0x7e, 0x85, 0x9e, + 0xd5, 0x5d, 0x04, 0x39, 0x5c, 0xa4, 0x1c, 0xa2, 0xba, 0x0b, 0xa7, 0x5b, 0x0d, 0x80, 0x6c, 0xd6, + 0xe8, 0xa9, 0x01, 0x8d, 0xee, 0x51, 0x1f, 0x3d, 0xad, 0x4c, 0x08, 0xa4, 0xfe, 0xcc, 0x40, 0xe6, + 0x34, 0x64, 0x31, 0xa3, 0x02, 0xaf, 0xff, 0xb8, 0xb9, 0x6c, 0x59, 0x83, 0xef, 0x16, 0x42, 0xb7, + 0x3e, 0xe2, 0x03, 0xd4, 0x6d, 0x96, 0x49, 0xcf, 0xb5, 0x37, 0xda, 0xfe, 0x87, 0x6f, 0x63, 0xa5, + 0xf2, 0xcf, 0x82, 0x91, 0x4e, 0x62, 0x2e, 0xf8, 0x2d, 0x7a, 0x1c, 0x42, 0x98, 0xd0, 0xa0, 0xd9, + 0x24, 0x67, 0x55, 0x93, 0x9f, 0x7b, 0x66, 0xd5, 0xbc, 0x66, 0xd5, 0xbc, 0xe3, 0xba, 0x80, 0x3c, + 0xd2, 0x84, 0x26, 0x1c, 0x9c, 0x20, 0x7b, 0x69, 0x0c, 0xde, 0x45, 0x6b, 0x19, 0xcc, 0xe9, 0xfd, + 0xcd, 0xd2, 0x69, 0xbc, 0x87, 0x36, 0x16, 0x90, 0x16, 0x34, 0xc8, 0x05, 0x8d, 0xd9, 0x37, 0xfd, + 0x96, 0x4d, 0x7a, 0x3a, 0x77, 0xaa, 0x53, 0x83, 0xdf, 0x16, 0x7a, 0x32, 0x29, 0xd5, 0xbb, 0x42, + 0x25, 0x34, 0x53, 0x2c, 0xd4, 0x8f, 0xe0, 0x0f, 0x68, 0x5d, 0x14, 0x29, 0x95, 0x8e, 0xa5, 0xc7, + 0xb6, 0xff, 0xc0, 0xb1, 0x55, 0x7b, 0x4f, 0x8c, 0x02, 0x3e, 0x40, 0x5b, 0x90, 0xa6, 0xbc, 0x0c, + 0xe6, 0x4c, 0x4a, 0x96, 0xcd, 0x02, 0x2e, 0x82, 0x18, 0x58, 0x4a, 0x23, 0xdd, 0x4e, 0x97, 0x6c, + 0x6a, 0xf8, 0xc4, 0xa0, 0x1f, 0xc5, 0x7b, 0x8d, 0xe1, 0x43, 0xd4, 0x9e, 0x5e, 0xe4, 0x20, 0xab, + 0x7d, 0xaf, 0x5a, 0xe8, 0xdf, 0x75, 0xd7, 0xfc, 0xa5, 0xa4, 0x3a, 0x4f, 0x40, 0x85, 0x09, 0xa9, + 0xab, 0x8f, 0x36, 0x7e, 0x5d, 0xf7, 0xad, 0xab, 0xeb, 0xbe, 0xf5, 0xe7, 0xba, 0x6f, 0x4d, 0xdb, + 0xda, 0xce, 0xfd, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x9e, 0xa4, 0x21, 0xaf, 0x8e, 0x04, 0x00, + 0x00, +} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/jwt_authn/v2alpha/config.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/jwt_authn/v2alpha/config.pb.validate.go new file mode 100644 index 00000000..310e9d40 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/jwt_authn/v2alpha/config.pb.validate.go @@ -0,0 +1,321 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/http/jwt_authn/v2alpha/config.proto +// DO NOT EDIT!!! + +package envoy_config_filter_http_jwt_authn_v2alpha + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on JwtRule with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *JwtRule) Validate() error { + if m == nil { + return nil + } + + if len(m.GetIssuer()) < 1 { + return JwtRuleValidationError{ + Field: "Issuer", + Reason: "value length must be at least 1 bytes", + } + } + + // no validation rules for Forward + + for idx, item := range m.GetFromHeaders() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return JwtRuleValidationError{ + Field: fmt.Sprintf("FromHeaders[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + // no validation rules for ForwardPayloadHeader + + switch m.JwksSourceSpecifier.(type) { + + case *JwtRule_RemoteJwks: + + if v, ok := interface{}(m.GetRemoteJwks()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return JwtRuleValidationError{ + Field: "RemoteJwks", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *JwtRule_LocalJwks: + + if v, ok := interface{}(m.GetLocalJwks()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return JwtRuleValidationError{ + Field: "LocalJwks", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + default: + return JwtRuleValidationError{ + Field: "JwksSourceSpecifier", + Reason: "value is required", + } + + } + + return nil +} + +// JwtRuleValidationError is the validation error returned by JwtRule.Validate +// if the designated constraints aren't met. +type JwtRuleValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e JwtRuleValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sJwtRule.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = JwtRuleValidationError{} + +// Validate checks the field values on RemoteJwks with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *RemoteJwks) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetHttpUri()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RemoteJwksValidationError{ + Field: "HttpUri", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetCacheDuration()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RemoteJwksValidationError{ + Field: "CacheDuration", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// RemoteJwksValidationError is the validation error returned by +// RemoteJwks.Validate if the designated constraints aren't met. +type RemoteJwksValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RemoteJwksValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRemoteJwks.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RemoteJwksValidationError{} + +// Validate checks the field values on JwtHeader with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *JwtHeader) Validate() error { + if m == nil { + return nil + } + + if len(m.GetName()) < 1 { + return JwtHeaderValidationError{ + Field: "Name", + Reason: "value length must be at least 1 bytes", + } + } + + // no validation rules for ValuePrefix + + return nil +} + +// JwtHeaderValidationError is the validation error returned by +// JwtHeader.Validate if the designated constraints aren't met. +type JwtHeaderValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e JwtHeaderValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sJwtHeader.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = JwtHeaderValidationError{} + +// Validate checks the field values on JwtAuthentication with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *JwtAuthentication) Validate() error { + if m == nil { + return nil + } + + for idx, item := range m.GetRules() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return JwtAuthenticationValidationError{ + Field: fmt.Sprintf("Rules[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + // no validation rules for AllowMissingOrFailed + + for idx, item := range m.GetBypass() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return JwtAuthenticationValidationError{ + Field: fmt.Sprintf("Bypass[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// JwtAuthenticationValidationError is the validation error returned by +// JwtAuthentication.Validate if the designated constraints aren't met. +type JwtAuthenticationValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e JwtAuthenticationValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sJwtAuthentication.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = JwtAuthenticationValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/lua/v2/lua.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/lua/v2/lua.pb.validate.go new file mode 100644 index 00000000..67616959 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/lua/v2/lua.pb.validate.go @@ -0,0 +1,83 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/http/lua/v2/lua.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Lua with the rules defined in the proto +// definition for this message. If any rules are violated, an error is returned. +func (m *Lua) Validate() error { + if m == nil { + return nil + } + + if len(m.GetInlineCode()) < 1 { + return LuaValidationError{ + Field: "InlineCode", + Reason: "value length must be at least 1 bytes", + } + } + + return nil +} + +// LuaValidationError is the validation error returned by Lua.Validate if the +// designated constraints aren't met. +type LuaValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e LuaValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sLua.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = LuaValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/rate_limit/v2/rate_limit.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/rate_limit/v2/rate_limit.pb.validate.go new file mode 100644 index 00000000..9f5b73bf --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/rate_limit/v2/rate_limit.pb.validate.go @@ -0,0 +1,102 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/http/rate_limit/v2/rate_limit.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on RateLimit with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *RateLimit) Validate() error { + if m == nil { + return nil + } + + if len(m.GetDomain()) < 1 { + return RateLimitValidationError{ + Field: "Domain", + Reason: "value length must be at least 1 bytes", + } + } + + if m.GetStage() > 10 { + return RateLimitValidationError{ + Field: "Stage", + Reason: "value must be less than or equal to 10", + } + } + + // no validation rules for RequestType + + if v, ok := interface{}(m.GetTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimitValidationError{ + Field: "Timeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// RateLimitValidationError is the validation error returned by +// RateLimit.Validate if the designated constraints aren't met. +type RateLimitValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimitValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimit.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimitValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/router/v2/router.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/router/v2/router.pb.validate.go new file mode 100644 index 00000000..75642c06 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/router/v2/router.pb.validate.go @@ -0,0 +1,103 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/http/router/v2/router.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Router with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Router) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetDynamicStats()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouterValidationError{ + Field: "DynamicStats", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for StartChildSpan + + for idx, item := range m.GetUpstreamLog() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RouterValidationError{ + Field: fmt.Sprintf("UpstreamLog[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// RouterValidationError is the validation error returned by Router.Validate if +// the designated constraints aren't met. +type RouterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RouterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRouter.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RouterValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/squash/v2/squash.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/squash/v2/squash.pb.validate.go new file mode 100644 index 00000000..6add8bed --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/squash/v2/squash.pb.validate.go @@ -0,0 +1,123 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/http/squash/v2/squash.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Squash with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Squash) Validate() error { + if m == nil { + return nil + } + + if len(m.GetCluster()) < 1 { + return SquashValidationError{ + Field: "Cluster", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetAttachmentTemplate()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return SquashValidationError{ + Field: "AttachmentTemplate", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetRequestTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return SquashValidationError{ + Field: "RequestTimeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetAttachmentTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return SquashValidationError{ + Field: "AttachmentTimeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetAttachmentPollPeriod()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return SquashValidationError{ + Field: "AttachmentPollPeriod", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// SquashValidationError is the validation error returned by Squash.Validate if +// the designated constraints aren't met. +type SquashValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e SquashValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sSquash.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = SquashValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/transcoder/v2/transcoder.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/transcoder/v2/transcoder.pb.validate.go new file mode 100644 index 00000000..e78cd7a5 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/http/transcoder/v2/transcoder.pb.validate.go @@ -0,0 +1,161 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/http/transcoder/v2/transcoder.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on GrpcJsonTranscoder with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *GrpcJsonTranscoder) Validate() error { + if m == nil { + return nil + } + + if len(m.GetServices()) < 1 { + return GrpcJsonTranscoderValidationError{ + Field: "Services", + Reason: "value must contain at least 1 item(s)", + } + } + + if v, ok := interface{}(m.GetPrintOptions()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GrpcJsonTranscoderValidationError{ + Field: "PrintOptions", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + switch m.DescriptorSet.(type) { + + case *GrpcJsonTranscoder_ProtoDescriptor: + // no validation rules for ProtoDescriptor + + case *GrpcJsonTranscoder_ProtoDescriptorBin: + // no validation rules for ProtoDescriptorBin + + default: + return GrpcJsonTranscoderValidationError{ + Field: "DescriptorSet", + Reason: "value is required", + } + + } + + return nil +} + +// GrpcJsonTranscoderValidationError is the validation error returned by +// GrpcJsonTranscoder.Validate if the designated constraints aren't met. +type GrpcJsonTranscoderValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e GrpcJsonTranscoderValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGrpcJsonTranscoder.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = GrpcJsonTranscoderValidationError{} + +// Validate checks the field values on GrpcJsonTranscoder_PrintOptions with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *GrpcJsonTranscoder_PrintOptions) Validate() error { + if m == nil { + return nil + } + + // no validation rules for AddWhitespace + + // no validation rules for AlwaysPrintPrimitiveFields + + // no validation rules for AlwaysPrintEnumsAsInts + + // no validation rules for PreserveProtoFieldNames + + return nil +} + +// GrpcJsonTranscoder_PrintOptionsValidationError is the validation error +// returned by GrpcJsonTranscoder_PrintOptions.Validate if the designated +// constraints aren't met. +type GrpcJsonTranscoder_PrintOptionsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e GrpcJsonTranscoder_PrintOptionsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGrpcJsonTranscoder_PrintOptions.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = GrpcJsonTranscoder_PrintOptionsValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/client_ssl_auth/v2/client_ssl_auth.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/client_ssl_auth/v2/client_ssl_auth.pb.validate.go new file mode 100644 index 00000000..3aa1f73e --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/client_ssl_auth/v2/client_ssl_auth.pb.validate.go @@ -0,0 +1,116 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/network/client_ssl_auth/v2/client_ssl_auth.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on ClientSSLAuth with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *ClientSSLAuth) Validate() error { + if m == nil { + return nil + } + + if len(m.GetAuthApiCluster()) < 1 { + return ClientSSLAuthValidationError{ + Field: "AuthApiCluster", + Reason: "value length must be at least 1 bytes", + } + } + + if len(m.GetStatPrefix()) < 1 { + return ClientSSLAuthValidationError{ + Field: "StatPrefix", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetRefreshDelay()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClientSSLAuthValidationError{ + Field: "RefreshDelay", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetIpWhiteList() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClientSSLAuthValidationError{ + Field: fmt.Sprintf("IpWhiteList[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// ClientSSLAuthValidationError is the validation error returned by +// ClientSSLAuth.Validate if the designated constraints aren't met. +type ClientSSLAuthValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ClientSSLAuthValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClientSSLAuth.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ClientSSLAuthValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/ext_authz/v2/ext_authz.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/ext_authz/v2/ext_authz.pb.validate.go new file mode 100644 index 00000000..7546a8ca --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/ext_authz/v2/ext_authz.pb.validate.go @@ -0,0 +1,95 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/network/ext_authz/v2/ext_authz.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on ExtAuthz with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *ExtAuthz) Validate() error { + if m == nil { + return nil + } + + if len(m.GetStatPrefix()) < 1 { + return ExtAuthzValidationError{ + Field: "StatPrefix", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetGrpcService()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ExtAuthzValidationError{ + Field: "GrpcService", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for FailureModeAllow + + return nil +} + +// ExtAuthzValidationError is the validation error returned by +// ExtAuthz.Validate if the designated constraints aren't met. +type ExtAuthzValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ExtAuthzValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sExtAuthz.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ExtAuthzValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.pb.validate.go new file mode 100644 index 00000000..d0f2be33 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.pb.validate.go @@ -0,0 +1,577 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on HttpConnectionManager with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HttpConnectionManager) Validate() error { + if m == nil { + return nil + } + + if _, ok := HttpConnectionManager_CodecType_name[int32(m.GetCodecType())]; !ok { + return HttpConnectionManagerValidationError{ + Field: "CodecType", + Reason: "value must be one of the defined enum values", + } + } + + if len(m.GetStatPrefix()) < 1 { + return HttpConnectionManagerValidationError{ + Field: "StatPrefix", + Reason: "value length must be at least 1 bytes", + } + } + + for idx, item := range m.GetHttpFilters() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManagerValidationError{ + Field: fmt.Sprintf("HttpFilters[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetAddUserAgent()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManagerValidationError{ + Field: "AddUserAgent", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetTracing()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManagerValidationError{ + Field: "Tracing", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetHttpProtocolOptions()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManagerValidationError{ + Field: "HttpProtocolOptions", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetHttp2ProtocolOptions()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManagerValidationError{ + Field: "Http2ProtocolOptions", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for ServerName + + if v, ok := interface{}(m.GetIdleTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManagerValidationError{ + Field: "IdleTimeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetDrainTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManagerValidationError{ + Field: "DrainTimeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetAccessLog() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManagerValidationError{ + Field: fmt.Sprintf("AccessLog[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetUseRemoteAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManagerValidationError{ + Field: "UseRemoteAddress", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for XffNumTrustedHops + + if v, ok := interface{}(m.GetGenerateRequestId()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManagerValidationError{ + Field: "GenerateRequestId", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if _, ok := HttpConnectionManager_ForwardClientCertDetails_name[int32(m.GetForwardClientCertDetails())]; !ok { + return HttpConnectionManagerValidationError{ + Field: "ForwardClientCertDetails", + Reason: "value must be one of the defined enum values", + } + } + + if v, ok := interface{}(m.GetSetCurrentClientCertDetails()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManagerValidationError{ + Field: "SetCurrentClientCertDetails", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for Proxy_100Continue + + // no validation rules for RepresentIpv4RemoteAddressAsIpv4MappedIpv6 + + switch m.RouteSpecifier.(type) { + + case *HttpConnectionManager_Rds: + + if v, ok := interface{}(m.GetRds()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManagerValidationError{ + Field: "Rds", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *HttpConnectionManager_RouteConfig: + + if v, ok := interface{}(m.GetRouteConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManagerValidationError{ + Field: "RouteConfig", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + default: + return HttpConnectionManagerValidationError{ + Field: "RouteSpecifier", + Reason: "value is required", + } + + } + + return nil +} + +// HttpConnectionManagerValidationError is the validation error returned by +// HttpConnectionManager.Validate if the designated constraints aren't met. +type HttpConnectionManagerValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HttpConnectionManagerValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHttpConnectionManager.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HttpConnectionManagerValidationError{} + +// Validate checks the field values on Rds with the rules defined in the proto +// definition for this message. If any rules are violated, an error is returned. +func (m *Rds) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetConfigSource()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RdsValidationError{ + Field: "ConfigSource", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if len(m.GetRouteConfigName()) < 1 { + return RdsValidationError{ + Field: "RouteConfigName", + Reason: "value length must be at least 1 bytes", + } + } + + return nil +} + +// RdsValidationError is the validation error returned by Rds.Validate if the +// designated constraints aren't met. +type RdsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RdsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRds.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RdsValidationError{} + +// Validate checks the field values on HttpFilter with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *HttpFilter) Validate() error { + if m == nil { + return nil + } + + if len(m.GetName()) < 1 { + return HttpFilterValidationError{ + Field: "Name", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpFilterValidationError{ + Field: "Config", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetDeprecatedV1()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpFilterValidationError{ + Field: "DeprecatedV1", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// HttpFilterValidationError is the validation error returned by +// HttpFilter.Validate if the designated constraints aren't met. +type HttpFilterValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HttpFilterValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHttpFilter.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HttpFilterValidationError{} + +// Validate checks the field values on HttpConnectionManager_Tracing with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HttpConnectionManager_Tracing) Validate() error { + if m == nil { + return nil + } + + if _, ok := HttpConnectionManager_Tracing_OperationName_name[int32(m.GetOperationName())]; !ok { + return HttpConnectionManager_TracingValidationError{ + Field: "OperationName", + Reason: "value must be one of the defined enum values", + } + } + + if v, ok := interface{}(m.GetClientSampling()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManager_TracingValidationError{ + Field: "ClientSampling", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetRandomSampling()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManager_TracingValidationError{ + Field: "RandomSampling", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetOverallSampling()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManager_TracingValidationError{ + Field: "OverallSampling", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// HttpConnectionManager_TracingValidationError is the validation error +// returned by HttpConnectionManager_Tracing.Validate if the designated +// constraints aren't met. +type HttpConnectionManager_TracingValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HttpConnectionManager_TracingValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHttpConnectionManager_Tracing.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HttpConnectionManager_TracingValidationError{} + +// Validate checks the field values on +// HttpConnectionManager_SetCurrentClientCertDetails with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *HttpConnectionManager_SetCurrentClientCertDetails) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetSubject()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManager_SetCurrentClientCertDetailsValidationError{ + Field: "Subject", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetSan()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HttpConnectionManager_SetCurrentClientCertDetailsValidationError{ + Field: "San", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for Cert + + return nil +} + +// HttpConnectionManager_SetCurrentClientCertDetailsValidationError is the +// validation error returned by +// HttpConnectionManager_SetCurrentClientCertDetails.Validate if the +// designated constraints aren't met. +type HttpConnectionManager_SetCurrentClientCertDetailsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HttpConnectionManager_SetCurrentClientCertDetailsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHttpConnectionManager_SetCurrentClientCertDetails.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HttpConnectionManager_SetCurrentClientCertDetailsValidationError{} + +// Validate checks the field values on HttpFilter_DeprecatedV1 with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HttpFilter_DeprecatedV1) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Type + + return nil +} + +// HttpFilter_DeprecatedV1ValidationError is the validation error returned by +// HttpFilter_DeprecatedV1.Validate if the designated constraints aren't met. +type HttpFilter_DeprecatedV1ValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HttpFilter_DeprecatedV1ValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHttpFilter_DeprecatedV1.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HttpFilter_DeprecatedV1ValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/mongo_proxy/v2/mongo_proxy.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/mongo_proxy/v2/mongo_proxy.pb.validate.go new file mode 100644 index 00000000..41f01a8b --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/mongo_proxy/v2/mongo_proxy.pb.validate.go @@ -0,0 +1,95 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/network/mongo_proxy/v2/mongo_proxy.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on MongoProxy with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *MongoProxy) Validate() error { + if m == nil { + return nil + } + + if len(m.GetStatPrefix()) < 1 { + return MongoProxyValidationError{ + Field: "StatPrefix", + Reason: "value length must be at least 1 bytes", + } + } + + // no validation rules for AccessLog + + if v, ok := interface{}(m.GetDelay()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return MongoProxyValidationError{ + Field: "Delay", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// MongoProxyValidationError is the validation error returned by +// MongoProxy.Validate if the designated constraints aren't met. +type MongoProxyValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e MongoProxyValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sMongoProxy.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = MongoProxyValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/rate_limit/v2/rate_limit.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/rate_limit/v2/rate_limit.pb.validate.go new file mode 100644 index 00000000..ad98bffa --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/rate_limit/v2/rate_limit.pb.validate.go @@ -0,0 +1,122 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/network/rate_limit/v2/rate_limit.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on RateLimit with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *RateLimit) Validate() error { + if m == nil { + return nil + } + + if len(m.GetStatPrefix()) < 1 { + return RateLimitValidationError{ + Field: "StatPrefix", + Reason: "value length must be at least 1 bytes", + } + } + + if len(m.GetDomain()) < 1 { + return RateLimitValidationError{ + Field: "Domain", + Reason: "value length must be at least 1 bytes", + } + } + + if len(m.GetDescriptors()) < 1 { + return RateLimitValidationError{ + Field: "Descriptors", + Reason: "value must contain at least 1 item(s)", + } + } + + for idx, item := range m.GetDescriptors() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimitValidationError{ + Field: fmt.Sprintf("Descriptors[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimitValidationError{ + Field: "Timeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// RateLimitValidationError is the validation error returned by +// RateLimit.Validate if the designated constraints aren't met. +type RateLimitValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimitValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimit.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimitValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/redis_proxy/v2/redis_proxy.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/redis_proxy/v2/redis_proxy.pb.validate.go new file mode 100644 index 00000000..d7c21652 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/redis_proxy/v2/redis_proxy.pb.validate.go @@ -0,0 +1,157 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/network/redis_proxy/v2/redis_proxy.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on RedisProxy with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *RedisProxy) Validate() error { + if m == nil { + return nil + } + + if len(m.GetStatPrefix()) < 1 { + return RedisProxyValidationError{ + Field: "StatPrefix", + Reason: "value length must be at least 1 bytes", + } + } + + if len(m.GetCluster()) < 1 { + return RedisProxyValidationError{ + Field: "Cluster", + Reason: "value length must be at least 1 bytes", + } + } + + if m.GetSettings() == nil { + return RedisProxyValidationError{ + Field: "Settings", + Reason: "value is required", + } + } + + if v, ok := interface{}(m.GetSettings()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RedisProxyValidationError{ + Field: "Settings", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// RedisProxyValidationError is the validation error returned by +// RedisProxy.Validate if the designated constraints aren't met. +type RedisProxyValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RedisProxyValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRedisProxy.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RedisProxyValidationError{} + +// Validate checks the field values on RedisProxy_ConnPoolSettings with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RedisProxy_ConnPoolSettings) Validate() error { + if m == nil { + return nil + } + + if m.GetOpTimeout() == nil { + return RedisProxy_ConnPoolSettingsValidationError{ + Field: "OpTimeout", + Reason: "value is required", + } + } + + return nil +} + +// RedisProxy_ConnPoolSettingsValidationError is the validation error returned +// by RedisProxy_ConnPoolSettings.Validate if the designated constraints +// aren't met. +type RedisProxy_ConnPoolSettingsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RedisProxy_ConnPoolSettingsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRedisProxy_ConnPoolSettings.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RedisProxy_ConnPoolSettingsValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/tcp_proxy/v2/tcp_proxy.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/tcp_proxy/v2/tcp_proxy.pb.validate.go new file mode 100644 index 00000000..720b0414 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/filter/network/tcp_proxy/v2/tcp_proxy.pb.validate.go @@ -0,0 +1,313 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/filter/network/tcp_proxy/v2/tcp_proxy.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on TcpProxy with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *TcpProxy) Validate() error { + if m == nil { + return nil + } + + if len(m.GetStatPrefix()) < 1 { + return TcpProxyValidationError{ + Field: "StatPrefix", + Reason: "value length must be at least 1 bytes", + } + } + + // no validation rules for Cluster + + if v, ok := interface{}(m.GetMetadataMatch()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TcpProxyValidationError{ + Field: "MetadataMatch", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if d := m.GetIdleTimeout(); d != nil { + dur := *d + + gt := time.Duration(0*time.Second + 0*time.Nanosecond) + + if dur <= gt { + return TcpProxyValidationError{ + Field: "IdleTimeout", + Reason: "value must be greater than 0s", + } + } + + } + + if v, ok := interface{}(m.GetDownstreamIdleTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TcpProxyValidationError{ + Field: "DownstreamIdleTimeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetUpstreamIdleTimeout()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TcpProxyValidationError{ + Field: "UpstreamIdleTimeout", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetAccessLog() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TcpProxyValidationError{ + Field: fmt.Sprintf("AccessLog[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetDeprecatedV1()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TcpProxyValidationError{ + Field: "DeprecatedV1", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if wrapper := m.GetMaxConnectAttempts(); wrapper != nil { + + if wrapper.GetValue() < 1 { + return TcpProxyValidationError{ + Field: "MaxConnectAttempts", + Reason: "value must be greater than or equal to 1", + } + } + + } + + return nil +} + +// TcpProxyValidationError is the validation error returned by +// TcpProxy.Validate if the designated constraints aren't met. +type TcpProxyValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TcpProxyValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTcpProxy.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TcpProxyValidationError{} + +// Validate checks the field values on TcpProxy_DeprecatedV1 with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *TcpProxy_DeprecatedV1) Validate() error { + if m == nil { + return nil + } + + if len(m.GetRoutes()) < 1 { + return TcpProxy_DeprecatedV1ValidationError{ + Field: "Routes", + Reason: "value must contain at least 1 item(s)", + } + } + + for idx, item := range m.GetRoutes() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TcpProxy_DeprecatedV1ValidationError{ + Field: fmt.Sprintf("Routes[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// TcpProxy_DeprecatedV1ValidationError is the validation error returned by +// TcpProxy_DeprecatedV1.Validate if the designated constraints aren't met. +type TcpProxy_DeprecatedV1ValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TcpProxy_DeprecatedV1ValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTcpProxy_DeprecatedV1.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TcpProxy_DeprecatedV1ValidationError{} + +// Validate checks the field values on TcpProxy_DeprecatedV1_TCPRoute with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *TcpProxy_DeprecatedV1_TCPRoute) Validate() error { + if m == nil { + return nil + } + + if len(m.GetCluster()) < 1 { + return TcpProxy_DeprecatedV1_TCPRouteValidationError{ + Field: "Cluster", + Reason: "value length must be at least 1 bytes", + } + } + + for idx, item := range m.GetDestinationIpList() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TcpProxy_DeprecatedV1_TCPRouteValidationError{ + Field: fmt.Sprintf("DestinationIpList[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + // no validation rules for DestinationPorts + + for idx, item := range m.GetSourceIpList() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TcpProxy_DeprecatedV1_TCPRouteValidationError{ + Field: fmt.Sprintf("SourceIpList[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + // no validation rules for SourcePorts + + return nil +} + +// TcpProxy_DeprecatedV1_TCPRouteValidationError is the validation error +// returned by TcpProxy_DeprecatedV1_TCPRoute.Validate if the designated +// constraints aren't met. +type TcpProxy_DeprecatedV1_TCPRouteValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TcpProxy_DeprecatedV1_TCPRouteValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTcpProxy_DeprecatedV1_TCPRoute.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TcpProxy_DeprecatedV1_TCPRouteValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/metrics/v2/metrics_service.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/metrics/v2/metrics_service.pb.validate.go new file mode 100644 index 00000000..49d93b47 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/metrics/v2/metrics_service.pb.validate.go @@ -0,0 +1,94 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/metrics/v2/metrics_service.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on MetricsServiceConfig with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *MetricsServiceConfig) Validate() error { + if m == nil { + return nil + } + + if m.GetGrpcService() == nil { + return MetricsServiceConfigValidationError{ + Field: "GrpcService", + Reason: "value is required", + } + } + + if v, ok := interface{}(m.GetGrpcService()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return MetricsServiceConfigValidationError{ + Field: "GrpcService", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// MetricsServiceConfigValidationError is the validation error returned by +// MetricsServiceConfig.Validate if the designated constraints aren't met. +type MetricsServiceConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e MetricsServiceConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sMetricsServiceConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = MetricsServiceConfigValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/metrics/v2/stats.pb.go b/github.com/envoyproxy/go-control-plane/envoy/config/metrics/v2/stats.pb.go index 54cffb6f..965bc78f 100644 --- a/github.com/envoyproxy/go-control-plane/envoy/config/metrics/v2/stats.pb.go +++ b/github.com/envoyproxy/go-control-plane/envoy/config/metrics/v2/stats.pb.go @@ -26,6 +26,8 @@ type StatsSink struct { // * :ref:`envoy.statsd ` // * :ref:`envoy.dog_statsd ` // * :ref:`envoy.metrics_service ` + // + // Sinks optionally support tagged/multiple dimensional metrics. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Stats sink specific configuration which depends on the sink being // instantiated. See :ref:`StatsdSink ` for an @@ -236,7 +238,8 @@ func _TagSpecifier_OneofSizer(msg proto.Message) (n int) { return n } -// Stats configuration proto schema for built-in *envoy.statsd* sink. +// Stats configuration proto schema for built-in *envoy.statsd* sink. This sink does not support +// tagged metrics. type StatsdSink struct { // Types that are valid to be assigned to StatsdSpecifier: // *StatsdSink_Address diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/metrics/v2/stats.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/metrics/v2/stats.pb.validate.go new file mode 100644 index 00000000..7e211fb6 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/metrics/v2/stats.pb.validate.go @@ -0,0 +1,339 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/metrics/v2/stats.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on StatsSink with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *StatsSink) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Name + + if v, ok := interface{}(m.GetConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StatsSinkValidationError{ + Field: "Config", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// StatsSinkValidationError is the validation error returned by +// StatsSink.Validate if the designated constraints aren't met. +type StatsSinkValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StatsSinkValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStatsSink.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StatsSinkValidationError{} + +// Validate checks the field values on StatsConfig with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *StatsConfig) Validate() error { + if m == nil { + return nil + } + + for idx, item := range m.GetStatsTags() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StatsConfigValidationError{ + Field: fmt.Sprintf("StatsTags[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetUseAllDefaultTags()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StatsConfigValidationError{ + Field: "UseAllDefaultTags", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// StatsConfigValidationError is the validation error returned by +// StatsConfig.Validate if the designated constraints aren't met. +type StatsConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StatsConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStatsConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StatsConfigValidationError{} + +// Validate checks the field values on TagSpecifier with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *TagSpecifier) Validate() error { + if m == nil { + return nil + } + + // no validation rules for TagName + + switch m.TagValue.(type) { + + case *TagSpecifier_Regex: + // no validation rules for Regex + + case *TagSpecifier_FixedValue: + // no validation rules for FixedValue + + } + + return nil +} + +// TagSpecifierValidationError is the validation error returned by +// TagSpecifier.Validate if the designated constraints aren't met. +type TagSpecifierValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TagSpecifierValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTagSpecifier.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TagSpecifierValidationError{} + +// Validate checks the field values on StatsdSink with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *StatsdSink) Validate() error { + if m == nil { + return nil + } + + switch m.StatsdSpecifier.(type) { + + case *StatsdSink_Address: + + if v, ok := interface{}(m.GetAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StatsdSinkValidationError{ + Field: "Address", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *StatsdSink_TcpClusterName: + // no validation rules for TcpClusterName + + default: + return StatsdSinkValidationError{ + Field: "StatsdSpecifier", + Reason: "value is required", + } + + } + + return nil +} + +// StatsdSinkValidationError is the validation error returned by +// StatsdSink.Validate if the designated constraints aren't met. +type StatsdSinkValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StatsdSinkValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStatsdSink.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StatsdSinkValidationError{} + +// Validate checks the field values on DogStatsdSink with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *DogStatsdSink) Validate() error { + if m == nil { + return nil + } + + switch m.DogStatsdSpecifier.(type) { + + case *DogStatsdSink_Address: + + if v, ok := interface{}(m.GetAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return DogStatsdSinkValidationError{ + Field: "Address", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + default: + return DogStatsdSinkValidationError{ + Field: "DogStatsdSpecifier", + Reason: "value is required", + } + + } + + return nil +} + +// DogStatsdSinkValidationError is the validation error returned by +// DogStatsdSink.Validate if the designated constraints aren't met. +type DogStatsdSinkValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e DogStatsdSinkValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDogStatsdSink.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = DogStatsdSinkValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/ratelimit/v2/rls.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/ratelimit/v2/rls.pb.validate.go new file mode 100644 index 00000000..65cf3a74 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/ratelimit/v2/rls.pb.validate.go @@ -0,0 +1,108 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/ratelimit/v2/rls.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on RateLimitServiceConfig with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RateLimitServiceConfig) Validate() error { + if m == nil { + return nil + } + + switch m.ServiceSpecifier.(type) { + + case *RateLimitServiceConfig_ClusterName: + + if len(m.GetClusterName()) < 1 { + return RateLimitServiceConfigValidationError{ + Field: "ClusterName", + Reason: "value length must be at least 1 bytes", + } + } + + case *RateLimitServiceConfig_GrpcService: + + if v, ok := interface{}(m.GetGrpcService()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimitServiceConfigValidationError{ + Field: "GrpcService", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + default: + return RateLimitServiceConfigValidationError{ + Field: "ServiceSpecifier", + Reason: "value is required", + } + + } + + return nil +} + +// RateLimitServiceConfigValidationError is the validation error returned by +// RateLimitServiceConfig.Validate if the designated constraints aren't met. +type RateLimitServiceConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimitServiceConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimitServiceConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimitServiceConfigValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/config/trace/v2/trace.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/config/trace/v2/trace.pb.validate.go new file mode 100644 index 00000000..06926b58 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/config/trace/v2/trace.pb.validate.go @@ -0,0 +1,375 @@ +// Code generated by protoc-gen-validate +// source: envoy/config/trace/v2/trace.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Tracing with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Tracing) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetHttp()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TracingValidationError{ + Field: "Http", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// TracingValidationError is the validation error returned by Tracing.Validate +// if the designated constraints aren't met. +type TracingValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TracingValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTracing.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TracingValidationError{} + +// Validate checks the field values on LightstepConfig with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *LightstepConfig) Validate() error { + if m == nil { + return nil + } + + if len(m.GetCollectorCluster()) < 1 { + return LightstepConfigValidationError{ + Field: "CollectorCluster", + Reason: "value length must be at least 1 bytes", + } + } + + if len(m.GetAccessTokenFile()) < 1 { + return LightstepConfigValidationError{ + Field: "AccessTokenFile", + Reason: "value length must be at least 1 bytes", + } + } + + return nil +} + +// LightstepConfigValidationError is the validation error returned by +// LightstepConfig.Validate if the designated constraints aren't met. +type LightstepConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e LightstepConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sLightstepConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = LightstepConfigValidationError{} + +// Validate checks the field values on ZipkinConfig with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *ZipkinConfig) Validate() error { + if m == nil { + return nil + } + + if len(m.GetCollectorCluster()) < 1 { + return ZipkinConfigValidationError{ + Field: "CollectorCluster", + Reason: "value length must be at least 1 bytes", + } + } + + if len(m.GetCollectorEndpoint()) < 1 { + return ZipkinConfigValidationError{ + Field: "CollectorEndpoint", + Reason: "value length must be at least 1 bytes", + } + } + + return nil +} + +// ZipkinConfigValidationError is the validation error returned by +// ZipkinConfig.Validate if the designated constraints aren't met. +type ZipkinConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ZipkinConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sZipkinConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ZipkinConfigValidationError{} + +// Validate checks the field values on DynamicOtConfig with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *DynamicOtConfig) Validate() error { + if m == nil { + return nil + } + + if len(m.GetLibrary()) < 1 { + return DynamicOtConfigValidationError{ + Field: "Library", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return DynamicOtConfigValidationError{ + Field: "Config", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// DynamicOtConfigValidationError is the validation error returned by +// DynamicOtConfig.Validate if the designated constraints aren't met. +type DynamicOtConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e DynamicOtConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDynamicOtConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = DynamicOtConfigValidationError{} + +// Validate checks the field values on TraceServiceConfig with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *TraceServiceConfig) Validate() error { + if m == nil { + return nil + } + + if m.GetGrpcService() == nil { + return TraceServiceConfigValidationError{ + Field: "GrpcService", + Reason: "value is required", + } + } + + if v, ok := interface{}(m.GetGrpcService()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TraceServiceConfigValidationError{ + Field: "GrpcService", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// TraceServiceConfigValidationError is the validation error returned by +// TraceServiceConfig.Validate if the designated constraints aren't met. +type TraceServiceConfigValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e TraceServiceConfigValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTraceServiceConfig.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = TraceServiceConfigValidationError{} + +// Validate checks the field values on Tracing_Http with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *Tracing_Http) Validate() error { + if m == nil { + return nil + } + + if len(m.GetName()) < 1 { + return Tracing_HttpValidationError{ + Field: "Name", + Reason: "value length must be at least 1 bytes", + } + } + + if v, ok := interface{}(m.GetConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return Tracing_HttpValidationError{ + Field: "Config", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// Tracing_HttpValidationError is the validation error returned by +// Tracing_Http.Validate if the designated constraints aren't met. +type Tracing_HttpValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Tracing_HttpValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTracing_Http.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Tracing_HttpValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/service/accesslog/v2/als.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/service/accesslog/v2/als.pb.validate.go new file mode 100644 index 00000000..2a6db864 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/service/accesslog/v2/als.pb.validate.go @@ -0,0 +1,361 @@ +// Code generated by protoc-gen-validate +// source: envoy/service/accesslog/v2/als.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on StreamAccessLogsResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *StreamAccessLogsResponse) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// StreamAccessLogsResponseValidationError is the validation error returned by +// StreamAccessLogsResponse.Validate if the designated constraints aren't met. +type StreamAccessLogsResponseValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StreamAccessLogsResponseValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStreamAccessLogsResponse.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StreamAccessLogsResponseValidationError{} + +// Validate checks the field values on StreamAccessLogsMessage with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *StreamAccessLogsMessage) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetIdentifier()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StreamAccessLogsMessageValidationError{ + Field: "Identifier", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + switch m.LogEntries.(type) { + + case *StreamAccessLogsMessage_HttpLogs: + + if v, ok := interface{}(m.GetHttpLogs()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StreamAccessLogsMessageValidationError{ + Field: "HttpLogs", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *StreamAccessLogsMessage_TcpLogs: + + if v, ok := interface{}(m.GetTcpLogs()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StreamAccessLogsMessageValidationError{ + Field: "TcpLogs", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + default: + return StreamAccessLogsMessageValidationError{ + Field: "LogEntries", + Reason: "value is required", + } + + } + + return nil +} + +// StreamAccessLogsMessageValidationError is the validation error returned by +// StreamAccessLogsMessage.Validate if the designated constraints aren't met. +type StreamAccessLogsMessageValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StreamAccessLogsMessageValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStreamAccessLogsMessage.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StreamAccessLogsMessageValidationError{} + +// Validate checks the field values on StreamAccessLogsMessage_Identifier with +// the rules defined in the proto definition for this message. If any rules +// are violated, an error is returned. +func (m *StreamAccessLogsMessage_Identifier) Validate() error { + if m == nil { + return nil + } + + if m.GetNode() == nil { + return StreamAccessLogsMessage_IdentifierValidationError{ + Field: "Node", + Reason: "value is required", + } + } + + if v, ok := interface{}(m.GetNode()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StreamAccessLogsMessage_IdentifierValidationError{ + Field: "Node", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if len(m.GetLogName()) < 1 { + return StreamAccessLogsMessage_IdentifierValidationError{ + Field: "LogName", + Reason: "value length must be at least 1 bytes", + } + } + + return nil +} + +// StreamAccessLogsMessage_IdentifierValidationError is the validation error +// returned by StreamAccessLogsMessage_Identifier.Validate if the designated +// constraints aren't met. +type StreamAccessLogsMessage_IdentifierValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StreamAccessLogsMessage_IdentifierValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStreamAccessLogsMessage_Identifier.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StreamAccessLogsMessage_IdentifierValidationError{} + +// Validate checks the field values on +// StreamAccessLogsMessage_HTTPAccessLogEntries with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *StreamAccessLogsMessage_HTTPAccessLogEntries) Validate() error { + if m == nil { + return nil + } + + if len(m.GetLogEntry()) < 1 { + return StreamAccessLogsMessage_HTTPAccessLogEntriesValidationError{ + Field: "LogEntry", + Reason: "value must contain at least 1 item(s)", + } + } + + for idx, item := range m.GetLogEntry() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StreamAccessLogsMessage_HTTPAccessLogEntriesValidationError{ + Field: fmt.Sprintf("LogEntry[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// StreamAccessLogsMessage_HTTPAccessLogEntriesValidationError is the +// validation error returned by +// StreamAccessLogsMessage_HTTPAccessLogEntries.Validate if the designated +// constraints aren't met. +type StreamAccessLogsMessage_HTTPAccessLogEntriesValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StreamAccessLogsMessage_HTTPAccessLogEntriesValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStreamAccessLogsMessage_HTTPAccessLogEntries.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StreamAccessLogsMessage_HTTPAccessLogEntriesValidationError{} + +// Validate checks the field values on +// StreamAccessLogsMessage_TCPAccessLogEntries with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *StreamAccessLogsMessage_TCPAccessLogEntries) Validate() error { + if m == nil { + return nil + } + + if len(m.GetLogEntry()) < 1 { + return StreamAccessLogsMessage_TCPAccessLogEntriesValidationError{ + Field: "LogEntry", + Reason: "value must contain at least 1 item(s)", + } + } + + for idx, item := range m.GetLogEntry() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StreamAccessLogsMessage_TCPAccessLogEntriesValidationError{ + Field: fmt.Sprintf("LogEntry[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// StreamAccessLogsMessage_TCPAccessLogEntriesValidationError is the validation +// error returned by StreamAccessLogsMessage_TCPAccessLogEntries.Validate if +// the designated constraints aren't met. +type StreamAccessLogsMessage_TCPAccessLogEntriesValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StreamAccessLogsMessage_TCPAccessLogEntriesValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStreamAccessLogsMessage_TCPAccessLogEntries.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StreamAccessLogsMessage_TCPAccessLogEntriesValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/service/auth/v2/attribute_context.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/service/auth/v2/attribute_context.pb.validate.go new file mode 100644 index 00000000..be5582a2 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/service/auth/v2/attribute_context.pb.validate.go @@ -0,0 +1,292 @@ +// Code generated by protoc-gen-validate +// source: envoy/service/auth/v2/attribute_context.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on AttributeContext with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *AttributeContext) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetSource()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AttributeContextValidationError{ + Field: "Source", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetDestination()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AttributeContextValidationError{ + Field: "Destination", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetRequest()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AttributeContextValidationError{ + Field: "Request", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for ContextExtensions + + return nil +} + +// AttributeContextValidationError is the validation error returned by +// AttributeContext.Validate if the designated constraints aren't met. +type AttributeContextValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AttributeContextValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAttributeContext.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AttributeContextValidationError{} + +// Validate checks the field values on AttributeContext_Peer with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *AttributeContext_Peer) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetAddress()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AttributeContext_PeerValidationError{ + Field: "Address", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for Service + + // no validation rules for Labels + + // no validation rules for Principal + + return nil +} + +// AttributeContext_PeerValidationError is the validation error returned by +// AttributeContext_Peer.Validate if the designated constraints aren't met. +type AttributeContext_PeerValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AttributeContext_PeerValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAttributeContext_Peer.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AttributeContext_PeerValidationError{} + +// Validate checks the field values on AttributeContext_Request with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *AttributeContext_Request) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetTime()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AttributeContext_RequestValidationError{ + Field: "Time", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetHttp()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AttributeContext_RequestValidationError{ + Field: "Http", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// AttributeContext_RequestValidationError is the validation error returned by +// AttributeContext_Request.Validate if the designated constraints aren't met. +type AttributeContext_RequestValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AttributeContext_RequestValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAttributeContext_Request.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AttributeContext_RequestValidationError{} + +// Validate checks the field values on AttributeContext_HttpRequest with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *AttributeContext_HttpRequest) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Id + + // no validation rules for Method + + // no validation rules for Headers + + // no validation rules for Path + + // no validation rules for Host + + // no validation rules for Scheme + + // no validation rules for Query + + // no validation rules for Fragment + + // no validation rules for Size + + // no validation rules for Protocol + + return nil +} + +// AttributeContext_HttpRequestValidationError is the validation error returned +// by AttributeContext_HttpRequest.Validate if the designated constraints +// aren't met. +type AttributeContext_HttpRequestValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AttributeContext_HttpRequestValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAttributeContext_HttpRequest.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AttributeContext_HttpRequestValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/service/auth/v2/external_auth.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/service/auth/v2/external_auth.pb.validate.go new file mode 100644 index 00000000..b5ac9dc2 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/service/auth/v2/external_auth.pb.validate.go @@ -0,0 +1,139 @@ +// Code generated by protoc-gen-validate +// source: envoy/service/auth/v2/external_auth.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on CheckRequest with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *CheckRequest) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetAttributes()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CheckRequestValidationError{ + Field: "Attributes", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// CheckRequestValidationError is the validation error returned by +// CheckRequest.Validate if the designated constraints aren't met. +type CheckRequestValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e CheckRequestValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCheckRequest.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = CheckRequestValidationError{} + +// Validate checks the field values on CheckResponse with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *CheckResponse) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetStatus()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CheckResponseValidationError{ + Field: "Status", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// CheckResponseValidationError is the validation error returned by +// CheckResponse.Validate if the designated constraints aren't met. +type CheckResponseValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e CheckResponseValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCheckResponse.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = CheckResponseValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2/ads.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2/ads.pb.validate.go new file mode 100644 index 00000000..2ad4e6d6 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2/ads.pb.validate.go @@ -0,0 +1,76 @@ +// Code generated by protoc-gen-validate +// source: envoy/service/discovery/v2/ads.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on AdsDummy with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *AdsDummy) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// AdsDummyValidationError is the validation error returned by +// AdsDummy.Validate if the designated constraints aren't met. +type AdsDummyValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e AdsDummyValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sAdsDummy.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = AdsDummyValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2/hds.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2/hds.pb.validate.go new file mode 100644 index 00000000..f3419224 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2/hds.pb.validate.go @@ -0,0 +1,528 @@ +// Code generated by protoc-gen-validate +// source: envoy/service/discovery/v2/hds.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Capability with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Capability) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// CapabilityValidationError is the validation error returned by +// Capability.Validate if the designated constraints aren't met. +type CapabilityValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e CapabilityValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sCapability.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = CapabilityValidationError{} + +// Validate checks the field values on HealthCheckRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HealthCheckRequest) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetNode()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckRequestValidationError{ + Field: "Node", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + if v, ok := interface{}(m.GetCapability()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckRequestValidationError{ + Field: "Capability", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// HealthCheckRequestValidationError is the validation error returned by +// HealthCheckRequest.Validate if the designated constraints aren't met. +type HealthCheckRequestValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HealthCheckRequestValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHealthCheckRequest.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HealthCheckRequestValidationError{} + +// Validate checks the field values on EndpointHealth with the rules defined in +// the proto definition for this message. If any rules are violated, an error +// is returned. +func (m *EndpointHealth) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetEndpoint()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return EndpointHealthValidationError{ + Field: "Endpoint", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for HealthStatus + + return nil +} + +// EndpointHealthValidationError is the validation error returned by +// EndpointHealth.Validate if the designated constraints aren't met. +type EndpointHealthValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e EndpointHealthValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sEndpointHealth.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = EndpointHealthValidationError{} + +// Validate checks the field values on EndpointHealthResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *EndpointHealthResponse) Validate() error { + if m == nil { + return nil + } + + for idx, item := range m.GetEndpointsHealth() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return EndpointHealthResponseValidationError{ + Field: fmt.Sprintf("EndpointsHealth[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// EndpointHealthResponseValidationError is the validation error returned by +// EndpointHealthResponse.Validate if the designated constraints aren't met. +type EndpointHealthResponseValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e EndpointHealthResponseValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sEndpointHealthResponse.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = EndpointHealthResponseValidationError{} + +// Validate checks the field values on +// HealthCheckRequestOrEndpointHealthResponse with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *HealthCheckRequestOrEndpointHealthResponse) Validate() error { + if m == nil { + return nil + } + + switch m.RequestType.(type) { + + case *HealthCheckRequestOrEndpointHealthResponse_HealthCheckRequest: + + if v, ok := interface{}(m.GetHealthCheckRequest()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckRequestOrEndpointHealthResponseValidationError{ + Field: "HealthCheckRequest", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + case *HealthCheckRequestOrEndpointHealthResponse_EndpointHealthResponse: + + if v, ok := interface{}(m.GetEndpointHealthResponse()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckRequestOrEndpointHealthResponseValidationError{ + Field: "EndpointHealthResponse", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// HealthCheckRequestOrEndpointHealthResponseValidationError is the validation +// error returned by HealthCheckRequestOrEndpointHealthResponse.Validate if +// the designated constraints aren't met. +type HealthCheckRequestOrEndpointHealthResponseValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HealthCheckRequestOrEndpointHealthResponseValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHealthCheckRequestOrEndpointHealthResponse.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HealthCheckRequestOrEndpointHealthResponseValidationError{} + +// Validate checks the field values on LocalityEndpoints with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *LocalityEndpoints) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetLocality()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return LocalityEndpointsValidationError{ + Field: "Locality", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetEndpoints() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return LocalityEndpointsValidationError{ + Field: fmt.Sprintf("Endpoints[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// LocalityEndpointsValidationError is the validation error returned by +// LocalityEndpoints.Validate if the designated constraints aren't met. +type LocalityEndpointsValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e LocalityEndpointsValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sLocalityEndpoints.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = LocalityEndpointsValidationError{} + +// Validate checks the field values on ClusterHealthCheck with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *ClusterHealthCheck) Validate() error { + if m == nil { + return nil + } + + // no validation rules for ClusterName + + for idx, item := range m.GetHealthChecks() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterHealthCheckValidationError{ + Field: fmt.Sprintf("HealthChecks[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + for idx, item := range m.GetEndpoints() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClusterHealthCheckValidationError{ + Field: fmt.Sprintf("Endpoints[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// ClusterHealthCheckValidationError is the validation error returned by +// ClusterHealthCheck.Validate if the designated constraints aren't met. +type ClusterHealthCheckValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e ClusterHealthCheckValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClusterHealthCheck.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = ClusterHealthCheckValidationError{} + +// Validate checks the field values on HealthCheckSpecifier with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *HealthCheckSpecifier) Validate() error { + if m == nil { + return nil + } + + for idx, item := range m.GetHealthCheck() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckSpecifierValidationError{ + Field: fmt.Sprintf("HealthCheck[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + if v, ok := interface{}(m.GetInterval()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return HealthCheckSpecifierValidationError{ + Field: "Interval", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// HealthCheckSpecifierValidationError is the validation error returned by +// HealthCheckSpecifier.Validate if the designated constraints aren't met. +type HealthCheckSpecifierValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e HealthCheckSpecifierValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sHealthCheckSpecifier.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = HealthCheckSpecifierValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2/sds.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2/sds.pb.validate.go new file mode 100644 index 00000000..3aab8d5a --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2/sds.pb.validate.go @@ -0,0 +1,76 @@ +// Code generated by protoc-gen-validate +// source: envoy/service/discovery/v2/sds.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on SdsDummy with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *SdsDummy) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// SdsDummyValidationError is the validation error returned by +// SdsDummy.Validate if the designated constraints aren't met. +type SdsDummyValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e SdsDummyValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sSdsDummy.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = SdsDummyValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/service/load_stats/v2/lrs.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/service/load_stats/v2/lrs.pb.validate.go new file mode 100644 index 00000000..8c955b86 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/service/load_stats/v2/lrs.pb.validate.go @@ -0,0 +1,161 @@ +// Code generated by protoc-gen-validate +// source: envoy/service/load_stats/v2/lrs.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on LoadStatsRequest with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *LoadStatsRequest) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetNode()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return LoadStatsRequestValidationError{ + Field: "Node", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetClusterStats() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return LoadStatsRequestValidationError{ + Field: fmt.Sprintf("ClusterStats[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// LoadStatsRequestValidationError is the validation error returned by +// LoadStatsRequest.Validate if the designated constraints aren't met. +type LoadStatsRequestValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e LoadStatsRequestValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sLoadStatsRequest.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = LoadStatsRequestValidationError{} + +// Validate checks the field values on LoadStatsResponse with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *LoadStatsResponse) Validate() error { + if m == nil { + return nil + } + + if len(m.GetClusters()) < 1 { + return LoadStatsResponseValidationError{ + Field: "Clusters", + Reason: "value must contain at least 1 item(s)", + } + } + + if v, ok := interface{}(m.GetLoadReportingInterval()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return LoadStatsResponseValidationError{ + Field: "LoadReportingInterval", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// LoadStatsResponseValidationError is the validation error returned by +// LoadStatsResponse.Validate if the designated constraints aren't met. +type LoadStatsResponseValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e LoadStatsResponseValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sLoadStatsResponse.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = LoadStatsResponseValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/service/metrics/v2/metrics_service.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/service/metrics/v2/metrics_service.pb.validate.go new file mode 100644 index 00000000..5f5a28d9 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/service/metrics/v2/metrics_service.pb.validate.go @@ -0,0 +1,204 @@ +// Code generated by protoc-gen-validate +// source: envoy/service/metrics/v2/metrics_service.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on StreamMetricsResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *StreamMetricsResponse) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// StreamMetricsResponseValidationError is the validation error returned by +// StreamMetricsResponse.Validate if the designated constraints aren't met. +type StreamMetricsResponseValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StreamMetricsResponseValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStreamMetricsResponse.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StreamMetricsResponseValidationError{} + +// Validate checks the field values on StreamMetricsMessage with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *StreamMetricsMessage) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetIdentifier()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StreamMetricsMessageValidationError{ + Field: "Identifier", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetEnvoyMetrics() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StreamMetricsMessageValidationError{ + Field: fmt.Sprintf("EnvoyMetrics[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// StreamMetricsMessageValidationError is the validation error returned by +// StreamMetricsMessage.Validate if the designated constraints aren't met. +type StreamMetricsMessageValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StreamMetricsMessageValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStreamMetricsMessage.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StreamMetricsMessageValidationError{} + +// Validate checks the field values on StreamMetricsMessage_Identifier with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *StreamMetricsMessage_Identifier) Validate() error { + if m == nil { + return nil + } + + if m.GetNode() == nil { + return StreamMetricsMessage_IdentifierValidationError{ + Field: "Node", + Reason: "value is required", + } + } + + if v, ok := interface{}(m.GetNode()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StreamMetricsMessage_IdentifierValidationError{ + Field: "Node", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// StreamMetricsMessage_IdentifierValidationError is the validation error +// returned by StreamMetricsMessage_Identifier.Validate if the designated +// constraints aren't met. +type StreamMetricsMessage_IdentifierValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StreamMetricsMessage_IdentifierValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStreamMetricsMessage_Identifier.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StreamMetricsMessage_IdentifierValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/service/ratelimit/v2/rls.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/service/ratelimit/v2/rls.pb.validate.go new file mode 100644 index 00000000..bdac1545 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/service/ratelimit/v2/rls.pb.validate.go @@ -0,0 +1,259 @@ +// Code generated by protoc-gen-validate +// source: envoy/service/ratelimit/v2/rls.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on RateLimitRequest with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *RateLimitRequest) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Domain + + for idx, item := range m.GetDescriptors() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimitRequestValidationError{ + Field: fmt.Sprintf("Descriptors[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + // no validation rules for HitsAddend + + return nil +} + +// RateLimitRequestValidationError is the validation error returned by +// RateLimitRequest.Validate if the designated constraints aren't met. +type RateLimitRequestValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimitRequestValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimitRequest.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimitRequestValidationError{} + +// Validate checks the field values on RateLimitResponse with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *RateLimitResponse) Validate() error { + if m == nil { + return nil + } + + // no validation rules for OverallCode + + for idx, item := range m.GetStatuses() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimitResponseValidationError{ + Field: fmt.Sprintf("Statuses[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// RateLimitResponseValidationError is the validation error returned by +// RateLimitResponse.Validate if the designated constraints aren't met. +type RateLimitResponseValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimitResponseValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimitResponse.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimitResponseValidationError{} + +// Validate checks the field values on RateLimitResponse_RateLimit with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *RateLimitResponse_RateLimit) Validate() error { + if m == nil { + return nil + } + + // no validation rules for RequestsPerUnit + + // no validation rules for Unit + + return nil +} + +// RateLimitResponse_RateLimitValidationError is the validation error returned +// by RateLimitResponse_RateLimit.Validate if the designated constraints +// aren't met. +type RateLimitResponse_RateLimitValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimitResponse_RateLimitValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimitResponse_RateLimit.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimitResponse_RateLimitValidationError{} + +// Validate checks the field values on RateLimitResponse_DescriptorStatus with +// the rules defined in the proto definition for this message. If any rules +// are violated, an error is returned. +func (m *RateLimitResponse_DescriptorStatus) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Code + + if v, ok := interface{}(m.GetCurrentLimit()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RateLimitResponse_DescriptorStatusValidationError{ + Field: "CurrentLimit", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + // no validation rules for LimitRemaining + + return nil +} + +// RateLimitResponse_DescriptorStatusValidationError is the validation error +// returned by RateLimitResponse_DescriptorStatus.Validate if the designated +// constraints aren't met. +type RateLimitResponse_DescriptorStatusValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e RateLimitResponse_DescriptorStatusValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sRateLimitResponse_DescriptorStatus.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = RateLimitResponse_DescriptorStatusValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/service/trace/v2/trace_service.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/service/trace/v2/trace_service.pb.validate.go new file mode 100644 index 00000000..3210ffce --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/service/trace/v2/trace_service.pb.validate.go @@ -0,0 +1,204 @@ +// Code generated by protoc-gen-validate +// source: envoy/service/trace/v2/trace_service.proto +// DO NOT EDIT!!! + +package v2 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on StreamTracesResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *StreamTracesResponse) Validate() error { + if m == nil { + return nil + } + + return nil +} + +// StreamTracesResponseValidationError is the validation error returned by +// StreamTracesResponse.Validate if the designated constraints aren't met. +type StreamTracesResponseValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StreamTracesResponseValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStreamTracesResponse.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StreamTracesResponseValidationError{} + +// Validate checks the field values on StreamTracesMessage with the rules +// defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *StreamTracesMessage) Validate() error { + if m == nil { + return nil + } + + if v, ok := interface{}(m.GetIdentifier()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StreamTracesMessageValidationError{ + Field: "Identifier", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + for idx, item := range m.GetSpans() { + _, _ = idx, item + + if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StreamTracesMessageValidationError{ + Field: fmt.Sprintf("Spans[%v]", idx), + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + } + + return nil +} + +// StreamTracesMessageValidationError is the validation error returned by +// StreamTracesMessage.Validate if the designated constraints aren't met. +type StreamTracesMessageValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StreamTracesMessageValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStreamTracesMessage.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StreamTracesMessageValidationError{} + +// Validate checks the field values on StreamTracesMessage_Identifier with the +// rules defined in the proto definition for this message. If any rules are +// violated, an error is returned. +func (m *StreamTracesMessage_Identifier) Validate() error { + if m == nil { + return nil + } + + if m.GetNode() == nil { + return StreamTracesMessage_IdentifierValidationError{ + Field: "Node", + Reason: "value is required", + } + } + + if v, ok := interface{}(m.GetNode()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return StreamTracesMessage_IdentifierValidationError{ + Field: "Node", + Reason: "embedded message failed validation", + Cause: err, + } + } + } + + return nil +} + +// StreamTracesMessage_IdentifierValidationError is the validation error +// returned by StreamTracesMessage_Identifier.Validate if the designated +// constraints aren't met. +type StreamTracesMessage_IdentifierValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e StreamTracesMessage_IdentifierValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sStreamTracesMessage_Identifier.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = StreamTracesMessage_IdentifierValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/type/percent.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/type/percent.pb.validate.go new file mode 100644 index 00000000..38fa3def --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/type/percent.pb.validate.go @@ -0,0 +1,134 @@ +// Code generated by protoc-gen-validate +// source: envoy/type/percent.proto +// DO NOT EDIT!!! + +package envoy_type + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Percent with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Percent) Validate() error { + if m == nil { + return nil + } + + if val := m.GetValue(); val < 0 || val > 100 { + return PercentValidationError{ + Field: "Value", + Reason: "value must be inside range [0, 100]", + } + } + + return nil +} + +// PercentValidationError is the validation error returned by Percent.Validate +// if the designated constraints aren't met. +type PercentValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e PercentValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sPercent.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = PercentValidationError{} + +// Validate checks the field values on FractionalPercent with the rules defined +// in the proto definition for this message. If any rules are violated, an +// error is returned. +func (m *FractionalPercent) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Numerator + + if _, ok := FractionalPercent_DenominatorType_name[int32(m.GetDenominator())]; !ok { + return FractionalPercentValidationError{ + Field: "Denominator", + Reason: "value must be one of the defined enum values", + } + } + + return nil +} + +// FractionalPercentValidationError is the validation error returned by +// FractionalPercent.Validate if the designated constraints aren't met. +type FractionalPercentValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e FractionalPercentValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sFractionalPercent.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = FractionalPercentValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/envoy/type/range.pb.validate.go b/github.com/envoyproxy/go-control-plane/envoy/type/range.pb.validate.go new file mode 100644 index 00000000..e558e9e4 --- /dev/null +++ b/github.com/envoyproxy/go-control-plane/envoy/type/range.pb.validate.go @@ -0,0 +1,80 @@ +// Code generated by protoc-gen-validate +// source: envoy/type/range.proto +// DO NOT EDIT!!! + +package envoy_type + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/gogo/protobuf/types" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = types.DynamicAny{} +) + +// Validate checks the field values on Int64Range with the rules defined in the +// proto definition for this message. If any rules are violated, an error is returned. +func (m *Int64Range) Validate() error { + if m == nil { + return nil + } + + // no validation rules for Start + + // no validation rules for End + + return nil +} + +// Int64RangeValidationError is the validation error returned by +// Int64Range.Validate if the designated constraints aren't met. +type Int64RangeValidationError struct { + Field string + Reason string + Cause error + Key bool +} + +// Error satisfies the builtin error interface +func (e Int64RangeValidationError) Error() string { + cause := "" + if e.Cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.Cause) + } + + key := "" + if e.Key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sInt64Range.%s: %s%s", + key, + e.Field, + e.Reason, + cause) +} + +var _ error = Int64RangeValidationError{} diff --git a/github.com/envoyproxy/go-control-plane/glide.lock b/github.com/envoyproxy/go-control-plane/glide.lock index 7c2879cd..c6af00d7 100644 --- a/github.com/envoyproxy/go-control-plane/glide.lock +++ b/github.com/envoyproxy/go-control-plane/glide.lock @@ -1,8 +1,8 @@ -hash: a952717853c3a38033a035acd2e5b089d33bd759d6464abb53b78a03c848deff -updated: 2018-03-15T10:55:09.93521862-07:00 +hash: 2b24134f468a3e0ddb72640328224a3fded06fa4eee6b62991979ae2fadc25c9 +updated: 2018-03-27T19:44:21.991981981-07:00 imports: - name: github.com/envoyproxy/data-plane-api - version: 47e11810c1af88fdd3cb5fe1aeee139cc67497e0 + version: ec157d3d8b359a1bd65c22116ba4387a459cc53a - name: github.com/gogo/googleapis version: 0cd9801be74a10d5ac39d69626eac8255ffcd502 subpackages: @@ -28,7 +28,7 @@ imports: - ptypes/duration - ptypes/timestamp - name: github.com/lyft/protoc-gen-validate - version: 6cd364ac742e088e22c2d04e90358ce48e1e33e5 + version: cae364899cd8c08b83bfdcabf4ce4dd4a68ca6da subpackages: - validate - name: github.com/sirupsen/logrus @@ -66,7 +66,7 @@ imports: - googleapis/rpc/status - opencensus - name: google.golang.org/grpc - version: 8e4536a86ab602859c20df5ebfd0bd4228d08655 + version: afc05b9e1d36f289ea16ba294894486a3e458246 subpackages: - balancer - balancer/base diff --git a/github.com/envoyproxy/go-control-plane/glide.yaml b/github.com/envoyproxy/go-control-plane/glide.yaml index 7b1c03b0..b505eb76 100644 --- a/github.com/envoyproxy/go-control-plane/glide.yaml +++ b/github.com/envoyproxy/go-control-plane/glide.yaml @@ -14,9 +14,10 @@ import: - package: google.golang.org/grpc version: ^1.7.2 - package: github.com/lyft/protoc-gen-validate + version: cae364899cd8c08b83bfdcabf4ce4dd4a68ca6da - package: istio.io/gogo-genproto - package: github.com/gogo/googleapis - package: github.com/envoyproxy/data-plane-api - version: 47e11810c1af88fdd3cb5fe1aeee139cc67497e0 + version: ec157d3d8b359a1bd65c22116ba4387a459cc53a - package: github.com/sirupsen/logrus version: ^1.0.4 diff --git a/github.com/envoyproxy/go-control-plane/pkg/test/resource/resource.go b/github.com/envoyproxy/go-control-plane/pkg/test/resource/resource.go index 6d258c6e..77f36512 100644 --- a/github.com/envoyproxy/go-control-plane/pkg/test/resource/resource.go +++ b/github.com/envoyproxy/go-control-plane/pkg/test/resource/resource.go @@ -33,8 +33,7 @@ import ( ) const ( - localhost = "127.0.0.1" - httpAccessLog = "envoy.http_grpc_access_log" + localhost = "127.0.0.1" // XdsCluster is the cluster name for the control server (used by non-ADS set-up) XdsCluster = "xds_cluster" @@ -202,7 +201,7 @@ func MakeHTTPListener(mode string, listenerName string, port uint32, route strin Name: util.Router, }}, AccessLog: []*alf.AccessLog{{ - Name: httpAccessLog, + Name: util.HTTPGRPCAccessLog, Config: alsConfigPbst, }}, } diff --git a/github.com/envoyproxy/go-control-plane/pkg/util/wellknown.go b/github.com/envoyproxy/go-control-plane/pkg/util/wellknown.go index 9c4c1325..ab6dc188 100644 --- a/github.com/envoyproxy/go-control-plane/pkg/util/wellknown.go +++ b/github.com/envoyproxy/go-control-plane/pkg/util/wellknown.go @@ -14,7 +14,7 @@ package util -// Common names for Envoy filters. +// HTTP filter names const ( // Buffer HTTP filter Buffer = "envoy.buffer" @@ -46,7 +46,12 @@ const ( Squash = "envoy.squash" // HTTPExternalAuthorization HTTP filter HTTPExternalAuthorization = "envoy.ext_authz" +) +// Network filter names +const ( + // ClientSSLAuth network filter + ClientSSLAuth = "envoy.client_ssl_auth" // Echo network filter Echo = "envoy.echo" // HTTPConnectionManager network filter @@ -62,3 +67,39 @@ const ( // ExternalAuthorization network filter ExternalAuthorization = "envoy.ext_authz" ) + +// Listener filter names +const ( + // OriginalDestination listener filter + OriginalDestination = "envoy.listener.original_dst" + // ProxyProtocol listener filter + ProxyProtocol = "envoy.listener.proxy_protocol" +) + +// Tracing provider names +const ( + // Lightstep tracer name + Lightstep = "envoy.lightstep" + // Zipkin tracer name + Zipkin = "envoy.zipkin" + // DynamicOT tracer name + DynamicOT = "envoy.dynamic.ot" +) + +// Stats sink names +const ( + // Statsd sink + Statsd = "envoy.statsd" + // DogStatsD compatible stastsd sink + DogStatsd = "envoy.dog_statsd" + // MetricsService sink + MetricsService = "envoy.metrics_service" +) + +// Access log sink names +const ( + // FileAccessLog sink name + FileAccessLog = "envoy.file_access_log" + // HTTPGRPCAccessLog sink for the HTTP gRPC access log service + HTTPGRPCAccessLog = "envoy.http_grpc_access_log" +) diff --git a/github.com/go-ini/ini/file.go b/github.com/go-ini/ini/file.go index ce26c3b3..ae6264ac 100644 --- a/github.com/go-ini/ini/file.go +++ b/github.com/go-ini/ini/file.go @@ -140,9 +140,14 @@ func (f *File) Section(name string) *Section { // Section returns list of Section. func (f *File) Sections() []*Section { + if f.BlockMode { + f.lock.RLock() + defer f.lock.RUnlock() + } + sections := make([]*Section, len(f.sectionList)) - for i := range f.sectionList { - sections[i] = f.Section(f.sectionList[i]) + for i, name := range f.sectionList { + sections[i] = f.sections[name] } return sections } diff --git a/github.com/go-ini/ini/ini.go b/github.com/go-ini/ini/ini.go index 535d3588..9f6ea3b4 100644 --- a/github.com/go-ini/ini/ini.go +++ b/github.com/go-ini/ini/ini.go @@ -32,7 +32,7 @@ const ( // Maximum allowed depth when recursively substituing variable names. _DEPTH_VALUES = 99 - _VERSION = "1.32.0" + _VERSION = "1.33.0" ) // Version returns current package version literal. diff --git a/github.com/go-openapi/swag/json.go b/github.com/go-openapi/swag/json.go index cb20a6a0..17ab0f61 100644 --- a/github.com/go-openapi/swag/json.go +++ b/github.com/go-openapi/swag/json.go @@ -96,8 +96,7 @@ func ConcatJSON(blobs ...[]byte) []byte { last := len(blobs) - 1 var opening, closing byte - a := 0 - idx := 0 + var idx, a int buf := bytes.NewBuffer(nil) for i, b := range blobs { diff --git a/github.com/go-openapi/swag/loading.go b/github.com/go-openapi/swag/loading.go index 8a2c8543..70f4fb36 100644 --- a/github.com/go-openapi/swag/loading.go +++ b/github.com/go-openapi/swag/loading.go @@ -19,7 +19,6 @@ import ( "io/ioutil" "log" "net/http" - "net/url" "path/filepath" "strings" "time" @@ -45,7 +44,10 @@ func LoadStrategy(path string, local, remote func(string) ([]byte, error)) func( return remote } return func(pth string) ([]byte, error) { - upth, _ := url.PathUnescape(pth) + upth, err := pathUnescape(pth) + if err != nil { + return nil, err + } return local(filepath.FromSlash(upth)) } } diff --git a/github.com/go-openapi/swag/post_go18.go b/github.com/go-openapi/swag/post_go18.go new file mode 100644 index 00000000..ef48086d --- /dev/null +++ b/github.com/go-openapi/swag/post_go18.go @@ -0,0 +1,9 @@ +// +build go1.8 + +package swag + +import "net/url" + +func pathUnescape(path string) (string, error) { + return url.PathUnescape(path) +} diff --git a/github.com/go-openapi/swag/pre_go18.go b/github.com/go-openapi/swag/pre_go18.go new file mode 100644 index 00000000..860bb2bb --- /dev/null +++ b/github.com/go-openapi/swag/pre_go18.go @@ -0,0 +1,9 @@ +// +build !go1.8 + +package swag + +import "net/url" + +func pathUnescape(path string) (string, error) { + return url.QueryUnescape(path) +} diff --git a/github.com/go-openapi/swag/yaml.go b/github.com/go-openapi/swag/yaml.go index 26502f21..e2eff756 100644 --- a/github.com/go-openapi/swag/yaml.go +++ b/github.com/go-openapi/swag/yaml.go @@ -42,6 +42,7 @@ func YAMLToJSON(data interface{}) (json.RawMessage, error) { return json.RawMessage(b), err } +// 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 { diff --git a/github.com/go-redis/redis/cluster.go b/github.com/go-redis/redis/cluster.go index 781dedb8..4a295115 100644 --- a/github.com/go-redis/redis/cluster.go +++ b/github.com/go-redis/redis/cluster.go @@ -1,6 +1,8 @@ package redis import ( + "context" + "errors" "fmt" "math" "math/rand" @@ -33,6 +35,8 @@ type ClusterOptions struct { ReadOnly bool // Allows routing read-only commands to the closest master or slave node. RouteByLatency bool + // Allows routing read-only commands to the random master or slave node. + RouteRandomly bool // Following options are copied from Options struct. @@ -123,7 +127,7 @@ type clusterNode struct { latency uint32 // atomic generation uint32 // atomic - loading int64 // atomic + loading uint32 // atomic } func newClusterNode(clOpt *ClusterOptions, addr string) *clusterNode { @@ -168,20 +172,20 @@ func (n *clusterNode) Latency() time.Duration { } func (n *clusterNode) MarkAsLoading() { - atomic.StoreInt64(&n.loading, time.Now().Unix()) + atomic.StoreUint32(&n.loading, uint32(time.Now().Unix())) } func (n *clusterNode) Loading() bool { const minute = int64(time.Minute / time.Second) - loading := atomic.LoadInt64(&n.loading) + loading := atomic.LoadUint32(&n.loading) if loading == 0 { return false } - if time.Now().Unix()-loading < minute { + if time.Now().Unix()-int64(loading) < minute { return true } - atomic.StoreInt64(&n.loading, 0) + atomic.StoreUint32(&n.loading, 0) return false } @@ -292,21 +296,6 @@ func (c *clusterNodes) GC(generation uint32) { } } -func (c *clusterNodes) All() ([]*clusterNode, error) { - c.mu.RLock() - defer c.mu.RUnlock() - - if c.closed { - return nil, pool.ErrClosed - } - - cp := make([]*clusterNode, 0, len(c.allNodes)) - for _, node := range c.allNodes { - cp = append(cp, node) - } - return cp, nil -} - func (c *clusterNodes) GetOrCreate(addr string) (*clusterNode, error) { var node *clusterNode var err error @@ -353,6 +342,21 @@ func (c *clusterNodes) GetOrCreate(addr string) (*clusterNode, error) { return node, err } +func (c *clusterNodes) All() ([]*clusterNode, error) { + c.mu.RLock() + defer c.mu.RUnlock() + + if c.closed { + return nil, pool.ErrClosed + } + + cp := make([]*clusterNode, 0, len(c.allNodes)) + for _, node := range c.allNodes { + cp = append(cp, node) + } + return cp, nil +} + func (c *clusterNodes) Random() (*clusterNode, error) { addrs, err := c.Addrs() if err != nil { @@ -412,6 +416,10 @@ func newClusterState(nodes *clusterNodes, slots []ClusterSlot, origin string) (* } } + time.AfterFunc(time.Minute, func() { + nodes.GC(c.generation) + }) + return &c, nil } @@ -468,6 +476,12 @@ func (c *clusterState) slotClosestNode(slot int) (*clusterNode, error) { return node, nil } +func (c *clusterState) slotRandomNode(slot int) *clusterNode { + nodes := c.slotNodes(slot) + n := rand.Intn(len(nodes)) + return nodes[n] +} + func (c *clusterState) slotNodes(slot int) []*clusterNode { if slot >= 0 && slot < len(c.slots) { return c.slots[slot] @@ -477,28 +491,83 @@ func (c *clusterState) slotNodes(slot int) []*clusterNode { //------------------------------------------------------------------------------ +type clusterStateHolder struct { + load func() (*clusterState, error) + + state atomic.Value + + lastErrMu sync.RWMutex + lastErr error + + reloading uint32 // atomic +} + +func newClusterStateHolder(fn func() (*clusterState, error)) *clusterStateHolder { + return &clusterStateHolder{ + load: fn, + } +} + +func (c *clusterStateHolder) Load() (*clusterState, error) { + state, err := c.load() + if err != nil { + c.lastErrMu.Lock() + c.lastErr = err + c.lastErrMu.Unlock() + return nil, err + } + c.state.Store(state) + return state, nil +} + +func (c *clusterStateHolder) LazyReload() { + if !atomic.CompareAndSwapUint32(&c.reloading, 0, 1) { + return + } + go func() { + defer atomic.StoreUint32(&c.reloading, 0) + + _, err := c.Load() + if err == nil { + time.Sleep(time.Second) + } + }() +} + +func (c *clusterStateHolder) Get() (*clusterState, error) { + v := c.state.Load() + if v != nil { + return v.(*clusterState), nil + } + + c.lastErrMu.RLock() + err := c.lastErr + c.lastErrMu.RUnlock() + if err != nil { + return nil, err + } + + return nil, errors.New("redis: cluster has no state") +} + +//------------------------------------------------------------------------------ + // ClusterClient is a Redis Cluster client representing a pool of zero // or more underlying connections. It's safe for concurrent use by // multiple goroutines. type ClusterClient struct { cmdable - opt *ClusterOptions - nodes *clusterNodes - - _state atomic.Value - stateErrMu sync.RWMutex - stateErr error + ctx context.Context - cmdsInfoOnce internal.Once - cmdsInfo map[string]*CommandInfo + opt *ClusterOptions + nodes *clusterNodes + state *clusterStateHolder + cmdsInfoCache *cmdsInfoCache process func(Cmder) error processPipeline func([]Cmder) error processTxPipeline func([]Cmder) error - - // Reports whether slots reloading is in progress. - reloading uint32 } // NewClusterClient returns a Redis Cluster client as described in @@ -507,9 +576,11 @@ func NewClusterClient(opt *ClusterOptions) *ClusterClient { opt.init() c := &ClusterClient{ - opt: opt, - nodes: newClusterNodes(opt), + opt: opt, + nodes: newClusterNodes(opt), + cmdsInfoCache: newCmdsInfoCache(), } + c.state = newClusterStateHolder(c.loadState) c.process = c.defaultProcess c.processPipeline = c.defaultProcessPipeline @@ -517,7 +588,7 @@ func NewClusterClient(opt *ClusterOptions) *ClusterClient { c.cmdable.setProcessor(c.Process) - c.reloadState() + _, _ = c.state.Load() if opt.IdleCheckFrequency > 0 { go c.reaper(opt.IdleCheckFrequency) } @@ -525,6 +596,27 @@ func NewClusterClient(opt *ClusterOptions) *ClusterClient { return c } +func (c *ClusterClient) Context() context.Context { + if c.ctx != nil { + return c.ctx + } + return context.Background() +} + +func (c *ClusterClient) WithContext(ctx context.Context) *ClusterClient { + if ctx == nil { + panic("nil context") + } + c2 := c.copy() + c2.ctx = ctx + return c2 +} + +func (c *ClusterClient) copy() *ClusterClient { + cp := *c + return &cp +} + // Options returns read-only Options that were used to create the client. func (c *ClusterClient) Options() *ClusterOptions { return c.opt @@ -535,24 +627,17 @@ func (c *ClusterClient) retryBackoff(attempt int) time.Duration { } func (c *ClusterClient) cmdInfo(name string) *CommandInfo { - err := c.cmdsInfoOnce.Do(func() error { + cmdsInfo, err := c.cmdsInfoCache.Do(func() (map[string]*CommandInfo, error) { node, err := c.nodes.Random() if err != nil { - return err - } - - cmdsInfo, err := node.Client.Command().Result() - if err != nil { - return err + return nil, err } - - c.cmdsInfo = cmdsInfo - return nil + return node.Client.Command().Result() }) if err != nil { return nil } - info := c.cmdsInfo[name] + info := cmdsInfo[name] if info == nil { internal.Logf("info for cmd=%s not found", name) } @@ -573,7 +658,7 @@ func (c *ClusterClient) cmdSlot(cmd Cmder) int { } func (c *ClusterClient) cmdSlotAndNode(cmd Cmder) (int, *clusterNode, error) { - state, err := c.state() + state, err := c.state.Get() if err != nil { return 0, nil, err } @@ -587,6 +672,11 @@ func (c *ClusterClient) cmdSlotAndNode(cmd Cmder) (int, *clusterNode, error) { return slot, node, err } + if c.opt.RouteRandomly { + node := state.slotRandomNode(slot) + return slot, node, nil + } + node, err := state.slotSlaveNode(slot) return slot, node, err } @@ -596,7 +686,7 @@ func (c *ClusterClient) cmdSlotAndNode(cmd Cmder) (int, *clusterNode, error) { } func (c *ClusterClient) slotMasterNode(slot int) (*clusterNode, error) { - state, err := c.state() + state, err := c.state.Get() if err != nil { return nil, err } @@ -641,7 +731,7 @@ func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error { moved, ask, addr := internal.IsMovedError(err) if moved || ask { - c.lazyReloadState() + c.state.LazyReload() node, err = c.nodes.GetOrCreate(addr) if err != nil { return err @@ -733,7 +823,7 @@ func (c *ClusterClient) defaultProcess(cmd Cmder) error { var addr string moved, ask, addr = internal.IsMovedError(err) if moved || ask { - c.lazyReloadState() + c.state.LazyReload() node, err = c.nodes.GetOrCreate(addr) if err != nil { @@ -756,7 +846,7 @@ func (c *ClusterClient) defaultProcess(cmd Cmder) error { // ForEachMaster concurrently calls the fn on each master node in the cluster. // It returns the first error if any. func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error { - state, err := c.state() + state, err := c.state.Get() if err != nil { return err } @@ -789,7 +879,7 @@ func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error { // ForEachSlave concurrently calls the fn on each slave node in the cluster. // It returns the first error if any. func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error { - state, err := c.state() + state, err := c.state.Get() if err != nil { return err } @@ -822,7 +912,7 @@ func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error { // ForEachNode concurrently calls the fn on each known node in the cluster. // It returns the first error if any. func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error { - state, err := c.state() + state, err := c.state.Get() if err != nil { return err } @@ -862,7 +952,7 @@ func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error { func (c *ClusterClient) PoolStats() *PoolStats { var acc PoolStats - state, _ := c.state() + state, _ := c.state.Get() if state == nil { return &acc } @@ -892,75 +982,34 @@ func (c *ClusterClient) PoolStats() *PoolStats { return &acc } -func (c *ClusterClient) lazyReloadState() { - if !atomic.CompareAndSwapUint32(&c.reloading, 0, 1) { - return - } - go func() { - if c.reloadState() { - time.Sleep(time.Second) - } - atomic.StoreUint32(&c.reloading, 0) - }() -} - -func (c *ClusterClient) reloadState() bool { - for attempt := 0; attempt <= c.opt.MaxRedirects; attempt++ { - if attempt > 0 { - time.Sleep(c.retryBackoff(attempt)) - } - - state, err := c.loadState() - if err == nil { - c._state.Store(state) - time.AfterFunc(time.Minute, func() { - c.nodes.GC(state.generation) - }) - return true - } - - c.setStateErr(err) - switch err { - case pool.ErrClosed, errClusterNoNodes: - return false - } - } - return false -} - func (c *ClusterClient) loadState() (*clusterState, error) { - node, err := c.nodes.Random() + addrs, err := c.nodes.Addrs() if err != nil { return nil, err } - slots, err := node.Client.ClusterSlots().Result() - if err != nil { - return nil, err - } + var firstErr error + for _, addr := range addrs { + node, err := c.nodes.GetOrCreate(addr) + if err != nil { + if firstErr == nil { + firstErr = err + } + continue + } - return newClusterState(c.nodes, slots, node.Client.opt.Addr) -} + slots, err := node.Client.ClusterSlots().Result() + if err != nil { + if firstErr == nil { + firstErr = err + } + continue + } -func (c *ClusterClient) state() (*clusterState, error) { - v := c._state.Load() - if v != nil { - return v.(*clusterState), nil + return newClusterState(c.nodes, slots, node.Client.opt.Addr) } - return nil, c.getStateErr() -} -func (c *ClusterClient) setStateErr(err error) { - c.stateErrMu.Lock() - c.stateErr = err - c.stateErrMu.Unlock() -} - -func (c *ClusterClient) getStateErr() error { - c.stateErrMu.RLock() - err := c.stateErr - c.stateErrMu.RUnlock() - return err + return nil, firstErr } // reaper closes idle connections to the cluster. @@ -1044,7 +1093,7 @@ func (c *ClusterClient) defaultProcessPipeline(cmds []Cmder) error { } func (c *ClusterClient) mapCmdsByNode(cmds []Cmder) (map[*clusterNode][]Cmder, error) { - state, err := c.state() + state, err := c.state.Get() if err != nil { setCmdsErr(cmds, err) return nil, err @@ -1120,7 +1169,7 @@ func (c *ClusterClient) checkMovedErr( moved, ask, addr := internal.IsMovedError(err) if moved { - c.lazyReloadState() + c.state.LazyReload() node, err := c.nodes.GetOrCreate(addr) if err != nil { @@ -1158,7 +1207,7 @@ func (c *ClusterClient) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) { } func (c *ClusterClient) defaultProcessTxPipeline(cmds []Cmder) error { - state, err := c.state() + state, err := c.state.Get() if err != nil { return err } @@ -1360,3 +1409,31 @@ func appendNode(nodes []*clusterNode, node *clusterNode) []*clusterNode { } return append(nodes, node) } + +func appendIfNotExists(ss []string, es ...string) []string { +loop: + for _, e := range es { + for _, s := range ss { + if s == e { + continue loop + } + } + ss = append(ss, e) + } + return ss +} + +func remove(ss []string, es ...string) []string { + if len(es) == 0 { + return ss[:0] + } + for _, e := range es { + for i, s := range ss { + if s == e { + ss = append(ss[:i], ss[i+1:]...) + break + } + } + } + return ss +} diff --git a/github.com/go-redis/redis/command.go b/github.com/go-redis/redis/command.go index 7d45c3fa..1588ca25 100644 --- a/github.com/go-redis/redis/command.go +++ b/github.com/go-redis/redis/command.go @@ -1023,3 +1023,26 @@ func (cmd *CommandsInfoCmd) readReply(cn *pool.Conn) error { cmd.val = v.(map[string]*CommandInfo) return nil } + +//------------------------------------------------------------------------------ + +type cmdsInfoCache struct { + once internal.Once + cmds map[string]*CommandInfo +} + +func newCmdsInfoCache() *cmdsInfoCache { + return &cmdsInfoCache{} +} + +func (c *cmdsInfoCache) Do(fn func() (map[string]*CommandInfo, error)) (map[string]*CommandInfo, error) { + err := c.once.Do(func() error { + cmds, err := fn() + if err != nil { + return err + } + c.cmds = cmds + return nil + }) + return c.cmds, err +} diff --git a/github.com/go-redis/redis/commands.go b/github.com/go-redis/redis/commands.go index 45bb0aed..a3dacacd 100644 --- a/github.com/go-redis/redis/commands.go +++ b/github.com/go-redis/redis/commands.go @@ -39,6 +39,22 @@ func formatSec(dur time.Duration) int64 { return int64(dur / time.Second) } +func appendArgs(dst, src []interface{}) []interface{} { + if len(src) == 1 { + if ss, ok := src[0].([]string); ok { + for _, s := range ss { + dst = append(dst, s) + } + return dst + } + } + + for _, v := range src { + dst = append(dst, v) + } + return dst +} + type Cmdable interface { Pipeline() Pipeliner Pipelined(fn func(Pipeliner) error) ([]Cmder, error) @@ -198,6 +214,7 @@ type Cmdable interface { ConfigGet(parameter string) *SliceCmd ConfigResetStat() *StatusCmd ConfigSet(parameter, value string) *StatusCmd + ConfigRewrite() *StatusCmd DBSize() *IntCmd FlushAll() *StatusCmd FlushAllAsync() *StatusCmd @@ -213,7 +230,7 @@ type Cmdable interface { Time() *TimeCmd Eval(script string, keys []string, args ...interface{}) *Cmd EvalSha(sha1 string, keys []string, args ...interface{}) *Cmd - ScriptExists(scripts ...string) *BoolSliceCmd + ScriptExists(hashes ...string) *BoolSliceCmd ScriptFlush() *StatusCmd ScriptKill() *StatusCmd ScriptLoad(script string) *StringCmd @@ -759,22 +776,18 @@ func (c *cmdable) MGet(keys ...string) *SliceCmd { } func (c *cmdable) MSet(pairs ...interface{}) *StatusCmd { - args := make([]interface{}, 1+len(pairs)) + args := make([]interface{}, 1, 1+len(pairs)) args[0] = "mset" - for i, pair := range pairs { - args[1+i] = pair - } + args = appendArgs(args, pairs) cmd := NewStatusCmd(args...) c.process(cmd) return cmd } func (c *cmdable) MSetNX(pairs ...interface{}) *BoolCmd { - args := make([]interface{}, 1+len(pairs)) + args := make([]interface{}, 1, 1+len(pairs)) args[0] = "msetnx" - for i, pair := range pairs { - args[1+i] = pair - } + args = appendArgs(args, pairs) cmd := NewBoolCmd(args...) c.process(cmd) return cmd @@ -1039,12 +1052,10 @@ func (c *cmdable) LPop(key string) *StringCmd { } func (c *cmdable) LPush(key string, values ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(values)) + args := make([]interface{}, 2, 2+len(values)) args[0] = "lpush" args[1] = key - for i, value := range values { - args[2+i] = value - } + args = appendArgs(args, values) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1103,12 +1114,10 @@ func (c *cmdable) RPopLPush(source, destination string) *StringCmd { } func (c *cmdable) RPush(key string, values ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(values)) + args := make([]interface{}, 2, 2+len(values)) args[0] = "rpush" args[1] = key - for i, value := range values { - args[2+i] = value - } + args = appendArgs(args, values) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1123,12 +1132,10 @@ func (c *cmdable) RPushX(key string, value interface{}) *IntCmd { //------------------------------------------------------------------------------ func (c *cmdable) SAdd(key string, members ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(members)) + args := make([]interface{}, 2, 2+len(members)) args[0] = "sadd" args[1] = key - for i, member := range members { - args[2+i] = member - } + args = appendArgs(args, members) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1241,12 +1248,10 @@ func (c *cmdable) SRandMemberN(key string, count int64) *StringSliceCmd { } func (c *cmdable) SRem(key string, members ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(members)) + args := make([]interface{}, 2, 2+len(members)) args[0] = "srem" args[1] = key - for i, member := range members { - args[2+i] = member - } + args = appendArgs(args, members) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1506,12 +1511,10 @@ func (c *cmdable) ZRank(key, member string) *IntCmd { } func (c *cmdable) ZRem(key string, members ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(members)) + args := make([]interface{}, 2, 2+len(members)) args[0] = "zrem" args[1] = key - for i, member := range members { - args[2+i] = member - } + args = appendArgs(args, members) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1627,12 +1630,10 @@ func (c *cmdable) ZUnionStore(dest string, store ZStore, keys ...string) *IntCmd //------------------------------------------------------------------------------ func (c *cmdable) PFAdd(key string, els ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(els)) + args := make([]interface{}, 2, 2+len(els)) args[0] = "pfadd" args[1] = key - for i, el := range els { - args[2+i] = el - } + args = appendArgs(args, els) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1725,6 +1726,12 @@ func (c *cmdable) ConfigSet(parameter, value string) *StatusCmd { return cmd } +func (c *cmdable) ConfigRewrite() *StatusCmd { + cmd := NewStatusCmd("config", "rewrite") + c.process(cmd) + return cmd +} + // Deperecated. Use DBSize instead. func (c *cmdable) DbSize() *IntCmd { return c.DBSize() @@ -1844,45 +1851,39 @@ func (c *cmdable) Time() *TimeCmd { //------------------------------------------------------------------------------ func (c *cmdable) Eval(script string, keys []string, args ...interface{}) *Cmd { - cmdArgs := make([]interface{}, 3+len(keys)+len(args)) + cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args)) cmdArgs[0] = "eval" cmdArgs[1] = script cmdArgs[2] = len(keys) for i, key := range keys { cmdArgs[3+i] = key } - pos := 3 + len(keys) - for i, arg := range args { - cmdArgs[pos+i] = arg - } + cmdArgs = appendArgs(cmdArgs, args) cmd := NewCmd(cmdArgs...) c.process(cmd) return cmd } func (c *cmdable) EvalSha(sha1 string, keys []string, args ...interface{}) *Cmd { - cmdArgs := make([]interface{}, 3+len(keys)+len(args)) + cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args)) cmdArgs[0] = "evalsha" cmdArgs[1] = sha1 cmdArgs[2] = len(keys) for i, key := range keys { cmdArgs[3+i] = key } - pos := 3 + len(keys) - for i, arg := range args { - cmdArgs[pos+i] = arg - } + cmdArgs = appendArgs(cmdArgs, args) cmd := NewCmd(cmdArgs...) c.process(cmd) return cmd } -func (c *cmdable) ScriptExists(scripts ...string) *BoolSliceCmd { - args := make([]interface{}, 2+len(scripts)) +func (c *cmdable) ScriptExists(hashes ...string) *BoolSliceCmd { + args := make([]interface{}, 2+len(hashes)) args[0] = "script" args[1] = "exists" - for i, script := range scripts { - args[2+i] = script + for i, hash := range hashes { + args[2+i] = hash } cmd := NewBoolSliceCmd(args...) c.process(cmd) diff --git a/github.com/go-redis/redis/internal/proto/write_buffer.go b/github.com/go-redis/redis/internal/proto/write_buffer.go index 096b6d76..cc4014fb 100644 --- a/github.com/go-redis/redis/internal/proto/write_buffer.go +++ b/github.com/go-redis/redis/internal/proto/write_buffer.go @@ -71,17 +71,15 @@ func (w *WriteBuffer) append(val interface{}) error { } else { w.AppendString("0") } - default: - if bm, ok := val.(encoding.BinaryMarshaler); ok { - bb, err := bm.MarshalBinary() - if err != nil { - return err - } - w.AppendBytes(bb) - } else { - return fmt.Errorf( - "redis: can't marshal %T (consider implementing encoding.BinaryMarshaler)", val) + case encoding.BinaryMarshaler: + b, err := v.MarshalBinary() + if err != nil { + return err } + w.AppendBytes(b) + default: + return fmt.Errorf( + "redis: can't marshal %T (consider implementing encoding.BinaryMarshaler)", val) } return nil } diff --git a/github.com/go-redis/redis/pubsub.go b/github.com/go-redis/redis/pubsub.go index 3ee4ea9d..b56728f3 100644 --- a/github.com/go-redis/redis/pubsub.go +++ b/github.com/go-redis/redis/pubsub.go @@ -24,8 +24,8 @@ type PubSub struct { mu sync.Mutex cn *pool.Conn - channels []string - patterns []string + channels map[string]struct{} + patterns map[string]struct{} closed bool cmd *Cmd @@ -67,12 +67,24 @@ func (c *PubSub) _conn(channels []string) (*pool.Conn, error) { func (c *PubSub) resubscribe(cn *pool.Conn) error { var firstErr error if len(c.channels) > 0 { - if err := c._subscribe(cn, "subscribe", c.channels...); err != nil && firstErr == nil { + channels := make([]string, len(c.channels)) + i := 0 + for channel := range c.channels { + channels[i] = channel + i++ + } + if err := c._subscribe(cn, "subscribe", channels...); err != nil && firstErr == nil { firstErr = err } } if len(c.patterns) > 0 { - if err := c._subscribe(cn, "psubscribe", c.patterns...); err != nil && firstErr == nil { + patterns := make([]string, len(c.patterns)) + i := 0 + for pattern := range c.patterns { + patterns[i] = pattern + i++ + } + if err := c._subscribe(cn, "psubscribe", patterns...); err != nil && firstErr == nil { firstErr = err } } @@ -132,7 +144,12 @@ func (c *PubSub) Close() error { func (c *PubSub) Subscribe(channels ...string) error { c.mu.Lock() err := c.subscribe("subscribe", channels...) - c.channels = appendIfNotExists(c.channels, channels...) + if c.channels == nil { + c.channels = make(map[string]struct{}) + } + for _, channel := range channels { + c.channels[channel] = struct{}{} + } c.mu.Unlock() return err } @@ -142,7 +159,12 @@ func (c *PubSub) Subscribe(channels ...string) error { func (c *PubSub) PSubscribe(patterns ...string) error { c.mu.Lock() err := c.subscribe("psubscribe", patterns...) - c.patterns = appendIfNotExists(c.patterns, patterns...) + if c.patterns == nil { + c.patterns = make(map[string]struct{}) + } + for _, pattern := range patterns { + c.patterns[pattern] = struct{}{} + } c.mu.Unlock() return err } @@ -152,7 +174,9 @@ func (c *PubSub) PSubscribe(patterns ...string) error { func (c *PubSub) Unsubscribe(channels ...string) error { c.mu.Lock() err := c.subscribe("unsubscribe", channels...) - c.channels = remove(c.channels, channels...) + for _, channel := range channels { + delete(c.channels, channel) + } c.mu.Unlock() return err } @@ -162,7 +186,9 @@ func (c *PubSub) Unsubscribe(channels ...string) error { func (c *PubSub) PUnsubscribe(patterns ...string) error { c.mu.Lock() err := c.subscribe("punsubscribe", patterns...) - c.patterns = remove(c.patterns, patterns...) + for _, pattern := range patterns { + delete(c.patterns, pattern) + } c.mu.Unlock() return err } @@ -371,31 +397,3 @@ func (c *PubSub) Channel() <-chan *Message { }) return c.ch } - -func appendIfNotExists(ss []string, es ...string) []string { -loop: - for _, e := range es { - for _, s := range ss { - if s == e { - continue loop - } - } - ss = append(ss, e) - } - return ss -} - -func remove(ss []string, es ...string) []string { - if len(es) == 0 { - return ss[:0] - } - for _, e := range es { - for i, s := range ss { - if s == e { - ss = append(ss[:i], ss[i+1:]...) - break - } - } - } - return ss -} diff --git a/github.com/go-redis/redis/redis.go b/github.com/go-redis/redis/redis.go index 20f1ed1c..7a606b70 100644 --- a/github.com/go-redis/redis/redis.go +++ b/github.com/go-redis/redis/redis.go @@ -1,6 +1,7 @@ package redis import ( + "context" "fmt" "log" "os" @@ -11,7 +12,7 @@ import ( "github.com/go-redis/redis/internal/proto" ) -// Nil reply redis returned when key does not exist. +// Nil reply Redis returns when key does not exist. const Nil = proto.Nil func init() { @@ -22,6 +23,17 @@ func SetLogger(logger *log.Logger) { internal.Logger = logger } +type baseClient struct { + opt *Options + connPool pool.Pooler + + process func(Cmder) error + processPipeline func([]Cmder) error + processTxPipeline func([]Cmder) error + + onClose func() error // hook called when client is closed +} + func (c *baseClient) init() { c.process = c.defaultProcess c.processPipeline = c.defaultProcessPipeline @@ -84,16 +96,7 @@ func (c *baseClient) initConn(cn *pool.Conn) error { return nil } - // Temp client to initialize connection. - conn := &Conn{ - baseClient: baseClient{ - opt: c.opt, - connPool: pool.NewSingleConnPool(cn), - }, - } - conn.baseClient.init() - conn.statefulCmdable.setProcessor(conn.Process) - + conn := newConn(c.opt, cn) _, err := conn.Pipelined(func(pipe Pipeliner) error { if c.opt.Password != "" { pipe.Auth(c.opt.Password) @@ -119,10 +122,7 @@ func (c *baseClient) initConn(cn *pool.Conn) error { return nil } -// WrapProcess replaces the process func. It takes a function createWrapper -// which is supplied by the user. createWrapper takes the old process func as -// an input and returns the new wrapper process func. createWrapper should -// use call the old process func within the new process func. +// WrapProcess wraps function that processes Redis commands. func (c *baseClient) WrapProcess(fn func(oldProcess func(cmd Cmder) error) func(cmd Cmder) error) { c.process = fn(c.process) } @@ -338,33 +338,52 @@ func (c *baseClient) txPipelineReadQueued(cn *pool.Conn, cmds []Cmder) error { type Client struct { baseClient cmdable + + ctx context.Context } -func newClient(opt *Options, pool pool.Pooler) *Client { +// NewClient returns a client to the Redis Server specified by Options. +func NewClient(opt *Options) *Client { + opt.init() + c := Client{ baseClient: baseClient{ opt: opt, - connPool: pool, + connPool: newConnPool(opt), }, } c.baseClient.init() - c.cmdable.setProcessor(c.Process) + c.init() + return &c } -// NewClient returns a client to the Redis Server specified by Options. -func NewClient(opt *Options) *Client { - opt.init() - return newClient(opt, newConnPool(opt)) +func (c *Client) init() { + c.cmdable.setProcessor(c.Process) } -func (c *Client) copy() *Client { - c2 := new(Client) - *c2 = *c - c2.cmdable.setProcessor(c2.Process) +func (c *Client) Context() context.Context { + if c.ctx != nil { + return c.ctx + } + return context.Background() +} + +func (c *Client) WithContext(ctx context.Context) *Client { + if ctx == nil { + panic("nil context") + } + c2 := c.copy() + c2.ctx = ctx return c2 } +func (c *Client) copy() *Client { + cp := *c + cp.init() + return &cp +} + // Options returns read-only Options that were used to create the client. func (c *Client) Options() *Options { return c.opt @@ -442,6 +461,18 @@ type Conn struct { statefulCmdable } +func newConn(opt *Options, cn *pool.Conn) *Conn { + c := Conn{ + baseClient: baseClient{ + opt: opt, + connPool: pool.NewSingleConnPool(cn), + }, + } + c.baseClient.init() + c.statefulCmdable.setProcessor(c.Process) + return &c +} + func (c *Conn) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) { return c.Pipeline().Pipelined(fn) } diff --git a/github.com/go-redis/redis/redis_context.go b/github.com/go-redis/redis/redis_context.go deleted file mode 100644 index c00e505f..00000000 --- a/github.com/go-redis/redis/redis_context.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build go1.7 - -package redis - -import ( - "context" - - "github.com/go-redis/redis/internal/pool" -) - -type baseClient struct { - connPool pool.Pooler - opt *Options - - process func(Cmder) error - processPipeline func([]Cmder) error - processTxPipeline func([]Cmder) error - - onClose func() error // hook called when client is closed - - ctx context.Context -} - -func (c *Client) Context() context.Context { - if c.ctx != nil { - return c.ctx - } - return context.Background() -} - -func (c *Client) WithContext(ctx context.Context) *Client { - if ctx == nil { - panic("nil context") - } - c2 := c.copy() - c2.ctx = ctx - return c2 -} diff --git a/github.com/go-redis/redis/redis_no_context.go b/github.com/go-redis/redis/redis_no_context.go deleted file mode 100644 index 8555c5c0..00000000 --- a/github.com/go-redis/redis/redis_no_context.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build !go1.7 - -package redis - -import ( - "github.com/go-redis/redis/internal/pool" -) - -type baseClient struct { - connPool pool.Pooler - opt *Options - - process func(Cmder) error - processPipeline func([]Cmder) error - processTxPipeline func([]Cmder) error - - onClose func() error // hook called when client is closed -} diff --git a/github.com/go-redis/redis/ring.go b/github.com/go-redis/redis/ring.go index 10f33ed0..6d287741 100644 --- a/github.com/go-redis/redis/ring.go +++ b/github.com/go-redis/redis/ring.go @@ -1,6 +1,7 @@ package redis import ( + "context" "errors" "fmt" "math/rand" @@ -15,6 +16,8 @@ import ( "github.com/go-redis/redis/internal/pool" ) +const nreplicas = 100 + var errRingShardsDown = errors.New("redis: all ring shards are down") // RingOptions are used to configure a ring client and should be @@ -85,6 +88,8 @@ func (opt *RingOptions) clientOptions() *Options { } } +//------------------------------------------------------------------------------ + type ringShard struct { Client *Client down int32 @@ -125,6 +130,150 @@ func (shard *ringShard) Vote(up bool) bool { return shard.IsDown() } +//------------------------------------------------------------------------------ + +type ringShards struct { + mu sync.RWMutex + hash *consistenthash.Map + shards map[string]*ringShard // read only + list []*ringShard // read only + closed bool +} + +func newRingShards() *ringShards { + return &ringShards{ + hash: consistenthash.New(nreplicas, nil), + shards: make(map[string]*ringShard), + } +} + +func (c *ringShards) Add(name string, cl *Client) { + shard := &ringShard{Client: cl} + c.hash.Add(name) + c.shards[name] = shard + c.list = append(c.list, shard) +} + +func (c *ringShards) List() []*ringShard { + c.mu.RLock() + list := c.list + c.mu.RUnlock() + return list +} + +func (c *ringShards) Hash(key string) string { + c.mu.RLock() + hash := c.hash.Get(key) + c.mu.RUnlock() + return hash +} + +func (c *ringShards) GetByKey(key string) (*ringShard, error) { + key = hashtag.Key(key) + + c.mu.RLock() + + if c.closed { + c.mu.RUnlock() + return nil, pool.ErrClosed + } + + hash := c.hash.Get(key) + if hash == "" { + c.mu.RUnlock() + return nil, errRingShardsDown + } + + shard := c.shards[hash] + c.mu.RUnlock() + + return shard, nil +} + +func (c *ringShards) GetByHash(name string) (*ringShard, error) { + if name == "" { + return c.Random() + } + + c.mu.RLock() + shard := c.shards[name] + c.mu.RUnlock() + return shard, nil +} + +func (c *ringShards) Random() (*ringShard, error) { + return c.GetByKey(strconv.Itoa(rand.Int())) +} + +// heartbeat monitors state of each shard in the ring. +func (c *ringShards) Heartbeat(frequency time.Duration) { + ticker := time.NewTicker(frequency) + defer ticker.Stop() + for range ticker.C { + var rebalance bool + + c.mu.RLock() + + if c.closed { + c.mu.RUnlock() + break + } + + shards := c.list + c.mu.RUnlock() + + for _, shard := range shards { + err := shard.Client.Ping().Err() + if shard.Vote(err == nil || err == pool.ErrPoolTimeout) { + internal.Logf("ring shard state changed: %s", shard) + rebalance = true + } + } + + if rebalance { + c.rebalance() + } + } +} + +// rebalance removes dead shards from the Ring. +func (c *ringShards) rebalance() { + hash := consistenthash.New(nreplicas, nil) + for name, shard := range c.shards { + if shard.IsUp() { + hash.Add(name) + } + } + + c.mu.Lock() + c.hash = hash + c.mu.Unlock() +} + +func (c *ringShards) Close() error { + c.mu.Lock() + defer c.mu.Unlock() + + if c.closed { + return nil + } + c.closed = true + + var firstErr error + for _, shard := range c.shards { + if err := shard.Client.Close(); err != nil && firstErr == nil { + firstErr = err + } + } + c.hash = nil + c.shards = nil + c.list = nil + + return firstErr +} + +//------------------------------------------------------------------------------ + // Ring is a Redis client that uses constistent hashing to distribute // keys across multiple Redis servers (shards). It's safe for // concurrent use by multiple goroutines. @@ -142,33 +291,22 @@ func (shard *ringShard) Vote(up bool) bool { type Ring struct { cmdable - opt *RingOptions - nreplicas int + ctx context.Context - mu sync.RWMutex - hash *consistenthash.Map - shards map[string]*ringShard - shardsList []*ringShard + opt *RingOptions + shards *ringShards + cmdsInfoCache *cmdsInfoCache processPipeline func([]Cmder) error - - cmdsInfoOnce internal.Once - cmdsInfo map[string]*CommandInfo - - closed bool } func NewRing(opt *RingOptions) *Ring { - const nreplicas = 100 - opt.init() ring := &Ring{ - opt: opt, - nreplicas: nreplicas, - - hash: consistenthash.New(nreplicas, nil), - shards: make(map[string]*ringShard), + opt: opt, + shards: newRingShards(), + cmdsInfoCache: newCmdsInfoCache(), } ring.processPipeline = ring.defaultProcessPipeline ring.cmdable.setProcessor(ring.Process) @@ -176,21 +314,33 @@ func NewRing(opt *RingOptions) *Ring { for name, addr := range opt.Addrs { clopt := opt.clientOptions() clopt.Addr = addr - ring.addShard(name, NewClient(clopt)) + ring.shards.Add(name, NewClient(clopt)) } - go ring.heartbeat() + go ring.shards.Heartbeat(opt.HeartbeatFrequency) return ring } -func (c *Ring) addShard(name string, cl *Client) { - shard := &ringShard{Client: cl} - c.mu.Lock() - c.hash.Add(name) - c.shards[name] = shard - c.shardsList = append(c.shardsList, shard) - c.mu.Unlock() +func (c *Ring) Context() context.Context { + if c.ctx != nil { + return c.ctx + } + return context.Background() +} + +func (c *Ring) WithContext(ctx context.Context) *Ring { + if ctx == nil { + panic("nil context") + } + c2 := c.copy() + c2.ctx = ctx + return c2 +} + +func (c *Ring) copy() *Ring { + cp := *c + return &cp } // Options returns read-only Options that were used to create the client. @@ -204,10 +354,7 @@ func (c *Ring) retryBackoff(attempt int) time.Duration { // PoolStats returns accumulated connection pool stats. func (c *Ring) PoolStats() *PoolStats { - c.mu.RLock() - shards := c.shardsList - c.mu.RUnlock() - + shards := c.shards.List() var acc PoolStats for _, shard := range shards { s := shard.Client.connPool.Stats() @@ -226,7 +373,7 @@ func (c *Ring) Subscribe(channels ...string) *PubSub { panic("at least one channel is required") } - shard, err := c.shardByKey(channels[0]) + shard, err := c.shards.GetByKey(channels[0]) if err != nil { // TODO: return PubSub with sticky error panic(err) @@ -240,7 +387,7 @@ func (c *Ring) PSubscribe(channels ...string) *PubSub { panic("at least one channel is required") } - shard, err := c.shardByKey(channels[0]) + shard, err := c.shards.GetByKey(channels[0]) if err != nil { // TODO: return PubSub with sticky error panic(err) @@ -251,10 +398,7 @@ func (c *Ring) PSubscribe(channels ...string) *PubSub { // ForEachShard concurrently calls the fn on each live shard in the ring. // It returns the first error if any. func (c *Ring) ForEachShard(fn func(client *Client) error) error { - c.mu.RLock() - shards := c.shardsList - c.mu.RUnlock() - + shards := c.shards.List() var wg sync.WaitGroup errCh := make(chan error, 1) for _, shard := range shards { @@ -285,81 +429,38 @@ func (c *Ring) ForEachShard(fn func(client *Client) error) error { } func (c *Ring) cmdInfo(name string) *CommandInfo { - err := c.cmdsInfoOnce.Do(func() error { - c.mu.RLock() - shards := c.shardsList - c.mu.RUnlock() - - var firstErr error + cmdsInfo, err := c.cmdsInfoCache.Do(func() (map[string]*CommandInfo, error) { + shards := c.shards.List() + firstErr := errRingShardsDown for _, shard := range shards { cmdsInfo, err := shard.Client.Command().Result() if err == nil { - c.cmdsInfo = cmdsInfo - return nil + return cmdsInfo, nil } if firstErr == nil { firstErr = err } } - return firstErr + return nil, firstErr }) if err != nil { return nil } - if c.cmdsInfo == nil { - return nil - } - info := c.cmdsInfo[name] + info := cmdsInfo[name] if info == nil { internal.Logf("info for cmd=%s not found", name) } return info } -func (c *Ring) shardByKey(key string) (*ringShard, error) { - key = hashtag.Key(key) - - c.mu.RLock() - - if c.closed { - c.mu.RUnlock() - return nil, pool.ErrClosed - } - - name := c.hash.Get(key) - if name == "" { - c.mu.RUnlock() - return nil, errRingShardsDown - } - - shard := c.shards[name] - c.mu.RUnlock() - return shard, nil -} - -func (c *Ring) randomShard() (*ringShard, error) { - return c.shardByKey(strconv.Itoa(rand.Int())) -} - -func (c *Ring) shardByName(name string) (*ringShard, error) { - if name == "" { - return c.randomShard() - } - - c.mu.RLock() - shard := c.shards[name] - c.mu.RUnlock() - return shard, nil -} - func (c *Ring) cmdShard(cmd Cmder) (*ringShard, error) { cmdInfo := c.cmdInfo(cmd.Name()) pos := cmdFirstKeyPos(cmd, cmdInfo) if pos == 0 { - return c.randomShard() + return c.shards.Random() } firstKey := cmd.stringArg(pos) - return c.shardByKey(firstKey) + return c.shards.GetByKey(firstKey) } func (c *Ring) WrapProcess(fn func(oldProcess func(cmd Cmder) error) func(cmd Cmder) error) { @@ -378,77 +479,6 @@ func (c *Ring) Process(cmd Cmder) error { return shard.Client.Process(cmd) } -// rebalance removes dead shards from the Ring. -func (c *Ring) rebalance() { - hash := consistenthash.New(c.nreplicas, nil) - for name, shard := range c.shards { - if shard.IsUp() { - hash.Add(name) - } - } - - c.mu.Lock() - c.hash = hash - c.mu.Unlock() -} - -// heartbeat monitors state of each shard in the ring. -func (c *Ring) heartbeat() { - ticker := time.NewTicker(c.opt.HeartbeatFrequency) - defer ticker.Stop() - for range ticker.C { - var rebalance bool - - c.mu.RLock() - - if c.closed { - c.mu.RUnlock() - break - } - - shards := c.shardsList - c.mu.RUnlock() - - for _, shard := range shards { - err := shard.Client.Ping().Err() - if shard.Vote(err == nil || err == pool.ErrPoolTimeout) { - internal.Logf("ring shard state changed: %s", shard) - rebalance = true - } - } - - if rebalance { - c.rebalance() - } - } -} - -// Close closes the ring client, releasing any open resources. -// -// It is rare to Close a Ring, as the Ring is meant to be long-lived -// and shared between many goroutines. -func (c *Ring) Close() error { - c.mu.Lock() - defer c.mu.Unlock() - - if c.closed { - return nil - } - c.closed = true - - var firstErr error - for _, shard := range c.shards { - if err := shard.Client.Close(); err != nil && firstErr == nil { - firstErr = err - } - } - c.hash = nil - c.shards = nil - c.shardsList = nil - - return firstErr -} - func (c *Ring) Pipeline() Pipeliner { pipe := Pipeline{ exec: c.processPipeline, @@ -471,11 +501,11 @@ func (c *Ring) defaultProcessPipeline(cmds []Cmder) error { cmdsMap := make(map[string][]Cmder) for _, cmd := range cmds { cmdInfo := c.cmdInfo(cmd.Name()) - name := cmd.stringArg(cmdFirstKeyPos(cmd, cmdInfo)) - if name != "" { - name = c.hash.Get(hashtag.Key(name)) + hash := cmd.stringArg(cmdFirstKeyPos(cmd, cmdInfo)) + if hash != "" { + hash = c.shards.Hash(hashtag.Key(hash)) } - cmdsMap[name] = append(cmdsMap[name], cmd) + cmdsMap[hash] = append(cmdsMap[hash], cmd) } for attempt := 0; attempt <= c.opt.MaxRetries; attempt++ { @@ -485,8 +515,8 @@ func (c *Ring) defaultProcessPipeline(cmds []Cmder) error { var failedCmdsMap map[string][]Cmder - for name, cmds := range cmdsMap { - shard, err := c.shardByName(name) + for hash, cmds := range cmdsMap { + shard, err := c.shards.GetByHash(hash) if err != nil { setCmdsErr(cmds, err) continue @@ -509,7 +539,7 @@ func (c *Ring) defaultProcessPipeline(cmds []Cmder) error { if failedCmdsMap == nil { failedCmdsMap = make(map[string][]Cmder) } - failedCmdsMap[name] = cmds + failedCmdsMap[hash] = cmds } } @@ -529,3 +559,11 @@ func (c *Ring) TxPipeline() Pipeliner { func (c *Ring) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) { panic("not implemented") } + +// Close closes the ring client, releasing any open resources. +// +// It is rare to Close a Ring, as the Ring is meant to be long-lived +// and shared between many goroutines. +func (c *Ring) Close() error { + return c.shards.Close() +} diff --git a/github.com/go-redis/redis/script.go b/github.com/go-redis/redis/script.go index 74135f5a..09f36d93 100644 --- a/github.com/go-redis/redis/script.go +++ b/github.com/go-redis/redis/script.go @@ -10,7 +10,7 @@ import ( type scripter interface { Eval(script string, keys []string, args ...interface{}) *Cmd EvalSha(sha1 string, keys []string, args ...interface{}) *Cmd - ScriptExists(scripts ...string) *BoolSliceCmd + ScriptExists(hashes ...string) *BoolSliceCmd ScriptLoad(script string) *StringCmd } @@ -40,7 +40,7 @@ func (s *Script) Load(c scripter) *StringCmd { } func (s *Script) Exists(c scripter) *BoolSliceCmd { - return c.ScriptExists(s.src) + return c.ScriptExists(s.hash) } func (s *Script) Eval(c scripter, keys []string, args ...interface{}) *Cmd { diff --git a/github.com/go-redis/redis/universal.go b/github.com/go-redis/redis/universal.go index ea42f698..fde3c415 100644 --- a/github.com/go-redis/redis/universal.go +++ b/github.com/go-redis/redis/universal.go @@ -114,6 +114,7 @@ func (o *UniversalOptions) simple() *Options { type UniversalClient interface { Cmdable Process(cmd Cmder) error + WrapProcess(fn func(oldProcess func(cmd Cmder) error) func(cmd Cmder) error) Subscribe(channels ...string) *PubSub PSubscribe(channels ...string) *PubSub Close() error diff --git a/github.com/gophercloud/gophercloud/errors.go b/github.com/gophercloud/gophercloud/errors.go index 88fd2ac6..2466932e 100644 --- a/github.com/gophercloud/gophercloud/errors.go +++ b/github.com/gophercloud/gophercloud/errors.go @@ -72,6 +72,11 @@ type ErrDefault401 struct { ErrUnexpectedResponseCode } +// ErrDefault403 is the default error type returned on a 403 HTTP response code. +type ErrDefault403 struct { + ErrUnexpectedResponseCode +} + // ErrDefault404 is the default error type returned on a 404 HTTP response code. type ErrDefault404 struct { ErrUnexpectedResponseCode @@ -108,6 +113,13 @@ func (e ErrDefault400) Error() string { func (e ErrDefault401) Error() string { return "Authentication failed" } +func (e ErrDefault403) Error() string { + e.DefaultErrString = fmt.Sprintf( + "Request forbidden: [%s %s], error message: %s", + e.Method, e.URL, e.Body, + ) + return e.choseErrString() +} func (e ErrDefault404) Error() string { return "Resource not found" } @@ -141,6 +153,12 @@ type Err401er interface { Error401(ErrUnexpectedResponseCode) error } +// Err403er is the interface resource error types implement to override the error message +// from a 403 error. +type Err403er interface { + Error403(ErrUnexpectedResponseCode) error +} + // Err404er is the interface resource error types implement to override the error message // from a 404 error. type Err404er interface { diff --git a/github.com/gophercloud/gophercloud/openstack/endpoint_location.go b/github.com/gophercloud/gophercloud/openstack/endpoint_location.go index 070ea7cb..12c8aebc 100644 --- a/github.com/gophercloud/gophercloud/openstack/endpoint_location.go +++ b/github.com/gophercloud/gophercloud/openstack/endpoint_location.go @@ -84,7 +84,7 @@ func V3EndpointURL(catalog *tokens3.ServiceCatalog, opts gophercloud.EndpointOpt return "", err } if (opts.Availability == gophercloud.Availability(endpoint.Interface)) && - (opts.Region == "" || endpoint.Region == opts.Region) { + (opts.Region == "" || endpoint.Region == opts.Region || endpoint.RegionID == opts.Region) { endpoints = append(endpoints, endpoint) } } diff --git a/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go b/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go index 6e78d1cb..ebdca58f 100644 --- a/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go +++ b/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go @@ -13,6 +13,7 @@ import ( type Endpoint struct { ID string `json:"id"` Region string `json:"region"` + RegionID string `json:"region_id"` Interface string `json:"interface"` URL string `json:"url"` } diff --git a/github.com/gophercloud/gophercloud/provider_client.go b/github.com/gophercloud/gophercloud/provider_client.go index 72daeb0a..17e45127 100644 --- a/github.com/gophercloud/gophercloud/provider_client.go +++ b/github.com/gophercloud/gophercloud/provider_client.go @@ -126,6 +126,36 @@ func (client *ProviderClient) SetToken(t string) { client.TokenID = t } +//Reauthenticate calls client.ReauthFunc in a thread-safe way. If this is +//called because of a 401 response, the caller may pass the previous token. In +//this case, the reauthentication can be skipped if another thread has already +//reauthenticated in the meantime. If no previous token is known, an empty +//string should be passed instead to force unconditional reauthentication. +func (client *ProviderClient) Reauthenticate(previousToken string) (err error) { + if client.ReauthFunc == nil { + return nil + } + + if client.mut == nil { + return client.ReauthFunc() + } + client.mut.Lock() + defer client.mut.Unlock() + + client.reauthmut.Lock() + client.reauthmut.reauthing = true + client.reauthmut.Unlock() + + if previousToken == "" || client.TokenID == previousToken { + err = client.ReauthFunc() + } + + client.reauthmut.Lock() + client.reauthmut.reauthing = false + client.reauthmut.Unlock() + return +} + // RequestOpts customizes the behavior of the provider.Request() method. type RequestOpts struct { // JSONBody, if provided, will be encoded as JSON and used as the body of the HTTP request. The @@ -254,21 +284,7 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts) } case http.StatusUnauthorized: if client.ReauthFunc != nil { - if client.mut != nil { - client.mut.Lock() - client.reauthmut.Lock() - client.reauthmut.reauthing = true - client.reauthmut.Unlock() - if curtok := client.TokenID; curtok == prereqtok { - err = client.ReauthFunc() - } - client.reauthmut.Lock() - client.reauthmut.reauthing = false - client.reauthmut.Unlock() - client.mut.Unlock() - } else { - err = client.ReauthFunc() - } + err = client.Reauthenticate(prereqtok) if err != nil { e := &ErrUnableToReauthenticate{} e.ErrOriginal = respErr @@ -298,6 +314,11 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts) if error401er, ok := errType.(Err401er); ok { err = error401er.Error401(respErr) } + case http.StatusForbidden: + err = ErrDefault403{respErr} + if error403er, ok := errType.(Err403er); ok { + err = error403er.Error403(respErr) + } case http.StatusNotFound: err = ErrDefault404{respErr} if error404er, ok := errType.(Err404er); ok { diff --git a/github.com/imdario/mergo/map.go b/github.com/imdario/mergo/map.go index 44361e88..20981432 100644 --- a/github.com/imdario/mergo/map.go +++ b/github.com/imdario/mergo/map.go @@ -31,7 +31,8 @@ func isExported(field reflect.StructField) bool { // Traverses recursively both values, assigning src's fields values to dst. // The map argument tracks comparisons that have already been seen, which allows // short circuiting on recursive types. -func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err error) { +func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *config) (err error) { + overwrite := config.overwrite if dst.CanAddr() { addr := dst.UnsafeAddr() h := 17 * addr @@ -57,10 +58,17 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err } fieldName := field.Name fieldName = changeInitialCase(fieldName, unicode.ToLower) - if v, ok := dstMap[fieldName]; !ok || isEmptyValue(reflect.ValueOf(v)) { + if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v)) || overwrite) { dstMap[fieldName] = src.Field(i).Interface() } } + case reflect.Ptr: + if dst.IsNil() { + v := reflect.New(dst.Type().Elem()) + dst.Set(v) + } + dst = dst.Elem() + fallthrough case reflect.Struct: srcMap := src.Interface().(map[string]interface{}) for key := range srcMap { @@ -85,21 +93,24 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err srcKind = reflect.Ptr } } + if !srcElement.IsValid() { continue } if srcKind == dstKind { - if err = deepMerge(dstElement, srcElement, visited, depth+1); err != nil { + if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil { return } - } else { - if srcKind == reflect.Map { - if err = deepMap(dstElement, srcElement, visited, depth+1); err != nil { - return - } - } else { - return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind) + } else if dstKind == reflect.Interface && dstElement.Kind() == reflect.Interface { + if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil { + return } + } else if srcKind == reflect.Map { + if err = deepMap(dstElement, srcElement, visited, depth+1, config); err != nil { + return + } + } else { + return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind) } } } @@ -117,18 +128,35 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err // doesn't apply if dst is a map. // This is separated method from Merge because it is cleaner and it keeps sane // semantics: merging equal types, mapping different (restricted) types. -func Map(dst, src interface{}) error { +func Map(dst, src interface{}, opts ...func(*config)) error { + return _map(dst, src, opts...) +} + +// MapWithOverwrite will do the same as Map except that non-empty dst attributes will be overriden by +// non-empty src attribute values. +// Deprecated: Use Map(…) with WithOverride +func MapWithOverwrite(dst, src interface{}, opts ...func(*config)) error { + return _map(dst, src, append(opts, WithOverride)...) +} + +func _map(dst, src interface{}, opts ...func(*config)) error { var ( vDst, vSrc reflect.Value err error ) + config := &config{} + + for _, opt := range opts { + opt(config) + } + if vDst, vSrc, err = resolveValues(dst, src); err != nil { return err } // To be friction-less, we redirect equal-type arguments // to deepMerge. Only because arguments can be anything. if vSrc.Kind() == vDst.Kind() { - return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0) + return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config) } switch vSrc.Kind() { case reflect.Struct: @@ -142,5 +170,5 @@ func Map(dst, src interface{}) error { default: return ErrNotSupported } - return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0) + return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, config) } diff --git a/github.com/imdario/mergo/merge.go b/github.com/imdario/mergo/merge.go index 5d328b1f..8ca10c91 100644 --- a/github.com/imdario/mergo/merge.go +++ b/github.com/imdario/mergo/merge.go @@ -8,14 +8,35 @@ package mergo -import ( - "reflect" -) +import "reflect" + +func hasExportedField(dst reflect.Value) (exported bool) { + for i, n := 0, dst.NumField(); i < n; i++ { + field := dst.Type().Field(i) + if field.Anonymous && dst.Field(i).Kind() == reflect.Struct { + exported = exported || hasExportedField(dst.Field(i)) + } else { + exported = exported || len(field.PkgPath) == 0 + } + } + return +} + +type config struct { + overwrite bool + transformers transformers +} + +type transformers interface { + Transformer(reflect.Type) func(dst, src reflect.Value) error +} // Traverses recursively both values, assigning src's fields values to dst. // The map argument tracks comparisons that have already been seen, which allows // short circuiting on recursive types. -func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err error) { +func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *config) (err error) { + overwrite := config.overwrite + if !src.IsValid() { return } @@ -32,68 +53,167 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (e // Remember, remember... visited[h] = &visit{addr, typ, seen} } + + if config.transformers != nil && !isEmptyValue(dst) { + if fn := config.transformers.Transformer(dst.Type()); fn != nil { + err = fn(dst, src) + return + } + } + switch dst.Kind() { case reflect.Struct: - for i, n := 0, dst.NumField(); i < n; i++ { - if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1); err != nil { - return + if hasExportedField(dst) { + for i, n := 0, dst.NumField(); i < n; i++ { + if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, config); err != nil { + return + } + } + } else { + if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) { + dst.Set(src) } } case reflect.Map: + if len(src.MapKeys()) == 0 && !src.IsNil() && len(dst.MapKeys()) == 0 { + dst.Set(reflect.MakeMap(dst.Type())) + return + } for _, key := range src.MapKeys() { srcElement := src.MapIndex(key) if !srcElement.IsValid() { continue } dstElement := dst.MapIndex(key) - switch reflect.TypeOf(srcElement.Interface()).Kind() { - case reflect.Struct: + switch srcElement.Kind() { + case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice: + if srcElement.IsNil() { + continue + } fallthrough - case reflect.Map: - if err = deepMerge(dstElement, srcElement, visited, depth+1); err != nil { - return + default: + if !srcElement.CanInterface() { + continue + } + switch reflect.TypeOf(srcElement.Interface()).Kind() { + case reflect.Struct: + fallthrough + case reflect.Ptr: + fallthrough + case reflect.Map: + if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil { + return + } + case reflect.Slice: + srcSlice := reflect.ValueOf(srcElement.Interface()) + + var dstSlice reflect.Value + if !dstElement.IsValid() || dstElement.IsNil() { + dstSlice = reflect.MakeSlice(srcSlice.Type(), 0, srcSlice.Len()) + } else { + dstSlice = reflect.ValueOf(dstElement.Interface()) + } + + dstSlice = reflect.AppendSlice(dstSlice, srcSlice) + dst.SetMapIndex(key, dstSlice) } } - if !dstElement.IsValid() { + if dstElement.IsValid() && reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map { + continue + } + + if !isEmptyValue(srcElement) && (overwrite || (!dstElement.IsValid() || isEmptyValue(dst))) { + if dst.IsNil() { + dst.Set(reflect.MakeMap(dst.Type())) + } dst.SetMapIndex(key, srcElement) } } + case reflect.Slice: + dst.Set(reflect.AppendSlice(dst, src)) case reflect.Ptr: fallthrough case reflect.Interface: if src.IsNil() { break - } else if dst.IsNil() { - if dst.CanSet() && isEmptyValue(dst) { + } + if src.Kind() != reflect.Interface { + if dst.IsNil() || overwrite { + if dst.CanSet() && (overwrite || isEmptyValue(dst)) { + dst.Set(src) + } + } else if src.Kind() == reflect.Ptr { + if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil { + return + } + } else if dst.Elem().Type() == src.Type() { + if err = deepMerge(dst.Elem(), src, visited, depth+1, config); err != nil { + return + } + } else { + return ErrDifferentArgumentsTypes + } + break + } + if dst.IsNil() || overwrite { + if dst.CanSet() && (overwrite || isEmptyValue(dst)) { dst.Set(src) } - } else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1); err != nil { + } else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil { return } default: - if dst.CanSet() && !isEmptyValue(src) { + if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) { dst.Set(src) } } return } -// Merge sets fields' values in dst from src if they have a zero -// value of their type. -// dst and src must be valid same-type structs and dst must be -// a pointer to struct. -// It won't merge unexported (private) fields and will do recursively -// any exported field. -func Merge(dst, src interface{}) error { +// Merge will fill any empty for value type attributes on the dst struct using corresponding +// src attributes if they themselves are not empty. dst and src must be valid same-type structs +// and dst must be a pointer to struct. +// It won't merge unexported (private) fields and will do recursively any exported field. +func Merge(dst, src interface{}, opts ...func(*config)) error { + return merge(dst, src, opts...) +} + +// MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overriden by +// non-empty src attribute values. +// Deprecated: use Merge(…) with WithOverride +func MergeWithOverwrite(dst, src interface{}, opts ...func(*config)) error { + return merge(dst, src, append(opts, WithOverride)...) +} + +// WithTransformers adds transformers to merge, allowing to customize the merging of some types. +func WithTransformers(transformers transformers) func(*config) { + return func(config *config) { + config.transformers = transformers + } +} + +// WithOverride will make merge override non-empty dst attributes with non-empty src attributes values. +func WithOverride(config *config) { + config.overwrite = true +} + +func merge(dst, src interface{}, opts ...func(*config)) error { var ( vDst, vSrc reflect.Value err error ) + + config := &config{} + + for _, opt := range opts { + opt(config) + } + if vDst, vSrc, err = resolveValues(dst, src); err != nil { return err } if vDst.Type() != vSrc.Type() { return ErrDifferentArgumentsTypes } - return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0) + return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config) } diff --git a/github.com/imdario/mergo/mergo.go b/github.com/imdario/mergo/mergo.go index f8a0991e..785618cd 100644 --- a/github.com/imdario/mergo/mergo.go +++ b/github.com/imdario/mergo/mergo.go @@ -32,7 +32,7 @@ type visit struct { next *visit } -// From src/pkg/encoding/json. +// From src/pkg/encoding/json/encode.go. func isEmptyValue(v reflect.Value) bool { switch v.Kind() { case reflect.Array, reflect.Map, reflect.Slice, reflect.String: @@ -45,8 +45,10 @@ func isEmptyValue(v reflect.Value) bool { return v.Uint() == 0 case reflect.Float32, reflect.Float64: return v.Float() == 0 - case reflect.Interface, reflect.Ptr: + case reflect.Interface, reflect.Ptr, reflect.Func: return v.IsNil() + case reflect.Invalid: + return true } return false } diff --git a/github.com/imdario/mergo/testdata/license.yml b/github.com/imdario/mergo/testdata/license.yml index 62fdb61e..2f1ad008 100644 --- a/github.com/imdario/mergo/testdata/license.yml +++ b/github.com/imdario/mergo/testdata/license.yml @@ -1,3 +1,4 @@ import: ../../../../fossene/db/schema/thing.yml fields: site: string + author: root diff --git a/github.com/istio/tools/protoc-gen-docs/htmlGenerator.go b/github.com/istio/tools/protoc-gen-docs/htmlGenerator.go index 29adcffc..131657c5 100644 --- a/github.com/istio/tools/protoc-gen-docs/htmlGenerator.go +++ b/github.com/istio/tools/protoc-gen-docs/htmlGenerator.go @@ -531,7 +531,18 @@ func (g *htmlGenerator) generateComment(loc locationDescriptor, name string) { for i := 0; i < len(lines); i++ { l := lines[i] if len(l) > pad { - lines[i] = l[pad:] + skip := 0 + ch := ' ' + for skip, ch = range l { + if !unicode.IsSpace(ch) { + break + } + + if skip == pad { + break + } + } + lines[i] = l[skip:] } } diff --git a/github.com/json-iterator/go/config.go b/github.com/json-iterator/go/config.go index b69cdbfc..bd66947d 100644 --- a/github.com/json-iterator/go/config.go +++ b/github.com/json-iterator/go/config.go @@ -2,11 +2,12 @@ package jsoniter import ( "encoding/json" + "github.com/modern-go/concurrent" "github.com/modern-go/reflect2" "io" + "reflect" "sync" "unsafe" - "github.com/modern-go/concurrent" ) // Config customize how the API should behave. @@ -39,6 +40,8 @@ type API interface { NewDecoder(reader io.Reader) *Decoder Valid(data []byte) bool RegisterExtension(extension Extension) + DecoderOf(typ reflect2.Type) ValDecoder + EncoderOf(typ reflect2.Type) ValEncoder } // ConfigDefault the default API @@ -60,7 +63,6 @@ var ConfigFastest = Config{ ObjectFieldMustBeSimpleString: true, // do not unescape object field }.Froze() - type frozenConfig struct { configBeforeFrozen Config sortMapKeys bool @@ -104,7 +106,7 @@ func (cfg *frozenConfig) getEncoderFromCache(cacheKey uintptr) ValEncoder { return nil } -var cfgCache = &sync.Map{} +var cfgCache = concurrent.NewMap() func getFrozenConfigFromCache(cfg Config) *frozenConfig { obj, found := cfgCache.Load(cfg) @@ -192,6 +194,11 @@ func (cfg *frozenConfig) validateJsonRawMessage(extension EncoderExtension) { func (cfg *frozenConfig) useNumber(extension DecoderExtension) { extension[reflect2.TypeOfPtr((*interface{})(nil)).Elem()] = &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) { + exitingValue := *((*interface{})(ptr)) + if exitingValue != nil && reflect.TypeOf(exitingValue).Kind() == reflect.Ptr { + iter.ReadVal(exitingValue) + return + } if iter.WhatIsNext() == NumberValue { *((*interface{})(ptr)) = json.Number(iter.readNumberAsString()) } else { diff --git a/github.com/json-iterator/go/reflect_map.go b/github.com/json-iterator/go/reflect_map.go index f34d519f..8812f085 100644 --- a/github.com/json-iterator/go/reflect_map.go +++ b/github.com/json-iterator/go/reflect_map.go @@ -3,6 +3,7 @@ package jsoniter import ( "fmt" "github.com/modern-go/reflect2" + "io" "reflect" "sort" "unsafe" @@ -107,6 +108,9 @@ func encoderOfMapKey(ctx *ctx, typ reflect2.Type) ValEncoder { stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")), } } + if typ.Kind() == reflect.Interface { + return &dynamicMapKeyEncoder{ctx, typ} + } return &lazyErrorEncoder{err: fmt.Errorf("unsupported map key type: %v", typ)} } } @@ -203,6 +207,21 @@ func (encoder *numericMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool { return false } +type dynamicMapKeyEncoder struct { + ctx *ctx + valType reflect2.Type +} + +func (encoder *dynamicMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + obj := encoder.valType.UnsafeIndirect(ptr) + encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).Encode(reflect2.PtrOf(obj), stream) +} + +func (encoder *dynamicMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool { + obj := encoder.valType.UnsafeIndirect(ptr) + return encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).IsEmpty(reflect2.PtrOf(obj)) +} + type mapEncoder struct { mapType *reflect2.UnsafeMapType keyEncoder ValEncoder @@ -253,6 +272,9 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { subStream.buf = make([]byte, 0, 64) key, elem := mapIter.UnsafeNext() encoder.keyEncoder.Encode(key, subStream) + if subStream.Error != nil && subStream.Error != io.EOF && stream.Error == nil { + stream.Error = subStream.Error + } encodedKey := subStream.Buffer() subIter.ResetBytes(encodedKey) decodedKey := subIter.ReadString() diff --git a/github.com/mailru/easyjson/jlexer/lexer.go b/github.com/mailru/easyjson/jlexer/lexer.go index e5558ae3..0fd9b122 100644 --- a/github.com/mailru/easyjson/jlexer/lexer.go +++ b/github.com/mailru/easyjson/jlexer/lexer.go @@ -997,6 +997,22 @@ func (r *Lexer) Float32() float32 { return float32(n) } +func (r *Lexer) Float32Str() float32 { + s, b := r.unsafeString() + if !r.Ok() { + return 0 + } + n, err := strconv.ParseFloat(s, 32) + if err != nil { + r.addNonfatalError(&LexerError{ + Offset: r.start, + Reason: err.Error(), + Data: string(b), + }) + } + return float32(n) +} + func (r *Lexer) Float64() float64 { s := r.number() if !r.Ok() { @@ -1014,6 +1030,22 @@ func (r *Lexer) Float64() float64 { return n } +func (r *Lexer) Float64Str() float64 { + s, b := r.unsafeString() + if !r.Ok() { + return 0 + } + n, err := strconv.ParseFloat(s, 64) + if err != nil { + r.addNonfatalError(&LexerError{ + Offset: r.start, + Reason: err.Error(), + Data: string(b), + }) + } + return n +} + func (r *Lexer) Error() error { return r.fatalError } @@ -1056,7 +1088,7 @@ func (r *Lexer) JsonNumber() json.Number { } if !r.Ok() { r.errInvalidToken("json.Number") - return json.Number("0") + return json.Number("") } switch r.token.kind { @@ -1064,9 +1096,12 @@ func (r *Lexer) JsonNumber() json.Number { return json.Number(r.String()) case tokenNumber: return json.Number(r.Raw()) + case tokenNull: + r.Null() + return json.Number("") default: r.errSyntax() - return json.Number("0") + return json.Number("") } } diff --git a/github.com/mailru/easyjson/jwriter/writer.go b/github.com/mailru/easyjson/jwriter/writer.go index e5a5ddfd..b9ed7cca 100644 --- a/github.com/mailru/easyjson/jwriter/writer.go +++ b/github.com/mailru/easyjson/jwriter/writer.go @@ -240,11 +240,25 @@ func (w *Writer) Float32(n float32) { w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 32) } +func (w *Writer) Float32Str(n float32) { + w.Buffer.EnsureSpace(20) + w.Buffer.Buf = append(w.Buffer.Buf, '"') + w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 32) + w.Buffer.Buf = append(w.Buffer.Buf, '"') +} + func (w *Writer) Float64(n float64) { w.Buffer.EnsureSpace(20) w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, n, 'g', -1, 64) } +func (w *Writer) Float64Str(n float64) { + w.Buffer.EnsureSpace(20) + w.Buffer.Buf = append(w.Buffer.Buf, '"') + w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 64) + w.Buffer.Buf = append(w.Buffer.Buf, '"') +} + func (w *Writer) Bool(v bool) { w.Buffer.EnsureSpace(5) if v { @@ -340,12 +354,11 @@ func (w *Writer) base64(in []byte) { return } - w.Buffer.EnsureSpace(((len(in) - 1) / 3 + 1) * 4) + w.Buffer.EnsureSpace(((len(in)-1)/3 + 1) * 4) si := 0 n := (len(in) / 3) * 3 - for si < n { // Convert 3x 8bit source bytes into 4 bytes val := uint(in[si+0])<<16 | uint(in[si+1])<<8 | uint(in[si+2]) diff --git a/github.com/modern-go/concurrent/unbounded_executor.go b/github.com/modern-go/concurrent/unbounded_executor.go index 31f52a9e..05a77dce 100644 --- a/github.com/modern-go/concurrent/unbounded_executor.go +++ b/github.com/modern-go/concurrent/unbounded_executor.go @@ -16,9 +16,6 @@ var HandlePanic = func(recovered interface{}, funcName string) { ErrorLogger.Println(string(debug.Stack())) } -// StopSignal will not be recovered, will propagate to upper level goroutine -const StopSignal = "STOP!" - // UnboundedExecutor is a executor without limits on counts of alive goroutines // it tracks the goroutine started by it, and can cancel them when shutdown type UnboundedExecutor struct { @@ -62,7 +59,9 @@ func (executor *UnboundedExecutor) Go(handler func(ctx context.Context)) { go func() { defer func() { recovered := recover() - if recovered != nil && recovered != StopSignal { + // if you want to quit a goroutine without trigger HandlePanic + // use runtime.Goexit() to quit + if recovered != nil { if executor.HandlePanic == nil { HandlePanic(recovered, funcName) } else { @@ -70,8 +69,8 @@ func (executor *UnboundedExecutor) Go(handler func(ctx context.Context)) { } } executor.activeGoroutinesMutex.Lock() - defer executor.activeGoroutinesMutex.Unlock() executor.activeGoroutines[startFrom] -= 1 + executor.activeGoroutinesMutex.Unlock() }() handler(executor.ctx) }() @@ -93,24 +92,24 @@ func (executor *UnboundedExecutor) StopAndWaitForever() { func (executor *UnboundedExecutor) StopAndWait(ctx context.Context) { executor.cancel() for { - fiveSeconds := time.NewTimer(time.Millisecond * 100) + oneHundredMilliseconds := time.NewTimer(time.Millisecond * 100) select { - case <-fiveSeconds.C: + case <-oneHundredMilliseconds.C: + if executor.checkNoActiveGoroutines() { + return + } case <-ctx.Done(): return } - if executor.checkGoroutines() { - return - } } } -func (executor *UnboundedExecutor) checkGoroutines() bool { +func (executor *UnboundedExecutor) checkNoActiveGoroutines() bool { executor.activeGoroutinesMutex.Lock() defer executor.activeGoroutinesMutex.Unlock() for startFrom, count := range executor.activeGoroutines { if count > 0 { - InfoLogger.Println("event!unbounded_executor.still waiting goroutines to quit", + InfoLogger.Println("UnboundedExecutor is still waiting goroutines to quit", "startFrom", startFrom, "count", count) return false diff --git a/github.com/open-policy-agent/opa/ast/builtins.go b/github.com/open-policy-agent/opa/ast/builtins.go index 577da6c8..f206e317 100644 --- a/github.com/open-policy-agent/opa/ast/builtins.go +++ b/github.com/open-policy-agent/opa/ast/builtins.go @@ -27,44 +27,104 @@ func RegisterBuiltin(b *Builtin) { // by default. When adding a new built-in function to OPA, update this // list. var DefaultBuiltins = [...]*Builtin{ - // = + + // Unification/equality ("=") Equality, + // Assignment (":=") + Assign, + // Comparisons - GreaterThan, GreaterThanEq, LessThan, LessThanEq, NotEqual, + GreaterThan, + GreaterThanEq, + LessThan, + LessThanEq, + NotEqual, + Equal, // Arithmetic - Plus, Minus, Multiply, Divide, Round, Abs, + Plus, + Minus, + Multiply, + Divide, + Round, + Abs, // Binary - And, Or, + And, + Or, // Aggregates - Count, Sum, Product, Max, Min, + Count, + Sum, + Product, + Max, + Min, // Casting ToNumber, // Regular Expressions RegexMatch, + GlobsMatch, // Sets SetDiff, + Intersection, + Union, // Strings - Concat, FormatInt, IndexOf, Substring, Lower, Upper, Contains, StartsWith, EndsWith, Split, Replace, Trim, Sprintf, + Concat, + FormatInt, + IndexOf, + Substring, + Lower, + Upper, + Contains, + StartsWith, + EndsWith, + Split, + Replace, + Trim, + Sprintf, // Encoding - JSONMarshal, JSONUnmarshal, Base64UrlEncode, Base64UrlDecode, YAMLMarshal, YAMLUnmarshal, + JSONMarshal, + JSONUnmarshal, + Base64UrlEncode, + Base64UrlDecode, + YAMLMarshal, + YAMLUnmarshal, // Tokens JWTDecode, // Time - NowNanos, ParseNanos, ParseRFC3339Nanos, ParseDurationNanos, + NowNanos, + ParseNanos, + ParseRFC3339Nanos, + ParseDurationNanos, + Date, + Clock, // Graphs WalkBuiltin, + + // Sort + Sort, + + // Types + IsNumber, + IsString, + IsBoolean, + IsArray, + IsSet, + IsObject, + IsNull, + TypeNameBuiltin, + + // HTTP + HTTPSend, } // BuiltinMap provides a convenient mapping of built-in names to @@ -81,7 +141,21 @@ var Equality = &Builtin{ Infix: "=", Decl: types.NewFunction( types.Args(types.A, types.A), - types.T, + types.B, + ), +} + +/** + * Assignment + */ + +// Assign represents the assignment (":=") operator. +var Assign = &Builtin{ + Name: "assign", + Infix: ":=", + Decl: types.NewFunction( + types.Args(types.A, types.A), + types.B, ), } @@ -95,7 +169,7 @@ var GreaterThan = &Builtin{ Infix: ">", Decl: types.NewFunction( types.Args(types.A, types.A), - types.T, + types.B, ), } @@ -105,7 +179,7 @@ var GreaterThanEq = &Builtin{ Infix: ">=", Decl: types.NewFunction( types.Args(types.A, types.A), - types.T, + types.B, ), } @@ -115,7 +189,7 @@ var LessThan = &Builtin{ Infix: "<", Decl: types.NewFunction( types.Args(types.A, types.A), - types.T, + types.B, ), } @@ -125,7 +199,7 @@ var LessThanEq = &Builtin{ Infix: "<=", Decl: types.NewFunction( types.Args(types.A, types.A), - types.T, + types.B, ), } @@ -135,7 +209,17 @@ var NotEqual = &Builtin{ Infix: "!=", Decl: types.NewFunction( types.Args(types.A, types.A), - types.T, + types.B, + ), +} + +// Equal represents the "==" comparison operator. +var Equal = &Builtin{ + Name: "equal", + Infix: "==", + Decl: types.NewFunction( + types.Args(types.A, types.A), + types.B, ), } @@ -348,7 +432,23 @@ var RegexMatch = &Builtin{ types.S, types.S, ), - types.T, + types.B, + ), +} + +// GlobsMatch takes two strings regexp-style strings and evaluates to true if their +// intersection matches a non-empty set of non-empty strings. +// Examples: +// - "a.a." and ".b.b" -> true. +// - "[a-z]*" and [0-9]+" -> not true. +var GlobsMatch = &Builtin{ + Name: "regex.globs_match", + Decl: types.NewFunction( + types.Args( + types.S, + types.S, + ), + types.B, ), } @@ -417,7 +517,7 @@ var Contains = &Builtin{ types.S, types.S, ), - types.T, + types.B, ), } @@ -429,7 +529,7 @@ var StartsWith = &Builtin{ types.S, types.S, ), - types.T, + types.B, ), } @@ -441,7 +541,7 @@ var EndsWith = &Builtin{ types.S, types.S, ), - types.T, + types.B, ), } @@ -633,6 +733,24 @@ var ParseDurationNanos = &Builtin{ ), } +// Date returns the [year, month, day] for the nanoseconds since epoch. +var Date = &Builtin{ + Name: "time.date", + Decl: types.NewFunction( + types.Args(types.N), + types.NewArray([]types.Type{types.N, types.N, types.N}, nil), + ), +} + +// Clock returns the [hour, minute, second] of the day for the nanoseconds since epoch. +var Clock = &Builtin{ + Name: "time.clock", + Decl: types.NewFunction( + types.Args(types.N), + types.NewArray([]types.Type{types.N, types.N, types.N}, nil), + ), +} + /** * Graphs. */ @@ -640,7 +758,8 @@ var ParseDurationNanos = &Builtin{ // WalkBuiltin generates [path, value] tuples for all nested documents // (recursively). var WalkBuiltin = &Builtin{ - Name: "walk", + Name: "walk", + Relation: true, Decl: types.NewFunction( types.Args(types.A), types.NewArray( @@ -653,6 +772,163 @@ var WalkBuiltin = &Builtin{ ), } +/** + * Sorting + */ + +// Sort returns a sorted array. +var Sort = &Builtin{ + Name: "sort", + Decl: types.NewFunction( + types.Args( + types.NewAny( + types.NewArray(nil, types.A), + types.NewSet(types.A), + ), + ), + types.NewArray(nil, types.A), + ), +} + +/** + * Type + */ + +// IsNumber returns true if the input value is a number +var IsNumber = &Builtin{ + Name: "is_number", + Decl: types.NewFunction( + types.Args( + types.A, + ), + types.B, + ), +} + +// IsString returns true if the input value is a string. +var IsString = &Builtin{ + Name: "is_string", + Decl: types.NewFunction( + types.Args( + types.A, + ), + types.B, + ), +} + +// IsBoolean returns true if the input value is a boolean. +var IsBoolean = &Builtin{ + Name: "is_boolean", + Decl: types.NewFunction( + types.Args( + types.A, + ), + types.B, + ), +} + +// IsArray returns true if the input value is an array. +var IsArray = &Builtin{ + Name: "is_array", + Decl: types.NewFunction( + types.Args( + types.A, + ), + types.B, + ), +} + +// IsSet returns true if the input value is a set. +var IsSet = &Builtin{ + Name: "is_set", + Decl: types.NewFunction( + types.Args( + types.A, + ), + types.B, + ), +} + +// IsObject returns true if the input value is an object. +var IsObject = &Builtin{ + Name: "is_object", + Decl: types.NewFunction( + types.Args( + types.A, + ), + types.B, + ), +} + +// IsNull returns true if the input value is null. +var IsNull = &Builtin{ + Name: "is_null", + Decl: types.NewFunction( + types.Args( + types.A, + ), + types.B, + ), +} + +/** + * Type Name + */ + +// TypeNameBuiltin returns the type of the input. +var TypeNameBuiltin = &Builtin{ + Name: "type_name", + Decl: types.NewFunction( + types.Args( + types.NewAny( + types.A, + ), + ), + types.S, + ), +} + +/** + * HTTP Request + */ + +// HTTPSend returns a HTTP response to the given HTTP request. +var HTTPSend = &Builtin{ + Name: "http.send", + Decl: types.NewFunction( + types.Args( + types.NewObject(nil, types.NewDynamicProperty(types.S, types.A)), + ), + types.NewObject(nil, types.NewDynamicProperty(types.A, types.A)), + ), +} + +/** + * Set + */ + +// Intersection returns the intersection of the given input sets +var Intersection = &Builtin{ + Name: "intersection", + Decl: types.NewFunction( + types.Args( + types.NewSet(types.NewSet(types.A)), + ), + types.NewSet(types.A), + ), +} + +// Union returns the union of the given input sets +var Union = &Builtin{ + Name: "union", + Decl: types.NewFunction( + types.Args( + types.NewSet(types.NewSet(types.A)), + ), + types.NewSet(types.A), + ), +} + /** * Deprecated built-ins. */ @@ -672,23 +948,34 @@ var SetDiff = &Builtin{ // Builtin represents a built-in function supported by OPA. Every built-in // function is uniquely identified by a name. type Builtin struct { - Name string // Unique name of built-in function, e.g., (arg1,arg2,...,argN) - Infix string // Unique name of infix operator. Default should be unset. - Decl *types.Function // Built-in function type declaration. + Name string // Unique name of built-in function, e.g., (arg1,arg2,...,argN) + Infix string // Unique name of infix operator. Default should be unset. + Decl *types.Function // Built-in function type declaration. + Relation bool // Indicates if the built-in acts as a relation. } -// Expr creates a new expression for the built-in with the given terms. -func (b *Builtin) Expr(terms ...*Term) *Expr { - ts := make([]*Term, len(terms)+1) +// Expr creates a new expression for the built-in with the given operands. +func (b *Builtin) Expr(operands ...*Term) *Expr { + ts := make([]*Term, len(operands)+1) ts[0] = NewTerm(b.Ref()) - for i := range terms { - ts[i+1] = terms[i] + for i := range operands { + ts[i+1] = operands[i] } return &Expr{ Terms: ts, } } +// Call creates a new term for the built-in with the given operands. +func (b *Builtin) Call(operands ...*Term) *Term { + call := make(Call, len(operands)+1) + call[0] = NewTerm(b.Ref()) + for i := range operands { + call[i+1] = operands[i] + } + return NewTerm(call) +} + // Ref returns a Ref that refers to the built-in function. func (b *Builtin) Ref() Ref { parts := strings.Split(b.Name, ".") diff --git a/github.com/open-policy-agent/opa/ast/check.go b/github.com/open-policy-agent/opa/ast/check.go index 3436522c..b41be37e 100644 --- a/github.com/open-policy-agent/opa/ast/check.go +++ b/github.com/open-policy-agent/opa/ast/check.go @@ -243,7 +243,7 @@ func (tc *typeChecker) checkExprBuiltin(env *TypeEnv, expr *Expr) *Error { } for i := range args { - if !unify1(env, args[i], expArgs[i]) { + if !unify1(env, args[i], expArgs[i], false) { post := make([]types.Type, len(args)) for i := range args { post[i] = env.Get(args[i]) @@ -278,68 +278,85 @@ func unify2(env *TypeEnv, a *Term, typeA types.Type, b *Term, typeB types.Type) nilB := types.Nil(typeB) if nilA && !nilB { - return unify1(env, a, typeB) + return unify1(env, a, typeB, false) } else if nilB && !nilA { - return unify1(env, b, typeA) + return unify1(env, b, typeA, false) } else if !nilA && !nilB { return unifies(typeA, typeB) } - switch av := a.Value.(type) { + switch a.Value.(type) { case Array: - switch bv := b.Value.(type) { + return unify2Array(env, a, typeA, b, typeB) + case Object: + return unify2Object(env, a, typeA, b, typeB) + case Var: + switch b.Value.(type) { + case Var: + return unify1(env, a, types.A, false) && unify1(env, b, env.Get(a), false) case Array: - if len(av) == len(bv) { - for i := range av { - if !unify2(env, av[i], env.Get(av[i]), bv[i], env.Get(bv[i])) { - return false - } + return unify2Array(env, b, typeB, a, typeA) + case Object: + return unify2Object(env, b, typeB, a, typeA) + } + } + + return false +} + +func unify2Array(env *TypeEnv, a *Term, typeA types.Type, b *Term, typeB types.Type) bool { + arr := a.Value.(Array) + switch bv := b.Value.(type) { + case Array: + if len(arr) == len(bv) { + for i := range arr { + if !unify2(env, arr[i], env.Get(arr[i]), bv[i], env.Get(bv[i])) { + return false } - return true } - case Var: - return unify1(env, a, types.A) && unify1(env, b, env.Get(a)) + return true } + case Var: + return unify1(env, a, types.A, false) && unify1(env, b, env.Get(a), false) + } + return false +} + +func unify2Object(env *TypeEnv, a *Term, typeA types.Type, b *Term, typeB types.Type) bool { + obj := a.Value.(Object) + switch bv := b.Value.(type) { case Object: - switch bv := b.Value.(type) { - case Object: - cv := av.Intersect(bv) - if len(av) == len(bv) && len(bv) == len(cv) { - for i := range cv { - if !unify2(env, cv[i][1], env.Get(cv[i][1]), cv[i][2], env.Get(cv[i][2])) { - return false - } + cv := obj.Intersect(bv) + if obj.Len() == bv.Len() && bv.Len() == len(cv) { + for i := range cv { + if !unify2(env, cv[i][1], env.Get(cv[i][1]), cv[i][2], env.Get(cv[i][2])) { + return false } - return true } - case Var: - return unify1(env, a, types.A) && unify1(env, b, env.Get(a)) + return true } case Var: - if _, ok := b.Value.(Var); ok { - return unify1(env, a, types.A) && unify1(env, b, env.Get(a)) - } + return unify1(env, a, types.A, false) && unify1(env, b, env.Get(a), false) } - return false } -func unify1(env *TypeEnv, term *Term, tpe types.Type) bool { +func unify1(env *TypeEnv, term *Term, tpe types.Type, union bool) bool { switch v := term.Value.(type) { case Array: switch tpe := tpe.(type) { case *types.Array: - return unify1Array(env, v, tpe) + return unify1Array(env, v, tpe, union) case types.Any: if types.Compare(tpe, types.A) == 0 { for i := range v { - unify1(env, v[i], types.A) + unify1(env, v[i], types.A, true) } return true } unifies := false for i := range tpe { - unifies = unify1(env, term, tpe[i]) || unifies + unifies = unify1(env, term, tpe[i], true) || unifies } return unifies } @@ -347,36 +364,35 @@ func unify1(env *TypeEnv, term *Term, tpe types.Type) bool { case Object: switch tpe := tpe.(type) { case *types.Object: - return unify1Object(env, v, tpe) + return unify1Object(env, v, tpe, union) case types.Any: if types.Compare(tpe, types.A) == 0 { - for i := range v { - unify1(env, v[i][1], types.A) - } + v.Foreach(func(_, value *Term) { + unify1(env, value, types.A, true) + }) return true } unifies := false for i := range tpe { - unifies = unify1(env, term, tpe[i]) || unifies + unifies = unify1(env, term, tpe[i], true) || unifies } return unifies } return false - case *Set: + case Set: switch tpe := tpe.(type) { case *types.Set: - return unify1Set(env, v, tpe) + return unify1Set(env, v, tpe, union) case types.Any: if types.Compare(tpe, types.A) == 0 { - v.Iter(func(elem *Term) bool { - unify1(env, elem, types.A) - return true + v.Foreach(func(elem *Term) { + unify1(env, elem, types.A, true) }) return true } unifies := false for i := range tpe { - unifies = unify1(env, term, tpe[i]) || unifies + unifies = unify1(env, term, tpe[i], true) || unifies } return unifies } @@ -384,10 +400,14 @@ func unify1(env *TypeEnv, term *Term, tpe types.Type) bool { case Ref, *ArrayComprehension, *ObjectComprehension, *SetComprehension: return unifies(env.Get(v), tpe) case Var: - if exist := env.Get(v); exist != nil { - return unifies(exist, tpe) + if !union { + if exist := env.Get(v); exist != nil { + return unifies(exist, tpe) + } + env.tree.PutOne(term.Value, tpe) + } else { + env.tree.PutOne(term.Value, types.Or(env.Get(v), tpe)) } - env.tree.PutOne(term.Value, tpe) return true default: if !IsConstant(v) { @@ -397,46 +417,47 @@ func unify1(env *TypeEnv, term *Term, tpe types.Type) bool { } } -func unify1Array(env *TypeEnv, val Array, tpe *types.Array) bool { +func unify1Array(env *TypeEnv, val Array, tpe *types.Array, union bool) bool { if len(val) != tpe.Len() && tpe.Dynamic() == nil { return false } for i := range val { - if !unify1(env, val[i], tpe.Select(i)) { + if !unify1(env, val[i], tpe.Select(i), union) { return false } } return true } -func unify1Object(env *TypeEnv, val Object, tpe *types.Object) bool { - if len(val) != len(tpe.Keys()) && tpe.DynamicValue() == nil { +func unify1Object(env *TypeEnv, val Object, tpe *types.Object, union bool) bool { + if val.Len() != len(tpe.Keys()) && tpe.DynamicValue() == nil { return false } - for i := range val { - if IsConstant(val[i][0].Value) { - if child := selectConstant(tpe, val[i][0]); child != nil { - if !unify1(env, val[i][1], child) { - return false + stop := val.Until(func(k, v *Term) bool { + if IsConstant(k.Value) { + if child := selectConstant(tpe, k); child != nil { + if !unify1(env, v, child, union) { + return true } } else { - return false + return true } } else { // Inferring type of value under dynamic key would involve unioning // with all property values of tpe whose keys unify. For now, type // these values as Any. We can investigate stricter inference in // the future. - unify1(env, val[i][1], types.A) + unify1(env, v, types.A, union) } - } - return true + return false + }) + return !stop } -func unify1Set(env *TypeEnv, val *Set, tpe *types.Set) bool { +func unify1Set(env *TypeEnv, val Set, tpe *types.Set, union bool) bool { of := types.Values(tpe) - return !val.Iter(func(elem *Term) bool { - return !unify1(env, elem, of) + return !val.Until(func(elem *Term) bool { + return !unify1(env, elem, of, union) }) } @@ -604,12 +625,12 @@ func (rc *refChecker) checkRefLeaf(tpe types.Type, ref Ref, idx int) *Error { } } - case Array, Object, *Set: + case Array, Object, Set: // Composite references operands may only be used with a set. if !unifies(tpe, types.NewSet(types.A)) { return newRefErrInvalid(ref[0].Location, ref, idx, tpe, types.NewSet(types.A), nil) } - if !unify1(rc.env, head, keys) { + if !unify1(rc.env, head, keys, false) { return newRefErrInvalid(ref[0].Location, ref, idx, rc.env.Get(head), keys, nil) } diff --git a/github.com/open-policy-agent/opa/ast/compare.go b/github.com/open-policy-agent/opa/ast/compare.go index 28c8afc3..bd905439 100644 --- a/github.com/open-policy-agent/opa/ast/compare.go +++ b/github.com/open-policy-agent/opa/ast/compare.go @@ -7,7 +7,6 @@ package ast import ( "encoding/json" "fmt" - "sort" "github.com/open-policy-agent/opa/util" ) @@ -111,41 +110,10 @@ func Compare(a, b interface{}) int { return termSliceCompare(a, b) case Object: b := b.(Object) - keysA := a.Keys() - keysB := b.Keys() - sort.Sort(termSlice(keysA)) - sort.Sort(termSlice(keysB)) - minLen := len(a) - if len(b) < len(a) { - minLen = len(b) - } - for i := 0; i < minLen; i++ { - keysCmp := Compare(keysA[i], keysB[i]) - if keysCmp < 0 { - return -1 - } - if keysCmp > 0 { - return 1 - } - valA := a.Get(keysA[i]) - valB := b.Get(keysB[i]) - valCmp := Compare(valA, valB) - if valCmp != 0 { - return valCmp - } - } - if len(a) < len(b) { - return -1 - } - if len(b) < len(a) { - return 1 - } - return 0 - case *Set: - b := b.(*Set) - sort.Sort(termSlice(*a)) - sort.Sort(termSlice(*b)) - return termSliceCompare(*a, *b) + return a.Compare(b) + case Set: + b := b.(Set) + return a.Compare(b) case *ArrayComprehension: b := b.(*ArrayComprehension) if cmp := Compare(a.Term, b.Term); cmp != 0 { @@ -167,6 +135,9 @@ func Compare(a, b interface{}) int { return cmp } return Compare(a.Body, b.Body) + case Call: + b := b.(Call) + return termSliceCompare(a, b) case *Expr: b := b.(*Expr) return a.Compare(b) @@ -222,7 +193,7 @@ func sortOrder(x interface{}) int { return 6 case Object: return 7 - case *Set: + case Set: return 8 case *ArrayComprehension: return 9 @@ -230,8 +201,10 @@ func sortOrder(x interface{}) int { return 10 case *SetComprehension: return 11 - case Args: + case Call: return 12 + case Args: + return 13 case *Expr: return 100 case *With: diff --git a/github.com/open-policy-agent/opa/ast/compile.go b/github.com/open-policy-agent/opa/ast/compile.go index 6ede6722..4ce152ce 100644 --- a/github.com/open-policy-agent/opa/ast/compile.go +++ b/github.com/open-policy-agent/opa/ast/compile.go @@ -75,11 +75,10 @@ type Compiler struct { // TypeEnv holds type information for values inferred by the compiler. TypeEnv *TypeEnv - generatedVars map[*Module]VarSet - moduleLoader ModuleLoader - ruleIndices *util.HashMap - stages []func() - maxErrs int + moduleLoader ModuleLoader + ruleIndices *util.HashMap + stages []func() + maxErrs int } // QueryContext contains contextual information for running an ad-hoc query. @@ -159,15 +158,26 @@ type QueryCompiler interface { // WithContext sets the QueryContext on the QueryCompiler. Subsequent calls // to Compile will take the QueryContext into account. WithContext(qctx *QueryContext) QueryCompiler + + // WithStageAfter registers a stage to run during query compilation after + // the named stage. + WithStageAfter(after string, stage QueryCompilerStage) QueryCompiler + + // RewrittenVars maps generated vars in the compiled query to vars from the + // parsed query. For example, given the query "input := 1" the rewritten + // query would be "__local0__ = 1". The mapping would then be {__local0__: input}. + RewrittenVars() map[Var]Var } +// QueryCompilerStage defines the interface for stages in the query compiler. +type QueryCompilerStage func(QueryCompiler, Body) (Body, error) + // NewCompiler returns a new empty compiler. func NewCompiler() *Compiler { c := &Compiler{ - Modules: map[string]*Module{}, - TypeEnv: NewTypeEnv(), - generatedVars: map[*Module]VarSet{}, + Modules: map[string]*Module{}, + TypeEnv: NewTypeEnv(), ruleIndices: util.NewHashMap(func(a, b util.T) bool { r1, r2 := a.(Ref), b.(Ref) return r1.Equal(r2) @@ -184,7 +194,14 @@ func NewCompiler() *Compiler { c.TypeEnv = checker.checkLanguageBuiltins() c.stages = []func(){ + + // Reference resolution should run first as it may be used to lazily + // load additional modules. If any stages run before resolution, they + // need to be re-run after resolution. c.resolveAllRefs, + + c.rewriteLocalAssignments, + c.rewriteExprTerms, c.setModuleTree, c.setRuleTree, c.setGraph, @@ -232,6 +249,20 @@ func (c *Compiler) Failed() bool { return len(c.Errors) > 0 } +// GetArity returns the number of args a function referred to by ref takes. If +// ref refers to built-in function, the built-in declaration is consulted, +// otherwise, the ref is used to perform a ruleset lookup. +func (c *Compiler) GetArity(ref Ref) int { + if bi := BuiltinMap[ref.String()]; bi != nil { + return len(bi.Decl.Args()) + } + rules := c.GetRulesExact(ref) + if len(rules) == 0 { + return -1 + } + return len(rules[0].Head.Args) +} + // GetRulesExact returns a slice of rules referred to by the reference. // // E.g., given the following module: @@ -429,21 +460,22 @@ func (c *Compiler) checkRecursion() { c.RuleTree.DepthFirst(func(node *TreeNode) bool { for _, rule := range node.Values { - r := rule.(*Rule) - c.checkSelfPath(RuleTypeName, r.Loc(), eq, r, r) + for node := rule.(*Rule); node != nil; node = node.Else { + c.checkSelfPath(node.Loc(), eq, node, node) + } } return false }) } -func (c *Compiler) checkSelfPath(t string, loc *Location, eq func(a, b util.T) bool, a, b util.T) { +func (c *Compiler) checkSelfPath(loc *Location, eq func(a, b util.T) bool, a, b util.T) { tr := newgraphTraversal(c.Graph) if p := util.DFSPath(tr, eq, a, b); len(p) > 0 { n := []string{} for _, x := range p { n = append(n, astNodeToString(x)) } - c.err(NewError(RecursionErr, loc, "%v %v is recursive: %v", t, astNodeToString(a), strings.Join(n, " -> "))) + c.err(NewError(RecursionErr, loc, "rule %v is recursive: %v", astNodeToString(a), strings.Join(n, " -> "))) } } @@ -519,11 +551,11 @@ func (c *Compiler) checkSafetyRuleBodies() { } func (c *Compiler) checkBodySafety(safe VarSet, m *Module, b Body, l *Location) Body { - reordered, unsafe := reorderBodyForSafety(safe, b) + reordered, unsafe := reorderBodyForSafety(c.GetArity, safe, b) if len(unsafe) != 0 { for v := range unsafe.Vars() { - if !c.generatedVars[m].Contains(v) { - c.err(NewError(UnsafeVarErr, l, "%v %v is unsafe", VarTypeName, v)) + if !v.IsGenerated() { + c.err(NewError(UnsafeVarErr, l, "var %v is unsafe", v)) } } return b @@ -545,8 +577,8 @@ func (c *Compiler) checkSafetyRuleHeads() { safe.Update(r.Head.Args.Vars()) unsafe := r.Head.Vars().Diff(safe) for v := range unsafe { - if !c.generatedVars[m].Contains(v) { - c.err(NewError(UnsafeVarErr, r.Loc(), "%v %v is unsafe", VarTypeName, v)) + if !v.IsGenerated() { + c.err(NewError(UnsafeVarErr, r.Loc(), "var %v is unsafe", v)) } } return false @@ -649,7 +681,10 @@ func (c *Compiler) resolveAllRefs() { globals := getGlobals(mod.Package, ruleExports, mod.Imports) WalkRules(mod, func(rule *Rule) bool { - resolveRefsInRule(globals, rule) + err := resolveRefsInRule(globals, rule) + if err != nil { + c.err(NewError(CompileErr, rule.Location, err.Error())) + } return false }) @@ -681,11 +716,18 @@ func (c *Compiler) rewriteComprehensionTerms() { for _, mod := range c.Modules { f := newEqualityFactory(newLocalVarGenerator(mod)) rewriteComprehensionTerms(f, mod) - if vs, ok := c.generatedVars[mod]; !ok { - c.generatedVars[mod] = f.gen.Generated() - } else { - vs.Update(f.gen.Generated()) - } + } +} + +func (c *Compiler) rewriteExprTerms() { + for k := range c.Modules { + mod := c.Modules[k] + gen := newLocalVarGenerator(mod) + WalkRules(mod, func(rule *Rule) bool { + rewriteExprTermsInHead(gen, rule) + rule.Body = rewriteExprTermsInBody(gen, rule.Body) + return false + }) } } @@ -725,11 +767,6 @@ func (c *Compiler) rewriteRefsInHead() { } return false }) - if vs, ok := c.generatedVars[mod]; !ok { - c.generatedVars[mod] = f.gen.Generated() - } else { - vs.Update(f.gen.Generated()) - } } } @@ -740,11 +777,84 @@ func (c *Compiler) rewriteDynamicTerms() { rule.Body = rewriteDynamics(f, rule.Body) return false }) - if vs, ok := c.generatedVars[mod]; !ok { - c.generatedVars[mod] = f.gen.Generated() - } else { - vs.Update(f.gen.Generated()) - } + } +} + +func (c *Compiler) rewriteLocalAssignments() { + + for _, mod := range c.Modules { + gen := newLocalVarGenerator(mod) + + WalkRules(mod, func(rule *Rule) bool { + + var errs Errors + + // Rewrite assignments contained in head of rule. Assignments can + // occur in rule head if they're inside a comprehension. Note, + // assigned vars in comprehensions in the head will be rewritten + // first to preserve scoping rules. For example: + // + // p = [x | x := 1] { x := 2 } becomes p = [__local0__ | __local0__ = 1] { __local1__ = 2 } + // + // This behaviour is consistent scoping inside the body. For example: + // + // p = xs { x := 2; xs = [x | x := 1] } becomes p = xs { __local0__ = 2; xs = [__local1__ | __local1__ = 1] } + WalkTerms(rule.Head, func(term *Term) bool { + switch v := term.Value.(type) { + case *ArrayComprehension: + stack := newLocalDeclaredVars() + errs = rewriteDeclaredVarsInArrayComprehension(gen, stack, v, errs) + return true + case *SetComprehension: + stack := newLocalDeclaredVars() + errs = rewriteDeclaredVarsInSetComprehension(gen, stack, v, errs) + return true + case *ObjectComprehension: + stack := newLocalDeclaredVars() + errs = rewriteDeclaredVarsInObjectComprehension(gen, stack, v, errs) + return true + } + return false + }) + + for _, err := range errs { + c.err(err) + } + + // Rewrite assignments in body. + body, declared, errs := rewriteLocalAssignments(gen, rule.Body) + for _, err := range errs { + c.err(err) + } + + rule.Body = body + + // Rewrite vars in head that refer to locally declared vars in the body. + vis := NewGenericVisitor(func(x interface{}) bool { + switch x := x.(type) { + case *Term: + if v, ok := x.Value.(Var); ok { + if gv, ok := declared[v]; ok { + x.Value = gv + return true + } + } + } + return false + }) + + Walk(vis, rule.Head.Args) + + if rule.Head.Key != nil { + Walk(vis, rule.Head.Key) + } + + if rule.Head.Value != nil { + Walk(vis, rule.Head.Value) + } + + return false + }) } } @@ -761,15 +871,18 @@ func (c *Compiler) setGraph() { } type queryCompiler struct { - compiler *Compiler - qctx *QueryContext - typeEnv *TypeEnv + compiler *Compiler + qctx *QueryContext + typeEnv *TypeEnv + rewritten map[Var]Var + after map[string][]QueryCompilerStage } func newQueryCompiler(compiler *Compiler) QueryCompiler { qc := &queryCompiler{ compiler: compiler, qctx: nil, + after: map[string][]QueryCompilerStage{}, } return qc } @@ -779,28 +892,45 @@ func (qc *queryCompiler) WithContext(qctx *QueryContext) QueryCompiler { return qc } +func (qc *queryCompiler) WithStageAfter(after string, stage QueryCompilerStage) QueryCompiler { + qc.after[after] = append(qc.after[after], stage) + return qc +} + +func (qc *queryCompiler) RewrittenVars() map[Var]Var { + return qc.rewritten +} + func (qc *queryCompiler) Compile(query Body) (Body, error) { - stages := []func(*QueryContext, Body) (Body, error){ - qc.resolveRefs, - qc.rewriteComprehensionTerms, - qc.rewriteDynamicTerms, - qc.checkWithModifiers, - qc.checkSafety, - qc.checkTypes, + query = query.Copy() + + stages := []struct { + name string + f func(*QueryContext, Body) (Body, error) + }{ + {"ResolveRefs", qc.resolveRefs}, + {"RewriteAssignments", qc.rewriteLocalAssignments}, + {"RewriteExprTerms", qc.rewriteExprTerms}, + {"RewriteComprehensionTerms", qc.rewriteComprehensionTerms}, + {"RewriteDynamicTerms", qc.rewriteDynamicTerms}, + {"CheckWithModifiers", qc.checkWithModifiers}, + {"CheckSafety", qc.checkSafety}, + {"CheckTypes", qc.checkTypes}, } qctx := qc.qctx.Copy() for _, s := range stages { var err error - if query, err = s(qctx, query); err != nil { - if errs, ok := err.(Errors); ok { - if qc.compiler.maxErrs > 0 && len(errs) > qc.compiler.maxErrs { - err = append(errs[:qc.compiler.maxErrs], errLimitReached) - } + if query, err = s.f(qctx, query); err != nil { + return nil, qc.applyErrorLimit(err) + } + for _, s := range qc.after[s.name] { + var err error + if query, err = s(qc, query); err != nil { + return nil, qc.applyErrorLimit(err) } - return nil, err } } @@ -811,6 +941,15 @@ func (qc *queryCompiler) TypeEnv() *TypeEnv { return qc.typeEnv } +func (qc *queryCompiler) applyErrorLimit(err error) error { + if errs, ok := err.(Errors); ok { + if qc.compiler.maxErrs > 0 && len(errs) > qc.compiler.maxErrs { + err = append(errs[:qc.compiler.maxErrs], errLimitReached) + } + } + return err +} + func (qc *queryCompiler) resolveRefs(qctx *QueryContext, body Body) (Body, error) { var globals map[Var]Ref @@ -826,7 +965,9 @@ func (qc *queryCompiler) resolveRefs(qctx *QueryContext, body Body) (Body, error qctx.Imports = nil } - return resolveRefsInBody(globals, body), nil + ignore := &assignedVarStack{assignedVars(body)} + + return resolveRefsInBody(globals, ignore, body), nil } func (qc *queryCompiler) rewriteComprehensionTerms(_ *QueryContext, body Body) (Body, error) { @@ -845,15 +986,35 @@ func (qc *queryCompiler) rewriteDynamicTerms(_ *QueryContext, body Body) (Body, return rewriteDynamics(f, body), nil } +func (qc *queryCompiler) rewriteExprTerms(_ *QueryContext, body Body) (Body, error) { + gen := newLocalVarGenerator(body) + return rewriteExprTermsInBody(gen, body), nil +} + +func (qc *queryCompiler) rewriteLocalAssignments(_ *QueryContext, body Body) (Body, error) { + gen := newLocalVarGenerator(body) + body, declared, err := rewriteLocalAssignments(gen, body) + if len(err) != 0 { + return nil, err + } + qc.rewritten = make(map[Var]Var, len(declared)) + for k, v := range declared { + qc.rewritten[v] = k + } + return body, nil +} + func (qc *queryCompiler) checkSafety(_ *QueryContext, body Body) (Body, error) { safe := ReservedVars.Copy() - reordered, unsafe := reorderBodyForSafety(safe, body) + reordered, unsafe := reorderBodyForSafety(qc.compiler.GetArity, safe, body) if len(unsafe) != 0 { var err Errors for v := range unsafe.Vars() { - err = append(err, NewError(UnsafeVarErr, body.Loc(), "%v %v is unsafe", VarTypeName, v)) + if !v.IsGenerated() { + err = append(err, NewError(UnsafeVarErr, body.Loc(), "var %v is unsafe", v)) + } } return nil, err } @@ -1063,7 +1224,7 @@ func (wc *withModifierChecker) checkValue(w *With) { } WalkRefs(w.Value, func(r Ref) bool { - wc.err(TypeErr, w.Location, "with keyword value must not contain %vs", RefTypeName) + wc.err(TypeErr, w.Location, "with keyword value must not contain refs") return true }) } @@ -1092,19 +1253,35 @@ func NewGraph(modules map[string]*Module, list func(Ref) []*Rule) *Graph { sorted: nil, } - // Walk over all rules, add them to graph, and build adjencency lists. - for _, module := range modules { - addRefDeps := func(a util.T) func(ref Ref) bool { - return func(ref Ref) bool { - for _, b := range list(ref.GroundPrefix()) { - graph.addDependency(a, b) + // Create visitor to walk a rule AST and add edges to the rule graph for + // each dependency. + vis := func(a *Rule) Visitor { + stop := false + return NewGenericVisitor(func(x interface{}) bool { + switch x := x.(type) { + case Ref: + for _, b := range list(x.GroundPrefix()) { + for node := b; node != nil; node = node.Else { + graph.addDependency(a, node) + } } - return false + case *Rule: + if stop { + // Do not recurse into else clauses (which will be handled + // by the outer visitor.) + return true + } + stop = true } - } + return false + }) + } + + // Walk over all rules, add them to graph, and build adjencency lists. + for _, module := range modules { WalkRules(module, func(a *Rule) bool { graph.addNode(a) - WalkRefs(a, addRefDeps(a)) + Walk(vis(a), a) return false }) } @@ -1262,9 +1439,9 @@ func (vs unsafeVars) Vars() VarSet { // // If the body cannot be reordered to ensure safety, the second return value // contains a mapping of expressions to unsafe variables in those expressions. -func reorderBodyForSafety(globals VarSet, body Body) (Body, unsafeVars) { +func reorderBodyForSafety(arity func(Ref) int, globals VarSet, body Body) (Body, unsafeVars) { - body, unsafe := reorderBodyForClosures(globals, body) + body, unsafe := reorderBodyForClosures(arity, globals, body) if len(unsafe) != 0 { return nil, unsafe } @@ -1290,7 +1467,7 @@ func reorderBodyForSafety(globals VarSet, body Body) (Body, unsafeVars) { continue } - safe.Update(e.OutputVars(safe)) + safe.Update(outputVarsForExpr(e, arity, safe)) for v := range unsafe[e] { if safe.Contains(v) { @@ -1318,6 +1495,7 @@ func reorderBodyForSafety(globals VarSet, body Body) (Body, unsafeVars) { g.Update(reordered[i-1].Vars(safetyCheckVarVisitorParams)) } vis := &bodySafetyVisitor{ + arity: arity, current: e, globals: g, unsafe: unsafe, @@ -1333,6 +1511,7 @@ func reorderBodyForSafety(globals VarSet, body Body) (Body, unsafeVars) { } type bodySafetyVisitor struct { + arity func(Ref) int current *Expr globals VarSet unsafe unsafeVars @@ -1367,7 +1546,7 @@ func (vis *bodySafetyVisitor) checkComprehensionSafety(tv VarSet, body Body) Bod } // Check body for safety, reordering as necessary. - r, u := reorderBodyForSafety(vis.globals, body) + r, u := reorderBodyForSafety(vis.arity, vis.globals, body) if len(u) == 0 { return r } @@ -1393,7 +1572,7 @@ func (vis *bodySafetyVisitor) checkSetComprehensionSafety(sc *SetComprehension) // reorderBodyForClosures returns a copy of the body ordered such that // expressions (such as array comprehensions) that close over variables are ordered // after other expressions that contain the same variable in an output position. -func reorderBodyForClosures(globals VarSet, body Body) (Body, unsafeVars) { +func reorderBodyForClosures(arity func(Ref) int, globals VarSet, body Body) (Body, unsafeVars) { reordered := Body{} unsafe := unsafeVars{} @@ -1419,7 +1598,7 @@ func reorderBodyForClosures(globals VarSet, body Body) (Body, unsafeVars) { // contained in the output position of an expression in the reordered // body. These vars are considered unsafe. cv := vs.Intersect(body.Vars(safetyCheckVarVisitorParams)).Diff(globals) - uv := cv.Diff(reordered.OutputVars(globals)) + uv := cv.Diff(outputVarsForBody(reordered, arity, globals)) if len(uv) == 0 { reordered = append(reordered, e) @@ -1437,6 +1616,159 @@ func reorderBodyForClosures(globals VarSet, body Body) (Body, unsafeVars) { return reordered, unsafe } +func outputVarsForBody(body Body, arity func(Ref) int, safe VarSet) VarSet { + o := safe.Copy() + for _, e := range body { + o.Update(outputVarsForExpr(e, arity, o)) + } + return o.Diff(safe) +} + +func outputVarsForExpr(expr *Expr, arity func(Ref) int, safe VarSet) VarSet { + + // Negated expressions must be safe. + if expr.Negated { + return VarSet{} + } + + // With modifier inputs must be safe. + for _, with := range expr.With { + unsafe := false + WalkVars(with, func(v Var) bool { + if !safe.Contains(v) { + unsafe = true + return true + } + return false + }) + if unsafe { + return VarSet{} + } + } + + if !expr.IsCall() { + return outputVarsForExprRefs(expr, safe) + } + + terms := expr.Terms.([]*Term) + name := terms[0].String() + + if b := BuiltinMap[name]; b != nil { + if b.Name == Equality.Name { + return outputVarsForExprEq(expr, safe) + } + return outputVarsForExprBuiltin(expr, b, safe) + } + + return outputVarsForExprCall(expr, arity, safe, terms) +} + +func outputVarsForExprBuiltin(expr *Expr, b *Builtin, safe VarSet) VarSet { + + output := outputVarsForExprRefs(expr, safe) + terms := expr.Terms.([]*Term) + + // Check that all input terms are safe. + for i, t := range terms[1:] { + if b.IsTargetPos(i) { + continue + } + vis := NewVarVisitor().WithParams(VarVisitorParams{ + SkipClosures: true, + SkipSets: true, + SkipObjectKeys: true, + SkipRefHead: true, + }) + Walk(vis, t) + unsafe := vis.Vars().Diff(output).Diff(safe) + if len(unsafe) > 0 { + return VarSet{} + } + } + + // Add vars in target positions to result. + for i, t := range terms[1:] { + if b.IsTargetPos(i) { + vis := NewVarVisitor().WithParams(VarVisitorParams{ + SkipRefHead: true, + SkipSets: true, + SkipObjectKeys: true, + SkipClosures: true, + }) + Walk(vis, t) + output.Update(vis.vars) + } + } + + return output +} + +func outputVarsForExprEq(expr *Expr, safe VarSet) VarSet { + ts := expr.Terms.([]*Term) + output := outputVarsForExprRefs(expr, safe) + output.Update(safe) + output.Update(Unify(output, ts[1], ts[2])) + return output.Diff(safe) +} + +func outputVarsForExprCall(expr *Expr, arity func(Ref) int, safe VarSet, terms []*Term) VarSet { + + output := outputVarsForExprRefs(expr, safe) + + ref, ok := terms[0].Value.(Ref) + if !ok { + return VarSet{} + } + + numArgs := arity(ref) + if numArgs == -1 { + return VarSet{} + } + + numInputTerms := numArgs + 1 + + if numInputTerms >= len(terms) { + return output + } + + vis := NewVarVisitor().WithParams(VarVisitorParams{ + SkipClosures: true, + SkipSets: true, + SkipObjectKeys: true, + SkipRefHead: true, + }) + + Walk(vis, Args(terms[:numInputTerms])) + unsafe := vis.Vars().Diff(output).Diff(safe) + + if len(unsafe) > 0 { + return VarSet{} + } + + vis = NewVarVisitor().WithParams(VarVisitorParams{ + SkipRefHead: true, + SkipSets: true, + SkipObjectKeys: true, + SkipClosures: true, + }) + + Walk(vis, Args(terms[numInputTerms:])) + output.Update(vis.vars) + return output +} + +func outputVarsForExprRefs(expr *Expr, safe VarSet) VarSet { + output := VarSet{} + WalkRefs(expr, func(r Ref) bool { + if safe.Contains(r[0].Value.(Var)) { + output.Update(r.OutputVars()) + return false + } + return true + }) + return output +} + type equalityFactory struct { gen *localVarGenerator } @@ -1521,7 +1853,7 @@ func requiresEval(x *Term) bool { return ContainsRefs(x) || ContainsComprehensions(x) } -func resolveRef(globals map[Var]Ref, ref Ref) Ref { +func resolveRef(globals map[Var]Ref, ignore *assignedVarStack, ref Ref) Ref { r := Ref{} for i, x := range ref { @@ -1540,8 +1872,8 @@ func resolveRef(globals map[Var]Ref, ref Ref) Ref { } else { r = append(r, x) } - case Ref, Array, Object, *Set: - r = append(r, resolveRefsInTerm(globals, x)) + case Ref, Array, Object, Set: + r = append(r, resolveRefsInTerm(globals, ignore, x)) default: r = append(r, x) } @@ -1550,50 +1882,100 @@ func resolveRef(globals map[Var]Ref, ref Ref) Ref { return r } -func resolveRefsInRule(globals map[Var]Ref, rule *Rule) { - for i := range rule.Head.Args { - rule.Head.Args[i] = resolveRefsInTerm(globals, rule.Head.Args[i]) +func resolveRefsInRule(globals map[Var]Ref, rule *Rule) error { + ignore := &assignedVarStack{} + + vars := NewVarSet() + var vis Visitor + var err error + + // Walk args to collect vars and transform body so that callers can shadow + // root documents. + vis = NewGenericVisitor(func(x interface{}) bool { + if err != nil { + return true + } + switch x := x.(type) { + case Var: + vars.Add(x) + + // Object keys cannot be pattern matched so only walk values. + case Object: + x.Foreach(func(_, v *Term) { + Walk(vis, v) + }) + + // Skip terms that could contain vars that cannot be pattern matched. + case Set, *ArrayComprehension, *SetComprehension, *ObjectComprehension, Call: + return true + + case *Term: + if _, ok := x.Value.(Ref); ok { + if RootDocumentRefs.Contains(x) { + // We could support args named input, data, etc. however + // this would require rewriting terms in the head and body. + // Preventing root document shadowing is simpler, and + // arguably, will prevent confusing names from being used. + err = fmt.Errorf("args must not shadow %v (use a different variable name)", x) + return true + } + } + } + return false + }) + + Walk(vis, rule.Head.Args) + + if err != nil { + return err } + + ignore.Push(vars) + ignore.Push(assignedVars(rule.Body)) + if rule.Head.Key != nil { - rule.Head.Key = resolveRefsInTerm(globals, rule.Head.Key) + rule.Head.Key = resolveRefsInTerm(globals, ignore, rule.Head.Key) } + if rule.Head.Value != nil { - rule.Head.Value = resolveRefsInTerm(globals, rule.Head.Value) + rule.Head.Value = resolveRefsInTerm(globals, ignore, rule.Head.Value) } - rule.Body = resolveRefsInBody(globals, rule.Body) + + rule.Body = resolveRefsInBody(globals, ignore, rule.Body) + return nil } -func resolveRefsInBody(globals map[Var]Ref, body Body) Body { +func resolveRefsInBody(globals map[Var]Ref, ignore *assignedVarStack, body Body) Body { r := Body{} for _, expr := range body { - r = append(r, resolveRefsInExpr(globals, expr)) + r = append(r, resolveRefsInExpr(globals, ignore, expr)) } return r } -func resolveRefsInExpr(globals map[Var]Ref, expr *Expr) *Expr { +func resolveRefsInExpr(globals map[Var]Ref, ignore *assignedVarStack, expr *Expr) *Expr { cpy := *expr switch ts := expr.Terms.(type) { case *Term: - cpy.Terms = resolveRefsInTerm(globals, ts) + cpy.Terms = resolveRefsInTerm(globals, ignore, ts) case []*Term: buf := make([]*Term, len(ts)) for i := 0; i < len(ts); i++ { - buf[i] = resolveRefsInTerm(globals, ts[i]) + buf[i] = resolveRefsInTerm(globals, ignore, ts[i]) } cpy.Terms = buf } for _, w := range cpy.With { - w.Target = resolveRefsInTerm(globals, w.Target) - w.Value = resolveRefsInTerm(globals, w.Value) + w.Target = resolveRefsInTerm(globals, ignore, w.Target) + w.Value = resolveRefsInTerm(globals, ignore, w.Value) } return &cpy } -func resolveRefsInTerm(globals map[Var]Ref, term *Term) *Term { +func resolveRefsInTerm(globals map[Var]Ref, ignore *assignedVarStack, term *Term) *Term { switch v := term.Value.(type) { case Var: - if g, ok := globals[v]; ok { + if g, ok := globals[v]; ok && !ignore.Assigned(v) { cpy := g.Copy() for i := range cpy { cpy[i].SetLocation(term.Location) @@ -1602,57 +1984,58 @@ func resolveRefsInTerm(globals map[Var]Ref, term *Term) *Term { } return term case Ref: - fqn := resolveRef(globals, v) + fqn := resolveRef(globals, ignore, v) cpy := *term cpy.Value = fqn return &cpy case Object: - o := Object{} - for _, i := range v { - k := resolveRefsInTerm(globals, i[0]) - v := resolveRefsInTerm(globals, i[1]) - o = append(o, Item(k, v)) - } cpy := *term - cpy.Value = o + cpy.Value, _ = v.Map(func(k, v *Term) (*Term, *Term, error) { + k = resolveRefsInTerm(globals, ignore, k) + v = resolveRefsInTerm(globals, ignore, v) + return k, v, nil + }) return &cpy case Array: - a := Array{} - for _, e := range v { - x := resolveRefsInTerm(globals, e) - a = append(a, x) - } cpy := *term - cpy.Value = a + cpy.Value = Array(resolveRefsInTermSlice(globals, ignore, v)) return &cpy - case *Set: - s := &Set{} - for _, e := range *v { - x := resolveRefsInTerm(globals, e) - s.Add(x) - } + case Call: + cpy := *term + cpy.Value = Call(resolveRefsInTermSlice(globals, ignore, v)) + return &cpy + case Set: + s, _ := v.Map(func(e *Term) (*Term, error) { + return resolveRefsInTerm(globals, ignore, e), nil + }) cpy := *term cpy.Value = s return &cpy case *ArrayComprehension: ac := &ArrayComprehension{} - ac.Term = resolveRefsInTerm(globals, v.Term) - ac.Body = resolveRefsInBody(globals, v.Body) + ignore.Push(assignedVars(v.Body)) + defer ignore.Pop() + ac.Term = resolveRefsInTerm(globals, ignore, v.Term) + ac.Body = resolveRefsInBody(globals, ignore, v.Body) cpy := *term cpy.Value = ac return &cpy case *ObjectComprehension: oc := &ObjectComprehension{} - oc.Key = resolveRefsInTerm(globals, v.Key) - oc.Value = resolveRefsInTerm(globals, v.Value) - oc.Body = resolveRefsInBody(globals, v.Body) + ignore.Push(assignedVars(v.Body)) + defer ignore.Pop() + oc.Key = resolveRefsInTerm(globals, ignore, v.Key) + oc.Value = resolveRefsInTerm(globals, ignore, v.Value) + oc.Body = resolveRefsInBody(globals, ignore, v.Body) cpy := *term cpy.Value = oc return &cpy case *SetComprehension: sc := &SetComprehension{} - sc.Term = resolveRefsInTerm(globals, v.Term) - sc.Body = resolveRefsInBody(globals, v.Body) + ignore.Push(assignedVars(v.Body)) + defer ignore.Pop() + sc.Term = resolveRefsInTerm(globals, ignore, v.Term) + sc.Body = resolveRefsInBody(globals, ignore, v.Body) cpy := *term cpy.Value = sc return &cpy @@ -1661,6 +2044,57 @@ func resolveRefsInTerm(globals map[Var]Ref, term *Term) *Term { } } +func resolveRefsInTermSlice(globals map[Var]Ref, ignore *assignedVarStack, terms []*Term) []*Term { + cpy := make([]*Term, len(terms)) + for i := 0; i < len(terms); i++ { + cpy[i] = resolveRefsInTerm(globals, ignore, terms[i]) + } + return cpy +} + +type assignedVarStack []VarSet + +func (s assignedVarStack) Assigned(v Var) bool { + for i := len(s) - 1; i >= 0; i-- { + if _, ok := s[i][v]; ok { + return ok + } + } + return false +} + +func (s assignedVarStack) Add(v Var) { + s[len(s)-1].Add(v) +} + +func (s *assignedVarStack) Push(vs VarSet) { + *s = append(*s, vs) +} + +func (s *assignedVarStack) Pop() { + curr := *s + *s = curr[:len(curr)-1] +} +func assignedVars(x interface{}) VarSet { + vars := NewVarSet() + vis := NewGenericVisitor(func(x interface{}) bool { + switch x := x.(type) { + case *Expr: + if x.IsAssignment() { + WalkVars(x.Operand(0), func(v Var) bool { + vars.Add(v) + return false + }) + } + case *ArrayComprehension, *SetComprehension, *ObjectComprehension: + return true + } + return false + }) + Walk(vis, x) + return vars +} + // rewriteComprehensionTerms will rewrite comprehensions so that the term part // is bound to a variable in the body. This allows any type of term to be used // in the term part (even if the term requires evaluation.) @@ -1796,12 +2230,13 @@ func rewriteDynamicsOne(original *Expr, f *equalityFactory, term *Term, extras [ } return extras, term case Object: - for i := 0; i < len(v); i++ { - extras, v[i][0] = rewriteDynamicsOne(original, f, v[i][0], extras) - extras, v[i][1] = rewriteDynamicsOne(original, f, v[i][1], extras) - } + term.Value, _ = v.Map(func(k, v *Term) (*Term, *Term, error) { + extras, k = rewriteDynamicsOne(original, f, k, extras) + extras, v = rewriteDynamicsOne(original, f, v, extras) + return k, v, nil + }) return extras, term - case *Set: + case Set: v, _ = v.Map(func(term *Term) (*Term, error) { extras, term = rewriteDynamicsOne(original, f, term, extras) return term, nil @@ -1832,3 +2267,332 @@ func rewriteDynamicsComprehensionBody(original *Expr, f *equalityFactory, body B generated.With = original.With return body, generated } + +func rewriteExprTermsInHead(gen *localVarGenerator, rule *Rule) { + if rule.Head.Key != nil { + support, output := expandExprTerm(gen, rule.Head.Key) + for i := range support { + rule.Body.Append(support[i]) + } + rule.Head.Key = output + } + if rule.Head.Value != nil { + support, output := expandExprTerm(gen, rule.Head.Value) + for i := range support { + rule.Body.Append(support[i]) + } + rule.Head.Value = output + } +} + +func rewriteExprTermsInBody(gen *localVarGenerator, body Body) Body { + cpy := make(Body, 0, len(body)) + for i := 0; i < len(body); i++ { + for _, expr := range expandExpr(gen, body[i]) { + cpy.Append(expr) + } + } + return cpy +} + +func expandExpr(gen *localVarGenerator, expr *Expr) (result []*Expr) { + switch terms := expr.Terms.(type) { + case *Term: + extras, term := expandExprTerm(gen, terms) + if len(expr.With) > 0 { + for i := range extras { + extras[i].With = expr.With + } + } + result = append(result, extras...) + expr.Terms = term + result = append(result, expr) + case []*Term: + for i := 1; i < len(terms); i++ { + var extras []*Expr + extras, terms[i] = expandExprTerm(gen, terms[i]) + if len(expr.With) > 0 { + for i := range extras { + extras[i].With = expr.With + } + } + result = append(result, extras...) + } + result = append(result, expr) + } + return +} + +func expandExprTerm(gen *localVarGenerator, term *Term) (support []*Expr, output *Term) { + output = term + switch v := term.Value.(type) { + case Call: + for i := 1; i < len(v); i++ { + var extras []*Expr + extras, v[i] = expandExprTerm(gen, v[i]) + support = append(support, extras...) + } + output = NewTerm(gen.Generate()).SetLocation(term.Location) + expr := v.MakeExpr(output).SetLocation(term.Location) + expr.Generated = true + support = append(support, expr) + case Ref: + support = expandExprTermSlice(gen, v) + case Array: + support = expandExprTermSlice(gen, v) + case Object: + cpy, _ := v.Map(func(k, v *Term) (*Term, *Term, error) { + extras1, expandedKey := expandExprTerm(gen, k) + extras2, expandedValue := expandExprTerm(gen, v) + support = append(support, extras1...) + support = append(support, extras2...) + return expandedKey, expandedValue, nil + }) + output = NewTerm(cpy).SetLocation(term.Location) + case Set: + cpy, _ := v.Map(func(x *Term) (*Term, error) { + extras, expanded := expandExprTerm(gen, x) + support = append(support, extras...) + return expanded, nil + }) + output = NewTerm(cpy).SetLocation(term.Location) + case *ArrayComprehension: + support, term := expandExprTerm(gen, v.Term) + for i := range support { + v.Body.Append(support[i]) + } + v.Term = term + v.Body = rewriteExprTermsInBody(gen, v.Body) + case *SetComprehension: + support, term := expandExprTerm(gen, v.Term) + for i := range support { + v.Body.Append(support[i]) + } + v.Term = term + v.Body = rewriteExprTermsInBody(gen, v.Body) + case *ObjectComprehension: + support, key := expandExprTerm(gen, v.Key) + for i := range support { + v.Body.Append(support[i]) + } + v.Key = key + support, value := expandExprTerm(gen, v.Value) + for i := range support { + v.Body.Append(support[i]) + } + v.Value = value + v.Body = rewriteExprTermsInBody(gen, v.Body) + } + return +} + +func expandExprTermSlice(gen *localVarGenerator, v []*Term) (support []*Expr) { + for i := 0; i < len(v); i++ { + var extras []*Expr + extras, v[i] = expandExprTerm(gen, v[i]) + support = append(support, extras...) + } + return +} + +type localDeclaredVars []map[Var]Var + +func newLocalDeclaredVars() *localDeclaredVars { + return &localDeclaredVars{map[Var]Var{}} +} + +func (s *localDeclaredVars) Push() { + *s = append(*s, map[Var]Var{}) +} + +func (s *localDeclaredVars) Pop() map[Var]Var { + sl := *s + curr := sl[len(sl)-1] + *s = sl[:len(sl)-1] + return curr +} + +func (s localDeclaredVars) Insert(x, y Var) { + s[len(s)-1][x] = y +} + +func (s localDeclaredVars) Declared(x Var) (y Var, ok bool) { + for i := len(s) - 1; i >= 0; i-- { + if y, ok = s[i][x]; ok { + return + } + } + return +} + +func (s localDeclaredVars) Seen(x Var) bool { + _, ok := s[len(s)-1][x] + return ok +} + +// rewriteLocalAssignments rewrites bodies to remove assignment/declaration +// expressions. For example: +// +// a := 1; p[a] +// +// Is rewritten to: +// +// __local0__ = 1; p[__local0__] +// +// During rewriting, assignees are validated to prevent use before declaration. +func rewriteLocalAssignments(g *localVarGenerator, body Body) (Body, map[Var]Var, Errors) { + stack := newLocalDeclaredVars() + var errs Errors + errs = rewriteDeclaredVarsInBody(g, stack, body, errs) + return body, stack.Pop(), errs +} + +func rewriteDeclaredVarsInBody(g *localVarGenerator, stack *localDeclaredVars, body Body, errs Errors) Errors { + vis := NewGenericVisitor(func(x interface{}) bool { + var stop bool + switch x := x.(type) { + case *Term: + stop, errs = rewriteDeclaredVarsInTerm(g, stack, x, errs) + case *With: + _, errs = rewriteDeclaredVarsInTerm(g, stack, x.Value, errs) + stop = true + } + return stop + }) + for _, expr := range body { + if expr.IsAssignment() { + errs = rewriteDeclaredAssignment(g, stack, expr, errs) + } else { + Walk(vis, expr) + } + } + return errs +} + +func rewriteDeclaredAssignment(g *localVarGenerator, stack *localDeclaredVars, expr *Expr, errs Errors) Errors { + + if expr.Negated { + errs = append(errs, NewError(CompileErr, expr.Location, "cannot assign vars inside negated expression")) + return errs + } + + numErrsBefore := len(errs) + + // Rewrite terms on right hand side capture seen vars and recursively + // process comprehensions before left hand side is processed. + rewriteDeclaredVarsInTermRecursive(g, stack, expr.Operand(1), errs) + + // Rewrite vars on right hand side with unique names. Catch redeclaration + // and invalid term types here. + var vis func(t *Term) bool + + vis = func(t *Term) bool { + switch v := t.Value.(type) { + case Var: + if gv, err := rewriteDeclaredVar(g, stack, v); err != nil { + errs = append(errs, NewError(CompileErr, t.Location, err.Error())) + } else { + t.Value = gv + } + return true + case Array: + return false + case Object: + v.Foreach(func(_, v *Term) { + WalkTerms(v, vis) + }) + return true + case Ref: + if RootDocumentRefs.Contains(t) { + if gv, err := rewriteDeclaredVar(g, stack, v[0].Value.(Var)); err != nil { + errs = append(errs, NewError(CompileErr, t.Location, err.Error())) + } else { + t.Value = gv + } + return true + } + } + errs = append(errs, NewError(CompileErr, t.Location, "cannot assign to %v", TypeName(t.Value))) + return true + } + + WalkTerms(expr.Operand(0), vis) + + if len(errs) == numErrsBefore { + loc := expr.Operator()[0].Location + expr.SetOperator(RefTerm(VarTerm(Equality.Name).SetLocation(loc)).SetLocation(loc)) + } + + return errs +} + +func rewriteDeclaredVarsInTerm(g *localVarGenerator, stack *localDeclaredVars, term *Term, errs Errors) (bool, Errors) { + switch v := term.Value.(type) { + case Var: + if gv, ok := stack.Declared(v); ok { + term.Value = gv + } else if !stack.Seen(v) { + stack.Insert(v, v) + } + case Ref: + if RootDocumentRefs.Contains(term) { + if gv, ok := stack.Declared(v[0].Value.(Var)); ok { + term.Value = gv + } + return true, errs + } + return false, errs + case *ArrayComprehension: + errs = rewriteDeclaredVarsInArrayComprehension(g, stack, v, errs) + case *SetComprehension: + errs = rewriteDeclaredVarsInSetComprehension(g, stack, v, errs) + case *ObjectComprehension: + errs = rewriteDeclaredVarsInObjectComprehension(g, stack, v, errs) + default: + return false, errs + } + return true, errs +} + +func rewriteDeclaredVarsInTermRecursive(g *localVarGenerator, stack *localDeclaredVars, term *Term, errs Errors) Errors { + WalkTerms(term, func(term *Term) bool { + _, errs = rewriteDeclaredVarsInTerm(g, stack, term, errs) + return false + }) + return errs +} + +func rewriteDeclaredVarsInArrayComprehension(g *localVarGenerator, stack *localDeclaredVars, v *ArrayComprehension, errs Errors) Errors { + stack.Push() + errs = rewriteDeclaredVarsInBody(g, stack, v.Body, errs) + errs = rewriteDeclaredVarsInTermRecursive(g, stack, v.Term, errs) + stack.Pop() + return errs +} + +func rewriteDeclaredVarsInSetComprehension(g *localVarGenerator, stack *localDeclaredVars, v *SetComprehension, errs Errors) Errors { + stack.Push() + errs = rewriteDeclaredVarsInBody(g, stack, v.Body, errs) + errs = rewriteDeclaredVarsInTermRecursive(g, stack, v.Term, errs) + stack.Pop() + return errs +} + +func rewriteDeclaredVarsInObjectComprehension(g *localVarGenerator, stack *localDeclaredVars, v *ObjectComprehension, errs Errors) Errors { + stack.Push() + errs = rewriteDeclaredVarsInBody(g, stack, v.Body, errs) + errs = rewriteDeclaredVarsInTermRecursive(g, stack, v.Key, errs) + errs = rewriteDeclaredVarsInTermRecursive(g, stack, v.Value, errs) + stack.Pop() + return errs +} + +func rewriteDeclaredVar(g *localVarGenerator, stack *localDeclaredVars, v Var) (gv Var, err error) { + if stack.Seen(v) { + err = fmt.Errorf("var %v assigned or referenced above", v) + return + } + gv = g.Generate() + stack.Insert(v, gv) + return +} diff --git a/github.com/open-policy-agent/opa/ast/env.go b/github.com/open-policy-agent/opa/ast/env.go index 22a7a9f9..f0830e5b 100644 --- a/github.com/open-policy-agent/opa/ast/env.go +++ b/github.com/open-policy-agent/opa/ast/env.go @@ -35,10 +35,7 @@ func (env *TypeEnv) Get(x interface{}) types.Type { case Null: return types.NewNull() case Boolean: - if x.Compare(Boolean(true)) == 0 { - return types.T - } - return types.F + return types.NewBoolean() case Number: return types.NewNumber() case String: @@ -63,20 +60,20 @@ func (env *TypeEnv) Get(x interface{}) types.Type { static := []*types.StaticProperty{} var dynamic *types.DynamicProperty - for _, pair := range x { - if IsConstant(pair[0].Value) { - k, err := JSON(pair[0].Value) + x.Foreach(func(k, v *Term) { + if IsConstant(k.Value) { + kjson, err := JSON(k.Value) if err != nil { panic("unreachable") } - tpe := env.Get(pair[1].Value) - static = append(static, types.NewStaticProperty(k, tpe)) + tpe := env.Get(v) + static = append(static, types.NewStaticProperty(kjson, tpe)) } else { - typeK := env.Get(pair[0].Value) - typeV := env.Get(pair[1].Value) + typeK := env.Get(k.Value) + typeV := env.Get(v.Value) dynamic = types.NewDynamicProperty(typeK, typeV) } - } + }) if len(static) == 0 && dynamic == nil { dynamic = types.NewDynamicProperty(types.A, types.A) @@ -84,12 +81,11 @@ func (env *TypeEnv) Get(x interface{}) types.Type { return types.NewObject(static, dynamic) - case *Set: + case Set: var tpe types.Type - x.Iter(func(elem *Term) bool { + x.Foreach(func(elem *Term) { other := env.Get(elem.Value) tpe = types.Or(tpe, other) - return false }) if tpe == nil { tpe = types.A @@ -319,7 +315,7 @@ func selectRef(tpe types.Type, ref Ref) types.Type { head, tail := ref[0], ref[1:] switch head.Value.(type) { - case Var, Ref, Array, Object, *Set: + case Var, Ref, Array, Object, Set: return selectRef(types.Values(tpe), tail) default: return selectRef(selectConstant(tpe, head), tail) diff --git a/github.com/open-policy-agent/opa/ast/index.go b/github.com/open-policy-agent/opa/ast/index.go index 5e923588..bb539d33 100644 --- a/github.com/open-policy-agent/opa/ast/index.go +++ b/github.com/open-policy-agent/opa/ast/index.go @@ -237,7 +237,7 @@ func (i *baseDocEqIndex) getRefAndValueFromTerms(a, b *Term) (Ref, Value, bool) } switch x.(type) { // No nested structures or values that require evaluation (other than var). - case Array, Object, *Set, *ArrayComprehension, *ObjectComprehension, *SetComprehension, Ref: + case Array, Object, Set, *ArrayComprehension, *ObjectComprehension, *SetComprehension, Ref: stop = true } return stop diff --git a/github.com/open-policy-agent/opa/ast/parser.go b/github.com/open-policy-agent/opa/ast/parser.go index f2bb518a..bbdf02ff 100644 --- a/github.com/open-policy-agent/opa/ast/parser.go +++ b/github.com/open-policy-agent/opa/ast/parser.go @@ -2,184 +2,58 @@ package ast import ( "bytes" - "encoding/json" "errors" "fmt" "io" "io/ioutil" - "math/big" + "math" "os" "sort" + "strconv" "strings" "unicode" "unicode/utf8" ) -const ( - // commentsKey is the global map key for the comments slice. - commentsKey = "comments" - - // filenameKey is the global map key for the filename. - filenameKey = "filename" -) - -type program struct { - buf []interface{} - comments interface{} -} - -type ruleExt struct { - loc *Location - term *Term - body Body -} - -// currentLocation converts the parser context to a Location object. -func currentLocation(c *current) *Location { - return NewLocation(c.text, c.globalStore[filenameKey].(string), c.pos.line, c.pos.col) -} - -func ifaceSliceToByteSlice(i interface{}) []byte { - var buf bytes.Buffer - for _, x := range i.([]interface{}) { - buf.Write(x.([]byte)) - } - return buf.Bytes() -} - -func ifacesToBody(i interface{}, a ...interface{}) Body { - var buf Body - buf = append(buf, i.(*Expr)) - for _, s := range a { - expr := s.([]interface{})[3].(*Expr) - buf = append(buf, expr) - } - return buf -} - -func makeObject(head interface{}, tail interface{}, loc *Location) (*Term, error) { - obj := ObjectTerm() - obj.Location = loc - - // Empty object. - if head == nil { - return obj, nil - } - - // Object definition above describes the "head" structure. We only care about the "Key" and "Term" elements. - headSlice := head.([]interface{}) - obj.Value = append(obj.Value.(Object), Item(headSlice[0].(*Term), headSlice[len(headSlice)-1].(*Term))) - - // Non-empty object, remaining key/value pairs. - tailSlice := tail.([]interface{}) - for _, v := range tailSlice { - s := v.([]interface{}) - // Object definition above describes the "tail" structure. We only care about the "Key" and "Term" elements. - obj.Value = append(obj.Value.(Object), Item(s[3].(*Term), s[len(s)-1].(*Term))) - } - - return obj, nil -} - -func makeArray(head interface{}, tail interface{}, loc *Location) (*Term, error) { - arr := ArrayTerm() - arr.Location = loc - - // Empty array. - if head == nil { - return arr, nil - } - - // Non-empty array, first element. - arr.Value = append(arr.Value.(Array), head.(*Term)) - - // Non-empty array, remaining elements. - tailSlice := tail.([]interface{}) - for _, v := range tailSlice { - s := v.([]interface{}) - // Array definition above describes the "tail" structure. We only care about the "Term" elements. - arr.Value = append(arr.Value.(Array), s[len(s)-1].(*Term)) - } - - return arr, nil -} - -func makeArgs(head interface{}, tail interface{}, loc *Location) (Args, error) { - args := Args{} - if head == nil { - return nil, nil - } - args = append(args, head.(*Term)) - tailSlice := tail.([]interface{}) - for _, v := range tailSlice { - s := v.([]interface{}) - args = append(args, s[len(s)-1].(*Term)) - } - return args, nil -} - -func makeInfixCallExpr(operator interface{}, args interface{}, output interface{}) (*Expr, error) { - expr := &Expr{} - a := args.(Args) - terms := make([]*Term, len(a)+2) - terms[0] = operator.(*Term) - dst := terms[1:] - for i := 0; i < len(a); i++ { - dst[i] = a[i] - } - terms[len(terms)-1] = output.(*Term) - expr.Terms = terms - expr.Infix = true - return expr, nil -} - var g = &grammar{ rules: []*rule{ { name: "Program", - pos: position{line: 125, col: 1, offset: 3203}, + pos: position{line: 5, col: 1, offset: 17}, expr: &actionExpr{ - pos: position{line: 125, col: 12, offset: 3214}, + pos: position{line: 5, col: 12, offset: 28}, run: (*parser).callonProgram1, expr: &seqExpr{ - pos: position{line: 125, col: 12, offset: 3214}, + pos: position{line: 5, col: 12, offset: 28}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 125, col: 12, offset: 3214}, + pos: position{line: 5, col: 12, offset: 28}, name: "_", }, &labeledExpr{ - pos: position{line: 125, col: 14, offset: 3216}, + pos: position{line: 5, col: 14, offset: 30}, label: "vals", expr: &zeroOrOneExpr{ - pos: position{line: 125, col: 19, offset: 3221}, + pos: position{line: 5, col: 19, offset: 35}, expr: &seqExpr{ - pos: position{line: 125, col: 20, offset: 3222}, + pos: position{line: 5, col: 20, offset: 36}, exprs: []interface{}{ - &labeledExpr{ - pos: position{line: 125, col: 20, offset: 3222}, - label: "head", - expr: &ruleRefExpr{ - pos: position{line: 125, col: 25, offset: 3227}, - name: "Stmt", - }, + &ruleRefExpr{ + pos: position{line: 5, col: 20, offset: 36}, + name: "Stmt", }, - &labeledExpr{ - pos: position{line: 125, col: 30, offset: 3232}, - label: "tail", - expr: &zeroOrMoreExpr{ - pos: position{line: 125, col: 35, offset: 3237}, - expr: &seqExpr{ - pos: position{line: 125, col: 36, offset: 3238}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 125, col: 36, offset: 3238}, - name: "ws", - }, - &ruleRefExpr{ - pos: position{line: 125, col: 39, offset: 3241}, - name: "Stmt", - }, + &zeroOrMoreExpr{ + pos: position{line: 5, col: 25, offset: 41}, + expr: &seqExpr{ + pos: position{line: 5, col: 26, offset: 42}, + exprs: []interface{}{ + &ruleRefExpr{ + pos: position{line: 5, col: 26, offset: 42}, + name: "ws", + }, + &ruleRefExpr{ + pos: position{line: 5, col: 29, offset: 45}, + name: "Stmt", }, }, }, @@ -189,11 +63,11 @@ var g = &grammar{ }, }, &ruleRefExpr{ - pos: position{line: 125, col: 48, offset: 3250}, + pos: position{line: 5, col: 38, offset: 54}, name: "_", }, &ruleRefExpr{ - pos: position{line: 125, col: 50, offset: 3252}, + pos: position{line: 5, col: 40, offset: 56}, name: "EOF", }, }, @@ -202,34 +76,34 @@ var g = &grammar{ }, { name: "Stmt", - pos: position{line: 143, col: 1, offset: 3626}, + pos: position{line: 9, col: 1, offset: 97}, expr: &actionExpr{ - pos: position{line: 143, col: 9, offset: 3634}, + pos: position{line: 9, col: 9, offset: 105}, run: (*parser).callonStmt1, expr: &labeledExpr{ - pos: position{line: 143, col: 9, offset: 3634}, + pos: position{line: 9, col: 9, offset: 105}, label: "val", expr: &choiceExpr{ - pos: position{line: 143, col: 14, offset: 3639}, + pos: position{line: 9, col: 14, offset: 110}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 143, col: 14, offset: 3639}, + pos: position{line: 9, col: 14, offset: 110}, name: "Package", }, &ruleRefExpr{ - pos: position{line: 143, col: 24, offset: 3649}, + pos: position{line: 9, col: 24, offset: 120}, name: "Import", }, &ruleRefExpr{ - pos: position{line: 143, col: 33, offset: 3658}, + pos: position{line: 9, col: 33, offset: 129}, name: "Rules", }, &ruleRefExpr{ - pos: position{line: 143, col: 41, offset: 3666}, + pos: position{line: 9, col: 41, offset: 137}, name: "Body", }, &ruleRefExpr{ - pos: position{line: 143, col: 48, offset: 3673}, + pos: position{line: 9, col: 48, offset: 144}, name: "Comment", }, }, @@ -239,34 +113,34 @@ var g = &grammar{ }, { name: "Package", - pos: position{line: 147, col: 1, offset: 3707}, + pos: position{line: 13, col: 1, offset: 178}, expr: &actionExpr{ - pos: position{line: 147, col: 12, offset: 3718}, + pos: position{line: 13, col: 12, offset: 189}, run: (*parser).callonPackage1, expr: &seqExpr{ - pos: position{line: 147, col: 12, offset: 3718}, + pos: position{line: 13, col: 12, offset: 189}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 147, col: 12, offset: 3718}, + pos: position{line: 13, col: 12, offset: 189}, val: "package", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 147, col: 22, offset: 3728}, + pos: position{line: 13, col: 22, offset: 199}, name: "ws", }, &labeledExpr{ - pos: position{line: 147, col: 25, offset: 3731}, + pos: position{line: 13, col: 25, offset: 202}, label: "val", expr: &choiceExpr{ - pos: position{line: 147, col: 30, offset: 3736}, + pos: position{line: 13, col: 30, offset: 207}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 147, col: 30, offset: 3736}, + pos: position{line: 13, col: 30, offset: 207}, name: "Ref", }, &ruleRefExpr{ - pos: position{line: 147, col: 36, offset: 3742}, + pos: position{line: 13, col: 36, offset: 213}, name: "Var", }, }, @@ -278,62 +152,62 @@ var g = &grammar{ }, { name: "Import", - pos: position{line: 181, col: 1, offset: 5058}, + pos: position{line: 17, col: 1, offset: 279}, expr: &actionExpr{ - pos: position{line: 181, col: 11, offset: 5068}, + pos: position{line: 17, col: 11, offset: 289}, run: (*parser).callonImport1, expr: &seqExpr{ - pos: position{line: 181, col: 11, offset: 5068}, + pos: position{line: 17, col: 11, offset: 289}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 181, col: 11, offset: 5068}, + pos: position{line: 17, col: 11, offset: 289}, val: "import", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 181, col: 20, offset: 5077}, + pos: position{line: 17, col: 20, offset: 298}, name: "ws", }, &labeledExpr{ - pos: position{line: 181, col: 23, offset: 5080}, + pos: position{line: 17, col: 23, offset: 301}, label: "path", expr: &choiceExpr{ - pos: position{line: 181, col: 29, offset: 5086}, + pos: position{line: 17, col: 29, offset: 307}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 181, col: 29, offset: 5086}, + pos: position{line: 17, col: 29, offset: 307}, name: "Ref", }, &ruleRefExpr{ - pos: position{line: 181, col: 35, offset: 5092}, + pos: position{line: 17, col: 35, offset: 313}, name: "Var", }, }, }, }, &labeledExpr{ - pos: position{line: 181, col: 40, offset: 5097}, + pos: position{line: 17, col: 40, offset: 318}, label: "alias", expr: &zeroOrOneExpr{ - pos: position{line: 181, col: 46, offset: 5103}, + pos: position{line: 17, col: 46, offset: 324}, expr: &seqExpr{ - pos: position{line: 181, col: 47, offset: 5104}, + pos: position{line: 17, col: 47, offset: 325}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 181, col: 47, offset: 5104}, + pos: position{line: 17, col: 47, offset: 325}, name: "ws", }, &litMatcher{ - pos: position{line: 181, col: 50, offset: 5107}, + pos: position{line: 17, col: 50, offset: 328}, val: "as", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 181, col: 55, offset: 5112}, + pos: position{line: 17, col: 55, offset: 333}, name: "ws", }, &ruleRefExpr{ - pos: position{line: 181, col: 58, offset: 5115}, + pos: position{line: 17, col: 58, offset: 336}, name: "Var", }, }, @@ -346,16 +220,16 @@ var g = &grammar{ }, { name: "Rules", - pos: position{line: 197, col: 1, offset: 5565}, + pos: position{line: 21, col: 1, offset: 402}, expr: &choiceExpr{ - pos: position{line: 197, col: 10, offset: 5574}, + pos: position{line: 21, col: 10, offset: 411}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 197, col: 10, offset: 5574}, + pos: position{line: 21, col: 10, offset: 411}, name: "DefaultRules", }, &ruleRefExpr{ - pos: position{line: 197, col: 25, offset: 5589}, + pos: position{line: 21, col: 25, offset: 426}, name: "NormalRules", }, }, @@ -363,48 +237,48 @@ var g = &grammar{ }, { name: "DefaultRules", - pos: position{line: 199, col: 1, offset: 5602}, + pos: position{line: 23, col: 1, offset: 439}, expr: &actionExpr{ - pos: position{line: 199, col: 17, offset: 5618}, + pos: position{line: 23, col: 17, offset: 455}, run: (*parser).callonDefaultRules1, expr: &seqExpr{ - pos: position{line: 199, col: 17, offset: 5618}, + pos: position{line: 23, col: 17, offset: 455}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 199, col: 17, offset: 5618}, + pos: position{line: 23, col: 17, offset: 455}, val: "default", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 199, col: 27, offset: 5628}, + pos: position{line: 23, col: 27, offset: 465}, name: "ws", }, &labeledExpr{ - pos: position{line: 199, col: 30, offset: 5631}, + pos: position{line: 23, col: 30, offset: 468}, label: "name", expr: &ruleRefExpr{ - pos: position{line: 199, col: 35, offset: 5636}, + pos: position{line: 23, col: 35, offset: 473}, name: "Var", }, }, &ruleRefExpr{ - pos: position{line: 199, col: 39, offset: 5640}, + pos: position{line: 23, col: 39, offset: 477}, name: "_", }, &litMatcher{ - pos: position{line: 199, col: 41, offset: 5642}, + pos: position{line: 23, col: 41, offset: 479}, val: "=", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 199, col: 45, offset: 5646}, + pos: position{line: 23, col: 45, offset: 483}, name: "_", }, &labeledExpr{ - pos: position{line: 199, col: 47, offset: 5648}, + pos: position{line: 23, col: 47, offset: 485}, label: "value", expr: &ruleRefExpr{ - pos: position{line: 199, col: 53, offset: 5654}, + pos: position{line: 23, col: 53, offset: 491}, name: "Term", }, }, @@ -414,46 +288,46 @@ var g = &grammar{ }, { name: "NormalRules", - pos: position{line: 242, col: 1, offset: 6623}, + pos: position{line: 27, col: 1, offset: 561}, expr: &actionExpr{ - pos: position{line: 242, col: 16, offset: 6638}, + pos: position{line: 27, col: 16, offset: 576}, run: (*parser).callonNormalRules1, expr: &seqExpr{ - pos: position{line: 242, col: 16, offset: 6638}, + pos: position{line: 27, col: 16, offset: 576}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 242, col: 16, offset: 6638}, + pos: position{line: 27, col: 16, offset: 576}, label: "head", expr: &ruleRefExpr{ - pos: position{line: 242, col: 21, offset: 6643}, + pos: position{line: 27, col: 21, offset: 581}, name: "RuleHead", }, }, &ruleRefExpr{ - pos: position{line: 242, col: 30, offset: 6652}, + pos: position{line: 27, col: 30, offset: 590}, name: "_", }, &labeledExpr{ - pos: position{line: 242, col: 32, offset: 6654}, - label: "b", + pos: position{line: 27, col: 32, offset: 592}, + label: "rest", expr: &seqExpr{ - pos: position{line: 242, col: 35, offset: 6657}, + pos: position{line: 27, col: 38, offset: 598}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 242, col: 35, offset: 6657}, + pos: position{line: 27, col: 38, offset: 598}, name: "NonEmptyBraceEnclosedBody", }, &zeroOrMoreExpr{ - pos: position{line: 242, col: 61, offset: 6683}, + pos: position{line: 27, col: 64, offset: 624}, expr: &seqExpr{ - pos: position{line: 242, col: 63, offset: 6685}, + pos: position{line: 27, col: 66, offset: 626}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 242, col: 63, offset: 6685}, + pos: position{line: 27, col: 66, offset: 626}, name: "_", }, &ruleRefExpr{ - pos: position{line: 242, col: 65, offset: 6687}, + pos: position{line: 27, col: 68, offset: 628}, name: "RuleExt", }, }, @@ -468,57 +342,57 @@ var g = &grammar{ }, { name: "RuleHead", - pos: position{line: 298, col: 1, offset: 8017}, + pos: position{line: 31, col: 1, offset: 697}, expr: &actionExpr{ - pos: position{line: 298, col: 13, offset: 8029}, + pos: position{line: 31, col: 13, offset: 709}, run: (*parser).callonRuleHead1, expr: &seqExpr{ - pos: position{line: 298, col: 13, offset: 8029}, + pos: position{line: 31, col: 13, offset: 709}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 298, col: 13, offset: 8029}, + pos: position{line: 31, col: 13, offset: 709}, label: "name", expr: &ruleRefExpr{ - pos: position{line: 298, col: 18, offset: 8034}, + pos: position{line: 31, col: 18, offset: 714}, name: "Var", }, }, &labeledExpr{ - pos: position{line: 298, col: 22, offset: 8038}, + pos: position{line: 31, col: 22, offset: 718}, label: "args", expr: &zeroOrOneExpr{ - pos: position{line: 298, col: 27, offset: 8043}, + pos: position{line: 31, col: 27, offset: 723}, expr: &seqExpr{ - pos: position{line: 298, col: 29, offset: 8045}, + pos: position{line: 31, col: 29, offset: 725}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 298, col: 29, offset: 8045}, + pos: position{line: 31, col: 29, offset: 725}, name: "_", }, &litMatcher{ - pos: position{line: 298, col: 31, offset: 8047}, + pos: position{line: 31, col: 31, offset: 727}, val: "(", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 298, col: 35, offset: 8051}, + pos: position{line: 31, col: 35, offset: 731}, name: "_", }, &ruleRefExpr{ - pos: position{line: 298, col: 37, offset: 8053}, + pos: position{line: 31, col: 37, offset: 733}, name: "Args", }, &ruleRefExpr{ - pos: position{line: 298, col: 42, offset: 8058}, + pos: position{line: 31, col: 42, offset: 738}, name: "_", }, &litMatcher{ - pos: position{line: 298, col: 44, offset: 8060}, + pos: position{line: 31, col: 44, offset: 740}, val: ")", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 298, col: 48, offset: 8064}, + pos: position{line: 31, col: 48, offset: 744}, name: "_", }, }, @@ -526,41 +400,41 @@ var g = &grammar{ }, }, &labeledExpr{ - pos: position{line: 298, col: 53, offset: 8069}, + pos: position{line: 31, col: 53, offset: 749}, label: "key", expr: &zeroOrOneExpr{ - pos: position{line: 298, col: 57, offset: 8073}, + pos: position{line: 31, col: 57, offset: 753}, expr: &seqExpr{ - pos: position{line: 298, col: 59, offset: 8075}, + pos: position{line: 31, col: 59, offset: 755}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 298, col: 59, offset: 8075}, + pos: position{line: 31, col: 59, offset: 755}, name: "_", }, &litMatcher{ - pos: position{line: 298, col: 61, offset: 8077}, + pos: position{line: 31, col: 61, offset: 757}, val: "[", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 298, col: 65, offset: 8081}, + pos: position{line: 31, col: 65, offset: 761}, name: "_", }, &ruleRefExpr{ - pos: position{line: 298, col: 67, offset: 8083}, - name: "Term", + pos: position{line: 31, col: 67, offset: 763}, + name: "ExprTerm", }, &ruleRefExpr{ - pos: position{line: 298, col: 72, offset: 8088}, + pos: position{line: 31, col: 76, offset: 772}, name: "_", }, &litMatcher{ - pos: position{line: 298, col: 74, offset: 8090}, + pos: position{line: 31, col: 78, offset: 774}, val: "]", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 298, col: 78, offset: 8094}, + pos: position{line: 31, col: 82, offset: 778}, name: "_", }, }, @@ -568,29 +442,29 @@ var g = &grammar{ }, }, &labeledExpr{ - pos: position{line: 298, col: 83, offset: 8099}, + pos: position{line: 31, col: 87, offset: 783}, label: "value", expr: &zeroOrOneExpr{ - pos: position{line: 298, col: 89, offset: 8105}, + pos: position{line: 31, col: 93, offset: 789}, expr: &seqExpr{ - pos: position{line: 298, col: 91, offset: 8107}, + pos: position{line: 31, col: 95, offset: 791}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 298, col: 91, offset: 8107}, + pos: position{line: 31, col: 95, offset: 791}, name: "_", }, &litMatcher{ - pos: position{line: 298, col: 93, offset: 8109}, + pos: position{line: 31, col: 97, offset: 793}, val: "=", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 298, col: 97, offset: 8113}, + pos: position{line: 31, col: 101, offset: 797}, name: "_", }, &ruleRefExpr{ - pos: position{line: 298, col: 99, offset: 8115}, - name: "Term", + pos: position{line: 31, col: 103, offset: 799}, + name: "ExprTerm", }, }, }, @@ -602,111 +476,57 @@ var g = &grammar{ }, { name: "Args", - pos: position{line: 341, col: 1, offset: 9323}, + pos: position{line: 35, col: 1, offset: 884}, expr: &actionExpr{ - pos: position{line: 341, col: 9, offset: 9331}, + pos: position{line: 35, col: 9, offset: 892}, run: (*parser).callonArgs1, - expr: &seqExpr{ - pos: position{line: 341, col: 9, offset: 9331}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 341, col: 9, offset: 9331}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 341, col: 11, offset: 9333}, - label: "head", - expr: &ruleRefExpr{ - pos: position{line: 341, col: 16, offset: 9338}, - name: "Term", - }, - }, - &labeledExpr{ - pos: position{line: 341, col: 21, offset: 9343}, - label: "tail", - expr: &zeroOrMoreExpr{ - pos: position{line: 341, col: 26, offset: 9348}, - expr: &seqExpr{ - pos: position{line: 341, col: 27, offset: 9349}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 341, col: 27, offset: 9349}, - name: "_", - }, - &litMatcher{ - pos: position{line: 341, col: 29, offset: 9351}, - val: ",", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 341, col: 33, offset: 9355}, - name: "_", - }, - &ruleRefExpr{ - pos: position{line: 341, col: 35, offset: 9357}, - name: "Term", - }, - }, - }, - }, - }, - &ruleRefExpr{ - pos: position{line: 341, col: 42, offset: 9364}, - name: "_", - }, - &zeroOrOneExpr{ - pos: position{line: 341, col: 44, offset: 9366}, - expr: &litMatcher{ - pos: position{line: 341, col: 44, offset: 9366}, - val: ",", - ignoreCase: false, - }, - }, - &ruleRefExpr{ - pos: position{line: 341, col: 49, offset: 9371}, - name: "_", - }, + expr: &labeledExpr{ + pos: position{line: 35, col: 9, offset: 892}, + label: "list", + expr: &ruleRefExpr{ + pos: position{line: 35, col: 14, offset: 897}, + name: "ExprTermList", }, }, }, }, { name: "Else", - pos: position{line: 345, col: 1, offset: 9427}, + pos: position{line: 39, col: 1, offset: 941}, expr: &actionExpr{ - pos: position{line: 345, col: 9, offset: 9435}, + pos: position{line: 39, col: 9, offset: 949}, run: (*parser).callonElse1, expr: &seqExpr{ - pos: position{line: 345, col: 9, offset: 9435}, + pos: position{line: 39, col: 9, offset: 949}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 345, col: 9, offset: 9435}, + pos: position{line: 39, col: 9, offset: 949}, val: "else", ignoreCase: false, }, &labeledExpr{ - pos: position{line: 345, col: 16, offset: 9442}, - label: "val", + pos: position{line: 39, col: 16, offset: 956}, + label: "value", expr: &zeroOrOneExpr{ - pos: position{line: 345, col: 20, offset: 9446}, + pos: position{line: 39, col: 22, offset: 962}, expr: &seqExpr{ - pos: position{line: 345, col: 22, offset: 9448}, + pos: position{line: 39, col: 24, offset: 964}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 345, col: 22, offset: 9448}, + pos: position{line: 39, col: 24, offset: 964}, name: "_", }, &litMatcher{ - pos: position{line: 345, col: 24, offset: 9450}, + pos: position{line: 39, col: 26, offset: 966}, val: "=", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 345, col: 28, offset: 9454}, + pos: position{line: 39, col: 30, offset: 970}, name: "_", }, &ruleRefExpr{ - pos: position{line: 345, col: 30, offset: 9456}, + pos: position{line: 39, col: 32, offset: 972}, name: "Term", }, }, @@ -714,17 +534,17 @@ var g = &grammar{ }, }, &labeledExpr{ - pos: position{line: 345, col: 38, offset: 9464}, - label: "b", + pos: position{line: 39, col: 40, offset: 980}, + label: "body", expr: &seqExpr{ - pos: position{line: 345, col: 42, offset: 9468}, + pos: position{line: 39, col: 47, offset: 987}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 345, col: 42, offset: 9468}, + pos: position{line: 39, col: 47, offset: 987}, name: "_", }, &ruleRefExpr{ - pos: position{line: 345, col: 44, offset: 9470}, + pos: position{line: 39, col: 49, offset: 989}, name: "NonEmptyBraceEnclosedBody", }, }, @@ -736,15 +556,15 @@ var g = &grammar{ }, { name: "RuleDup", - pos: position{line: 360, col: 1, offset: 9822}, + pos: position{line: 43, col: 1, offset: 1078}, expr: &actionExpr{ - pos: position{line: 360, col: 12, offset: 9833}, + pos: position{line: 43, col: 12, offset: 1089}, run: (*parser).callonRuleDup1, expr: &labeledExpr{ - pos: position{line: 360, col: 12, offset: 9833}, + pos: position{line: 43, col: 12, offset: 1089}, label: "b", expr: &ruleRefExpr{ - pos: position{line: 360, col: 14, offset: 9835}, + pos: position{line: 43, col: 14, offset: 1091}, name: "NonEmptyBraceEnclosedBody", }, }, @@ -752,16 +572,16 @@ var g = &grammar{ }, { name: "RuleExt", - pos: position{line: 364, col: 1, offset: 9931}, + pos: position{line: 47, col: 1, offset: 1187}, expr: &choiceExpr{ - pos: position{line: 364, col: 12, offset: 9942}, + pos: position{line: 47, col: 12, offset: 1198}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 364, col: 12, offset: 9942}, + pos: position{line: 47, col: 12, offset: 1198}, name: "Else", }, &ruleRefExpr{ - pos: position{line: 364, col: 19, offset: 9949}, + pos: position{line: 47, col: 19, offset: 1205}, name: "RuleDup", }, }, @@ -769,16 +589,16 @@ var g = &grammar{ }, { name: "Body", - pos: position{line: 366, col: 1, offset: 9958}, + pos: position{line: 49, col: 1, offset: 1214}, expr: &choiceExpr{ - pos: position{line: 366, col: 9, offset: 9966}, + pos: position{line: 49, col: 9, offset: 1222}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 366, col: 9, offset: 9966}, + pos: position{line: 49, col: 9, offset: 1222}, name: "NonWhitespaceBody", }, &ruleRefExpr{ - pos: position{line: 366, col: 29, offset: 9986}, + pos: position{line: 49, col: 29, offset: 1242}, name: "BraceEnclosedBody", }, }, @@ -786,39 +606,39 @@ var g = &grammar{ }, { name: "NonEmptyBraceEnclosedBody", - pos: position{line: 368, col: 1, offset: 10005}, + pos: position{line: 51, col: 1, offset: 1261}, expr: &actionExpr{ - pos: position{line: 368, col: 30, offset: 10034}, + pos: position{line: 51, col: 30, offset: 1290}, run: (*parser).callonNonEmptyBraceEnclosedBody1, expr: &seqExpr{ - pos: position{line: 368, col: 30, offset: 10034}, + pos: position{line: 51, col: 30, offset: 1290}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 368, col: 30, offset: 10034}, + pos: position{line: 51, col: 30, offset: 1290}, val: "{", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 368, col: 34, offset: 10038}, + pos: position{line: 51, col: 34, offset: 1294}, name: "_", }, &labeledExpr{ - pos: position{line: 368, col: 36, offset: 10040}, + pos: position{line: 51, col: 36, offset: 1296}, label: "val", expr: &zeroOrOneExpr{ - pos: position{line: 368, col: 40, offset: 10044}, + pos: position{line: 51, col: 40, offset: 1300}, expr: &ruleRefExpr{ - pos: position{line: 368, col: 40, offset: 10044}, + pos: position{line: 51, col: 40, offset: 1300}, name: "WhitespaceBody", }, }, }, &ruleRefExpr{ - pos: position{line: 368, col: 56, offset: 10060}, + pos: position{line: 51, col: 56, offset: 1316}, name: "_", }, &litMatcher{ - pos: position{line: 368, col: 58, offset: 10062}, + pos: position{line: 51, col: 58, offset: 1318}, val: "}", ignoreCase: false, }, @@ -828,39 +648,39 @@ var g = &grammar{ }, { name: "BraceEnclosedBody", - pos: position{line: 375, col: 1, offset: 10157}, + pos: position{line: 58, col: 1, offset: 1413}, expr: &actionExpr{ - pos: position{line: 375, col: 22, offset: 10178}, + pos: position{line: 58, col: 22, offset: 1434}, run: (*parser).callonBraceEnclosedBody1, expr: &seqExpr{ - pos: position{line: 375, col: 22, offset: 10178}, + pos: position{line: 58, col: 22, offset: 1434}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 375, col: 22, offset: 10178}, + pos: position{line: 58, col: 22, offset: 1434}, val: "{", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 375, col: 26, offset: 10182}, + pos: position{line: 58, col: 26, offset: 1438}, name: "_", }, &labeledExpr{ - pos: position{line: 375, col: 28, offset: 10184}, + pos: position{line: 58, col: 28, offset: 1440}, label: "val", expr: &zeroOrOneExpr{ - pos: position{line: 375, col: 32, offset: 10188}, + pos: position{line: 58, col: 32, offset: 1444}, expr: &ruleRefExpr{ - pos: position{line: 375, col: 32, offset: 10188}, + pos: position{line: 58, col: 32, offset: 1444}, name: "WhitespaceBody", }, }, }, &ruleRefExpr{ - pos: position{line: 375, col: 48, offset: 10204}, + pos: position{line: 58, col: 48, offset: 1460}, name: "_", }, &litMatcher{ - pos: position{line: 375, col: 50, offset: 10206}, + pos: position{line: 58, col: 50, offset: 1462}, val: "}", ignoreCase: false, }, @@ -870,86 +690,39 @@ var g = &grammar{ }, { name: "WhitespaceBody", - pos: position{line: 389, col: 1, offset: 10558}, + pos: position{line: 62, col: 1, offset: 1529}, expr: &actionExpr{ - pos: position{line: 389, col: 19, offset: 10576}, + pos: position{line: 62, col: 19, offset: 1547}, run: (*parser).callonWhitespaceBody1, expr: &seqExpr{ - pos: position{line: 389, col: 19, offset: 10576}, + pos: position{line: 62, col: 19, offset: 1547}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 389, col: 19, offset: 10576}, + pos: position{line: 62, col: 19, offset: 1547}, label: "head", expr: &ruleRefExpr{ - pos: position{line: 389, col: 24, offset: 10581}, + pos: position{line: 62, col: 24, offset: 1552}, name: "Literal", }, }, &labeledExpr{ - pos: position{line: 389, col: 32, offset: 10589}, + pos: position{line: 62, col: 32, offset: 1560}, label: "tail", expr: &zeroOrMoreExpr{ - pos: position{line: 389, col: 37, offset: 10594}, + pos: position{line: 62, col: 37, offset: 1565}, expr: &seqExpr{ - pos: position{line: 389, col: 38, offset: 10595}, + pos: position{line: 62, col: 38, offset: 1566}, exprs: []interface{}{ - &zeroOrMoreExpr{ - pos: position{line: 389, col: 38, offset: 10595}, - expr: &charClassMatcher{ - pos: position{line: 389, col: 38, offset: 10595}, - val: "[ \\t]", - chars: []rune{' ', '\t'}, - ignoreCase: false, - inverted: false, - }, - }, - &choiceExpr{ - pos: position{line: 389, col: 46, offset: 10603}, - alternatives: []interface{}{ - &seqExpr{ - pos: position{line: 389, col: 47, offset: 10604}, - exprs: []interface{}{ - &litMatcher{ - pos: position{line: 389, col: 47, offset: 10604}, - val: ";", - ignoreCase: false, - }, - &zeroOrOneExpr{ - pos: position{line: 389, col: 51, offset: 10608}, - expr: &ruleRefExpr{ - pos: position{line: 389, col: 51, offset: 10608}, - name: "Comment", - }, - }, - }, - }, - &seqExpr{ - pos: position{line: 389, col: 64, offset: 10621}, - exprs: []interface{}{ - &zeroOrOneExpr{ - pos: position{line: 389, col: 64, offset: 10621}, - expr: &ruleRefExpr{ - pos: position{line: 389, col: 64, offset: 10621}, - name: "Comment", - }, - }, - &charClassMatcher{ - pos: position{line: 389, col: 73, offset: 10630}, - val: "[\\r\\n]", - chars: []rune{'\r', '\n'}, - ignoreCase: false, - inverted: false, - }, - }, - }, - }, + &ruleRefExpr{ + pos: position{line: 62, col: 38, offset: 1566}, + name: "WhitespaceLiteralSeparator", }, &ruleRefExpr{ - pos: position{line: 389, col: 82, offset: 10639}, + pos: position{line: 62, col: 65, offset: 1593}, name: "_", }, &ruleRefExpr{ - pos: position{line: 389, col: 84, offset: 10641}, + pos: position{line: 62, col: 67, offset: 1595}, name: "Literal", }, }, @@ -962,44 +735,43 @@ var g = &grammar{ }, { name: "NonWhitespaceBody", - pos: position{line: 395, col: 1, offset: 10830}, + pos: position{line: 66, col: 1, offset: 1645}, expr: &actionExpr{ - pos: position{line: 395, col: 22, offset: 10851}, + pos: position{line: 66, col: 22, offset: 1666}, run: (*parser).callonNonWhitespaceBody1, expr: &seqExpr{ - pos: position{line: 395, col: 22, offset: 10851}, + pos: position{line: 66, col: 22, offset: 1666}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 395, col: 22, offset: 10851}, + pos: position{line: 66, col: 22, offset: 1666}, label: "head", expr: &ruleRefExpr{ - pos: position{line: 395, col: 27, offset: 10856}, + pos: position{line: 66, col: 27, offset: 1671}, name: "Literal", }, }, &labeledExpr{ - pos: position{line: 395, col: 35, offset: 10864}, + pos: position{line: 66, col: 35, offset: 1679}, label: "tail", expr: &zeroOrMoreExpr{ - pos: position{line: 395, col: 40, offset: 10869}, + pos: position{line: 66, col: 40, offset: 1684}, expr: &seqExpr{ - pos: position{line: 395, col: 42, offset: 10871}, + pos: position{line: 66, col: 42, offset: 1686}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 395, col: 42, offset: 10871}, + pos: position{line: 66, col: 42, offset: 1686}, name: "_", }, - &litMatcher{ - pos: position{line: 395, col: 44, offset: 10873}, - val: ";", - ignoreCase: false, + &ruleRefExpr{ + pos: position{line: 66, col: 44, offset: 1688}, + name: "NonWhitespaceLiteralSeparator", }, &ruleRefExpr{ - pos: position{line: 395, col: 48, offset: 10877}, + pos: position{line: 66, col: 74, offset: 1718}, name: "_", }, &ruleRefExpr{ - pos: position{line: 395, col: 50, offset: 10879}, + pos: position{line: 66, col: 76, offset: 1720}, name: "Literal", }, }, @@ -1010,75 +782,258 @@ var g = &grammar{ }, }, }, + { + name: "WhitespaceLiteralSeparator", + pos: position{line: 70, col: 1, offset: 1770}, + expr: &seqExpr{ + pos: position{line: 70, col: 31, offset: 1800}, + exprs: []interface{}{ + &zeroOrMoreExpr{ + pos: position{line: 70, col: 31, offset: 1800}, + expr: &charClassMatcher{ + pos: position{line: 70, col: 31, offset: 1800}, + val: "[ \\t]", + chars: []rune{' ', '\t'}, + ignoreCase: false, + inverted: false, + }, + }, + &choiceExpr{ + pos: position{line: 70, col: 39, offset: 1808}, + alternatives: []interface{}{ + &seqExpr{ + pos: position{line: 70, col: 40, offset: 1809}, + exprs: []interface{}{ + &ruleRefExpr{ + pos: position{line: 70, col: 40, offset: 1809}, + name: "NonWhitespaceLiteralSeparator", + }, + &zeroOrOneExpr{ + pos: position{line: 70, col: 70, offset: 1839}, + expr: &ruleRefExpr{ + pos: position{line: 70, col: 70, offset: 1839}, + name: "Comment", + }, + }, + }, + }, + &seqExpr{ + pos: position{line: 70, col: 83, offset: 1852}, + exprs: []interface{}{ + &zeroOrOneExpr{ + pos: position{line: 70, col: 83, offset: 1852}, + expr: &ruleRefExpr{ + pos: position{line: 70, col: 83, offset: 1852}, + name: "Comment", + }, + }, + &charClassMatcher{ + pos: position{line: 70, col: 92, offset: 1861}, + val: "[\\r\\n]", + chars: []rune{'\r', '\n'}, + ignoreCase: false, + inverted: false, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "NonWhitespaceLiteralSeparator", + pos: position{line: 72, col: 1, offset: 1871}, + expr: &litMatcher{ + pos: position{line: 72, col: 34, offset: 1904}, + val: ";", + ignoreCase: false, + }, + }, { name: "Literal", - pos: position{line: 399, col: 1, offset: 10954}, + pos: position{line: 74, col: 1, offset: 1909}, expr: &actionExpr{ - pos: position{line: 399, col: 12, offset: 10965}, + pos: position{line: 74, col: 12, offset: 1920}, run: (*parser).callonLiteral1, expr: &seqExpr{ - pos: position{line: 399, col: 12, offset: 10965}, + pos: position{line: 74, col: 12, offset: 1920}, + exprs: []interface{}{ + &labeledExpr{ + pos: position{line: 74, col: 12, offset: 1920}, + label: "negated", + expr: &zeroOrOneExpr{ + pos: position{line: 74, col: 20, offset: 1928}, + expr: &ruleRefExpr{ + pos: position{line: 74, col: 20, offset: 1928}, + name: "NotKeyword", + }, + }, + }, + &labeledExpr{ + pos: position{line: 74, col: 32, offset: 1940}, + label: "value", + expr: &ruleRefExpr{ + pos: position{line: 74, col: 38, offset: 1946}, + name: "LiteralExpr", + }, + }, + &labeledExpr{ + pos: position{line: 74, col: 50, offset: 1958}, + label: "with", + expr: &zeroOrOneExpr{ + pos: position{line: 74, col: 55, offset: 1963}, + expr: &ruleRefExpr{ + pos: position{line: 74, col: 55, offset: 1963}, + name: "WithKeywordList", + }, + }, + }, + }, + }, + }, + }, + { + name: "LiteralExpr", + pos: position{line: 78, col: 1, offset: 2030}, + expr: &actionExpr{ + pos: position{line: 78, col: 16, offset: 2045}, + run: (*parser).callonLiteralExpr1, + expr: &seqExpr{ + pos: position{line: 78, col: 16, offset: 2045}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 399, col: 12, offset: 10965}, - label: "neg", + pos: position{line: 78, col: 16, offset: 2045}, + label: "lhs", + expr: &ruleRefExpr{ + pos: position{line: 78, col: 20, offset: 2049}, + name: "ExprTerm", + }, + }, + &labeledExpr{ + pos: position{line: 78, col: 29, offset: 2058}, + label: "rest", expr: &zeroOrOneExpr{ - pos: position{line: 399, col: 16, offset: 10969}, + pos: position{line: 78, col: 34, offset: 2063}, expr: &seqExpr{ - pos: position{line: 399, col: 18, offset: 10971}, + pos: position{line: 78, col: 36, offset: 2065}, exprs: []interface{}{ - &litMatcher{ - pos: position{line: 399, col: 18, offset: 10971}, - val: "not", - ignoreCase: false, + &ruleRefExpr{ + pos: position{line: 78, col: 36, offset: 2065}, + name: "_", }, &ruleRefExpr{ - pos: position{line: 399, col: 24, offset: 10977}, - name: "ws", + pos: position{line: 78, col: 38, offset: 2067}, + name: "LiteralExprOperator", + }, + &ruleRefExpr{ + pos: position{line: 78, col: 58, offset: 2087}, + name: "_", + }, + &ruleRefExpr{ + pos: position{line: 78, col: 60, offset: 2089}, + name: "ExprTerm", }, }, }, }, }, + }, + }, + }, + }, + { + name: "LiteralExprOperator", + pos: position{line: 82, col: 1, offset: 2163}, + expr: &actionExpr{ + pos: position{line: 82, col: 24, offset: 2186}, + run: (*parser).callonLiteralExprOperator1, + expr: &labeledExpr{ + pos: position{line: 82, col: 24, offset: 2186}, + label: "val", + expr: &choiceExpr{ + pos: position{line: 82, col: 30, offset: 2192}, + alternatives: []interface{}{ + &litMatcher{ + pos: position{line: 82, col: 30, offset: 2192}, + val: ":=", + ignoreCase: false, + }, + &litMatcher{ + pos: position{line: 82, col: 37, offset: 2199}, + val: "=", + ignoreCase: false, + }, + }, + }, + }, + }, + }, + { + name: "NotKeyword", + pos: position{line: 86, col: 1, offset: 2267}, + expr: &actionExpr{ + pos: position{line: 86, col: 15, offset: 2281}, + run: (*parser).callonNotKeyword1, + expr: &labeledExpr{ + pos: position{line: 86, col: 15, offset: 2281}, + label: "val", + expr: &zeroOrOneExpr{ + pos: position{line: 86, col: 19, offset: 2285}, + expr: &seqExpr{ + pos: position{line: 86, col: 20, offset: 2286}, + exprs: []interface{}{ + &litMatcher{ + pos: position{line: 86, col: 20, offset: 2286}, + val: "not", + ignoreCase: false, + }, + &ruleRefExpr{ + pos: position{line: 86, col: 26, offset: 2292}, + name: "ws", + }, + }, + }, + }, + }, + }, + }, + { + name: "WithKeywordList", + pos: position{line: 90, col: 1, offset: 2329}, + expr: &actionExpr{ + pos: position{line: 90, col: 20, offset: 2348}, + run: (*parser).callonWithKeywordList1, + expr: &seqExpr{ + pos: position{line: 90, col: 20, offset: 2348}, + exprs: []interface{}{ + &ruleRefExpr{ + pos: position{line: 90, col: 20, offset: 2348}, + name: "ws", + }, &labeledExpr{ - pos: position{line: 399, col: 30, offset: 10983}, - label: "val", + pos: position{line: 90, col: 23, offset: 2351}, + label: "head", expr: &ruleRefExpr{ - pos: position{line: 399, col: 34, offset: 10987}, - name: "Expr", + pos: position{line: 90, col: 28, offset: 2356}, + name: "WithKeyword", }, }, &labeledExpr{ - pos: position{line: 399, col: 39, offset: 10992}, - label: "with", - expr: &zeroOrOneExpr{ - pos: position{line: 399, col: 44, offset: 10997}, + pos: position{line: 90, col: 40, offset: 2368}, + label: "rest", + expr: &zeroOrMoreExpr{ + pos: position{line: 90, col: 45, offset: 2373}, expr: &seqExpr{ - pos: position{line: 399, col: 46, offset: 10999}, + pos: position{line: 90, col: 47, offset: 2375}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 399, col: 46, offset: 10999}, + pos: position{line: 90, col: 47, offset: 2375}, name: "ws", }, &ruleRefExpr{ - pos: position{line: 399, col: 49, offset: 11002}, - name: "With", - }, - &zeroOrMoreExpr{ - pos: position{line: 399, col: 54, offset: 11007}, - expr: &seqExpr{ - pos: position{line: 399, col: 55, offset: 11008}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 399, col: 55, offset: 11008}, - name: "ws", - }, - &ruleRefExpr{ - pos: position{line: 399, col: 58, offset: 11011}, - name: "With", - }, - }, - }, + pos: position{line: 90, col: 50, offset: 2378}, + name: "WithKeyword", }, }, }, @@ -1089,50 +1044,50 @@ var g = &grammar{ }, }, { - name: "With", - pos: position{line: 427, col: 1, offset: 11682}, + name: "WithKeyword", + pos: position{line: 94, col: 1, offset: 2441}, expr: &actionExpr{ - pos: position{line: 427, col: 9, offset: 11690}, - run: (*parser).callonWith1, + pos: position{line: 94, col: 16, offset: 2456}, + run: (*parser).callonWithKeyword1, expr: &seqExpr{ - pos: position{line: 427, col: 9, offset: 11690}, + pos: position{line: 94, col: 16, offset: 2456}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 427, col: 9, offset: 11690}, + pos: position{line: 94, col: 16, offset: 2456}, val: "with", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 427, col: 16, offset: 11697}, + pos: position{line: 94, col: 23, offset: 2463}, name: "ws", }, &labeledExpr{ - pos: position{line: 427, col: 19, offset: 11700}, + pos: position{line: 94, col: 26, offset: 2466}, label: "target", expr: &ruleRefExpr{ - pos: position{line: 427, col: 26, offset: 11707}, - name: "Term", + pos: position{line: 94, col: 33, offset: 2473}, + name: "ExprTerm", }, }, &ruleRefExpr{ - pos: position{line: 427, col: 31, offset: 11712}, + pos: position{line: 94, col: 42, offset: 2482}, name: "ws", }, &litMatcher{ - pos: position{line: 427, col: 34, offset: 11715}, + pos: position{line: 94, col: 45, offset: 2485}, val: "as", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 427, col: 39, offset: 11720}, + pos: position{line: 94, col: 50, offset: 2490}, name: "ws", }, &labeledExpr{ - pos: position{line: 427, col: 42, offset: 11723}, + pos: position{line: 94, col: 53, offset: 2493}, label: "value", expr: &ruleRefExpr{ - pos: position{line: 427, col: 48, offset: 11729}, - name: "Term", + pos: position{line: 94, col: 59, offset: 2499}, + name: "ExprTerm", }, }, }, @@ -1140,203 +1095,113 @@ var g = &grammar{ }, }, { - name: "Expr", - pos: position{line: 438, col: 1, offset: 11978}, - expr: &choiceExpr{ - pos: position{line: 438, col: 9, offset: 11986}, - alternatives: []interface{}{ - &ruleRefExpr{ - pos: position{line: 438, col: 9, offset: 11986}, - name: "InfixExpr", - }, - &ruleRefExpr{ - pos: position{line: 438, col: 21, offset: 11998}, - name: "PrefixExpr", - }, - &ruleRefExpr{ - pos: position{line: 438, col: 34, offset: 12011}, - name: "Term", - }, - }, - }, - }, - { - name: "InfixExpr", - pos: position{line: 440, col: 1, offset: 12017}, - expr: &choiceExpr{ - pos: position{line: 440, col: 14, offset: 12030}, - alternatives: []interface{}{ - &choiceExpr{ - pos: position{line: 440, col: 15, offset: 12031}, - alternatives: []interface{}{ - &ruleRefExpr{ - pos: position{line: 440, col: 15, offset: 12031}, - name: "InfixCallExpr", - }, - &ruleRefExpr{ - pos: position{line: 440, col: 31, offset: 12047}, - name: "InfixCallExprReverse", - }, - }, - }, - &choiceExpr{ - pos: position{line: 440, col: 56, offset: 12072}, - alternatives: []interface{}{ - &ruleRefExpr{ - pos: position{line: 440, col: 56, offset: 12072}, - name: "InfixArithExpr", - }, - &ruleRefExpr{ - pos: position{line: 440, col: 73, offset: 12089}, - name: "InfixArithExprReverse", - }, - }, - }, - &ruleRefExpr{ - pos: position{line: 440, col: 98, offset: 12114}, - name: "InfixRelationExpr", - }, - }, - }, - }, - { - name: "InfixCallExpr", - pos: position{line: 442, col: 1, offset: 12133}, + name: "ExprTerm", + pos: position{line: 98, col: 1, offset: 2575}, expr: &actionExpr{ - pos: position{line: 442, col: 18, offset: 12150}, - run: (*parser).callonInfixCallExpr1, + pos: position{line: 98, col: 13, offset: 2587}, + run: (*parser).callonExprTerm1, expr: &seqExpr{ - pos: position{line: 442, col: 18, offset: 12150}, + pos: position{line: 98, col: 13, offset: 2587}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 442, col: 18, offset: 12150}, - label: "output", + pos: position{line: 98, col: 13, offset: 2587}, + label: "lhs", expr: &ruleRefExpr{ - pos: position{line: 442, col: 25, offset: 12157}, - name: "Term", + pos: position{line: 98, col: 17, offset: 2591}, + name: "RelationExpr", }, }, - &ruleRefExpr{ - pos: position{line: 442, col: 30, offset: 12162}, - name: "_", - }, - &litMatcher{ - pos: position{line: 442, col: 32, offset: 12164}, - val: "=", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 442, col: 36, offset: 12168}, - name: "_", - }, &labeledExpr{ - pos: position{line: 442, col: 38, offset: 12170}, - label: "operator", - expr: &ruleRefExpr{ - pos: position{line: 442, col: 47, offset: 12179}, - name: "Operator", - }, - }, - &ruleRefExpr{ - pos: position{line: 442, col: 56, offset: 12188}, - name: "_", - }, - &litMatcher{ - pos: position{line: 442, col: 58, offset: 12190}, - val: "(", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 442, col: 62, offset: 12194}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 442, col: 64, offset: 12196}, - label: "args", - expr: &ruleRefExpr{ - pos: position{line: 442, col: 69, offset: 12201}, - name: "Args", + pos: position{line: 98, col: 30, offset: 2604}, + label: "rest", + expr: &zeroOrMoreExpr{ + pos: position{line: 98, col: 35, offset: 2609}, + expr: &seqExpr{ + pos: position{line: 98, col: 37, offset: 2611}, + exprs: []interface{}{ + &ruleRefExpr{ + pos: position{line: 98, col: 37, offset: 2611}, + name: "_", + }, + &ruleRefExpr{ + pos: position{line: 98, col: 39, offset: 2613}, + name: "RelationOperator", + }, + &ruleRefExpr{ + pos: position{line: 98, col: 56, offset: 2630}, + name: "_", + }, + &ruleRefExpr{ + pos: position{line: 98, col: 58, offset: 2632}, + name: "RelationExpr", + }, + }, + }, }, }, - &ruleRefExpr{ - pos: position{line: 442, col: 74, offset: 12206}, - name: "_", - }, - &litMatcher{ - pos: position{line: 442, col: 76, offset: 12208}, - val: ")", - ignoreCase: false, - }, }, }, }, }, { - name: "InfixCallExprReverse", - pos: position{line: 446, col: 1, offset: 12270}, + name: "ExprTermPairList", + pos: position{line: 102, col: 1, offset: 2708}, expr: &actionExpr{ - pos: position{line: 446, col: 25, offset: 12294}, - run: (*parser).callonInfixCallExprReverse1, + pos: position{line: 102, col: 21, offset: 2728}, + run: (*parser).callonExprTermPairList1, expr: &seqExpr{ - pos: position{line: 446, col: 25, offset: 12294}, + pos: position{line: 102, col: 21, offset: 2728}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 446, col: 25, offset: 12294}, - label: "operator", - expr: &ruleRefExpr{ - pos: position{line: 446, col: 34, offset: 12303}, - name: "Operator", + pos: position{line: 102, col: 21, offset: 2728}, + label: "head", + expr: &zeroOrOneExpr{ + pos: position{line: 102, col: 26, offset: 2733}, + expr: &ruleRefExpr{ + pos: position{line: 102, col: 26, offset: 2733}, + name: "ExprTermPair", + }, }, }, - &ruleRefExpr{ - pos: position{line: 446, col: 43, offset: 12312}, - name: "_", - }, - &litMatcher{ - pos: position{line: 446, col: 45, offset: 12314}, - val: "(", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 446, col: 49, offset: 12318}, - name: "_", - }, &labeledExpr{ - pos: position{line: 446, col: 51, offset: 12320}, - label: "args", - expr: &ruleRefExpr{ - pos: position{line: 446, col: 56, offset: 12325}, - name: "Args", + pos: position{line: 102, col: 40, offset: 2747}, + label: "tail", + expr: &zeroOrMoreExpr{ + pos: position{line: 102, col: 45, offset: 2752}, + expr: &seqExpr{ + pos: position{line: 102, col: 47, offset: 2754}, + exprs: []interface{}{ + &ruleRefExpr{ + pos: position{line: 102, col: 47, offset: 2754}, + name: "_", + }, + &litMatcher{ + pos: position{line: 102, col: 49, offset: 2756}, + val: ",", + ignoreCase: false, + }, + &ruleRefExpr{ + pos: position{line: 102, col: 53, offset: 2760}, + name: "_", + }, + &ruleRefExpr{ + pos: position{line: 102, col: 55, offset: 2762}, + name: "ExprTermPair", + }, + }, + }, }, }, &ruleRefExpr{ - pos: position{line: 446, col: 61, offset: 12330}, + pos: position{line: 102, col: 71, offset: 2778}, name: "_", }, - &litMatcher{ - pos: position{line: 446, col: 63, offset: 12332}, - val: ")", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 446, col: 67, offset: 12336}, - name: "_", - }, - &litMatcher{ - pos: position{line: 446, col: 69, offset: 12338}, - val: "=", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 446, col: 73, offset: 12342}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 446, col: 75, offset: 12344}, - label: "output", - expr: &ruleRefExpr{ - pos: position{line: 446, col: 82, offset: 12351}, - name: "Term", + &zeroOrOneExpr{ + pos: position{line: 102, col: 73, offset: 2780}, + expr: &litMatcher{ + pos: position{line: 102, col: 73, offset: 2780}, + val: ",", + ignoreCase: false, }, }, }, @@ -1344,65 +1209,64 @@ var g = &grammar{ }, }, { - name: "InfixArithExpr", - pos: position{line: 450, col: 1, offset: 12414}, + name: "ExprTermList", + pos: position{line: 106, col: 1, offset: 2834}, expr: &actionExpr{ - pos: position{line: 450, col: 19, offset: 12432}, - run: (*parser).callonInfixArithExpr1, + pos: position{line: 106, col: 17, offset: 2850}, + run: (*parser).callonExprTermList1, expr: &seqExpr{ - pos: position{line: 450, col: 19, offset: 12432}, + pos: position{line: 106, col: 17, offset: 2850}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 450, col: 19, offset: 12432}, - label: "output", - expr: &ruleRefExpr{ - pos: position{line: 450, col: 26, offset: 12439}, - name: "Term", - }, - }, - &ruleRefExpr{ - pos: position{line: 450, col: 31, offset: 12444}, - name: "_", - }, - &litMatcher{ - pos: position{line: 450, col: 33, offset: 12446}, - val: "=", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 450, col: 37, offset: 12450}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 450, col: 39, offset: 12452}, - label: "left", - expr: &ruleRefExpr{ - pos: position{line: 450, col: 44, offset: 12457}, - name: "Term", + pos: position{line: 106, col: 17, offset: 2850}, + label: "head", + expr: &zeroOrOneExpr{ + pos: position{line: 106, col: 22, offset: 2855}, + expr: &ruleRefExpr{ + pos: position{line: 106, col: 22, offset: 2855}, + name: "ExprTerm", + }, }, }, - &ruleRefExpr{ - pos: position{line: 450, col: 49, offset: 12462}, - name: "_", - }, &labeledExpr{ - pos: position{line: 450, col: 51, offset: 12464}, - label: "operator", - expr: &ruleRefExpr{ - pos: position{line: 450, col: 60, offset: 12473}, - name: "ArithInfixOp", + pos: position{line: 106, col: 32, offset: 2865}, + label: "tail", + expr: &zeroOrMoreExpr{ + pos: position{line: 106, col: 37, offset: 2870}, + expr: &seqExpr{ + pos: position{line: 106, col: 39, offset: 2872}, + exprs: []interface{}{ + &ruleRefExpr{ + pos: position{line: 106, col: 39, offset: 2872}, + name: "_", + }, + &litMatcher{ + pos: position{line: 106, col: 41, offset: 2874}, + val: ",", + ignoreCase: false, + }, + &ruleRefExpr{ + pos: position{line: 106, col: 45, offset: 2878}, + name: "_", + }, + &ruleRefExpr{ + pos: position{line: 106, col: 47, offset: 2880}, + name: "ExprTerm", + }, + }, + }, }, }, &ruleRefExpr{ - pos: position{line: 450, col: 73, offset: 12486}, + pos: position{line: 106, col: 59, offset: 2892}, name: "_", }, - &labeledExpr{ - pos: position{line: 450, col: 75, offset: 12488}, - label: "right", - expr: &ruleRefExpr{ - pos: position{line: 450, col: 81, offset: 12494}, - name: "Term", + &zeroOrOneExpr{ + pos: position{line: 106, col: 61, offset: 2894}, + expr: &litMatcher{ + pos: position{line: 106, col: 61, offset: 2894}, + val: ",", + ignoreCase: false, }, }, }, @@ -1410,65 +1274,41 @@ var g = &grammar{ }, }, { - name: "InfixArithExprReverse", - pos: position{line: 454, col: 1, offset: 12586}, + name: "ExprTermPair", + pos: position{line: 110, col: 1, offset: 2945}, expr: &actionExpr{ - pos: position{line: 454, col: 26, offset: 12611}, - run: (*parser).callonInfixArithExprReverse1, + pos: position{line: 110, col: 17, offset: 2961}, + run: (*parser).callonExprTermPair1, expr: &seqExpr{ - pos: position{line: 454, col: 26, offset: 12611}, + pos: position{line: 110, col: 17, offset: 2961}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 454, col: 26, offset: 12611}, - label: "left", - expr: &ruleRefExpr{ - pos: position{line: 454, col: 31, offset: 12616}, - name: "Term", - }, - }, - &ruleRefExpr{ - pos: position{line: 454, col: 36, offset: 12621}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 454, col: 38, offset: 12623}, - label: "operator", - expr: &ruleRefExpr{ - pos: position{line: 454, col: 47, offset: 12632}, - name: "ArithInfixOp", - }, - }, - &ruleRefExpr{ - pos: position{line: 454, col: 60, offset: 12645}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 454, col: 62, offset: 12647}, - label: "right", + pos: position{line: 110, col: 17, offset: 2961}, + label: "key", expr: &ruleRefExpr{ - pos: position{line: 454, col: 68, offset: 12653}, - name: "Term", + pos: position{line: 110, col: 21, offset: 2965}, + name: "ExprTerm", }, }, &ruleRefExpr{ - pos: position{line: 454, col: 73, offset: 12658}, + pos: position{line: 110, col: 30, offset: 2974}, name: "_", }, &litMatcher{ - pos: position{line: 454, col: 75, offset: 12660}, - val: "=", + pos: position{line: 110, col: 32, offset: 2976}, + val: ":", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 454, col: 79, offset: 12664}, + pos: position{line: 110, col: 36, offset: 2980}, name: "_", }, &labeledExpr{ - pos: position{line: 454, col: 81, offset: 12666}, - label: "output", + pos: position{line: 110, col: 38, offset: 2982}, + label: "value", expr: &ruleRefExpr{ - pos: position{line: 454, col: 88, offset: 12673}, - name: "Term", + pos: position{line: 110, col: 44, offset: 2988}, + name: "ExprTerm", }, }, }, @@ -1476,50 +1316,45 @@ var g = &grammar{ }, }, { - name: "ArithInfixOp", - pos: position{line: 458, col: 1, offset: 12765}, + name: "RelationOperator", + pos: position{line: 114, col: 1, offset: 3042}, expr: &actionExpr{ - pos: position{line: 458, col: 17, offset: 12781}, - run: (*parser).callonArithInfixOp1, + pos: position{line: 114, col: 21, offset: 3062}, + run: (*parser).callonRelationOperator1, expr: &labeledExpr{ - pos: position{line: 458, col: 17, offset: 12781}, + pos: position{line: 114, col: 21, offset: 3062}, label: "val", expr: &choiceExpr{ - pos: position{line: 458, col: 22, offset: 12786}, + pos: position{line: 114, col: 26, offset: 3067}, alternatives: []interface{}{ &litMatcher{ - pos: position{line: 458, col: 22, offset: 12786}, - val: "+", - ignoreCase: false, - }, - &litMatcher{ - pos: position{line: 458, col: 28, offset: 12792}, - val: "-", + pos: position{line: 114, col: 26, offset: 3067}, + val: "==", ignoreCase: false, }, &litMatcher{ - pos: position{line: 458, col: 34, offset: 12798}, - val: "*", + pos: position{line: 114, col: 33, offset: 3074}, + val: "!=", ignoreCase: false, }, &litMatcher{ - pos: position{line: 458, col: 40, offset: 12804}, - val: "/", + pos: position{line: 114, col: 40, offset: 3081}, + val: "<=", ignoreCase: false, }, &litMatcher{ - pos: position{line: 458, col: 46, offset: 12810}, - val: "&", + pos: position{line: 114, col: 47, offset: 3088}, + val: ">=", ignoreCase: false, }, &litMatcher{ - pos: position{line: 458, col: 52, offset: 12816}, - val: "|", + pos: position{line: 114, col: 54, offset: 3095}, + val: ">", ignoreCase: false, }, &litMatcher{ - pos: position{line: 458, col: 58, offset: 12822}, - val: "-", + pos: position{line: 114, col: 60, offset: 3101}, + val: "<", ignoreCase: false, }, }, @@ -1528,44 +1363,180 @@ var g = &grammar{ }, }, { - name: "InfixRelationExpr", - pos: position{line: 470, col: 1, offset: 13096}, + name: "RelationExpr", + pos: position{line: 118, col: 1, offset: 3168}, expr: &actionExpr{ - pos: position{line: 470, col: 22, offset: 13117}, - run: (*parser).callonInfixRelationExpr1, + pos: position{line: 118, col: 17, offset: 3184}, + run: (*parser).callonRelationExpr1, expr: &seqExpr{ - pos: position{line: 470, col: 22, offset: 13117}, + pos: position{line: 118, col: 17, offset: 3184}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 470, col: 22, offset: 13117}, - label: "left", + pos: position{line: 118, col: 17, offset: 3184}, + label: "lhs", expr: &ruleRefExpr{ - pos: position{line: 470, col: 27, offset: 13122}, - name: "Term", + pos: position{line: 118, col: 21, offset: 3188}, + name: "BitwiseOrExpr", }, }, - &ruleRefExpr{ - pos: position{line: 470, col: 32, offset: 13127}, - name: "_", + &labeledExpr{ + pos: position{line: 118, col: 35, offset: 3202}, + label: "rest", + expr: &zeroOrMoreExpr{ + pos: position{line: 118, col: 40, offset: 3207}, + expr: &seqExpr{ + pos: position{line: 118, col: 42, offset: 3209}, + exprs: []interface{}{ + &ruleRefExpr{ + pos: position{line: 118, col: 42, offset: 3209}, + name: "_", + }, + &ruleRefExpr{ + pos: position{line: 118, col: 44, offset: 3211}, + name: "BitwiseOrOperator", + }, + &ruleRefExpr{ + pos: position{line: 118, col: 62, offset: 3229}, + name: "_", + }, + &ruleRefExpr{ + pos: position{line: 118, col: 64, offset: 3231}, + name: "BitwiseOrExpr", + }, + }, + }, + }, }, + }, + }, + }, + }, + { + name: "BitwiseOrOperator", + pos: position{line: 122, col: 1, offset: 3307}, + expr: &actionExpr{ + pos: position{line: 122, col: 22, offset: 3328}, + run: (*parser).callonBitwiseOrOperator1, + expr: &labeledExpr{ + pos: position{line: 122, col: 22, offset: 3328}, + label: "val", + expr: &litMatcher{ + pos: position{line: 122, col: 26, offset: 3332}, + val: "|", + ignoreCase: false, + }, + }, + }, + }, + { + name: "BitwiseOrExpr", + pos: position{line: 126, col: 1, offset: 3398}, + expr: &actionExpr{ + pos: position{line: 126, col: 18, offset: 3415}, + run: (*parser).callonBitwiseOrExpr1, + expr: &seqExpr{ + pos: position{line: 126, col: 18, offset: 3415}, + exprs: []interface{}{ &labeledExpr{ - pos: position{line: 470, col: 34, offset: 13129}, - label: "operator", + pos: position{line: 126, col: 18, offset: 3415}, + label: "lhs", expr: &ruleRefExpr{ - pos: position{line: 470, col: 43, offset: 13138}, - name: "InfixRelationOp", + pos: position{line: 126, col: 22, offset: 3419}, + name: "BitwiseAndExpr", }, }, - &ruleRefExpr{ - pos: position{line: 470, col: 59, offset: 13154}, - name: "_", + &labeledExpr{ + pos: position{line: 126, col: 37, offset: 3434}, + label: "rest", + expr: &zeroOrMoreExpr{ + pos: position{line: 126, col: 42, offset: 3439}, + expr: &seqExpr{ + pos: position{line: 126, col: 44, offset: 3441}, + exprs: []interface{}{ + &ruleRefExpr{ + pos: position{line: 126, col: 44, offset: 3441}, + name: "_", + }, + &ruleRefExpr{ + pos: position{line: 126, col: 46, offset: 3443}, + name: "BitwiseAndOperator", + }, + &ruleRefExpr{ + pos: position{line: 126, col: 65, offset: 3462}, + name: "_", + }, + &ruleRefExpr{ + pos: position{line: 126, col: 67, offset: 3464}, + name: "BitwiseAndExpr", + }, + }, + }, + }, }, + }, + }, + }, + }, + { + name: "BitwiseAndOperator", + pos: position{line: 130, col: 1, offset: 3541}, + expr: &actionExpr{ + pos: position{line: 130, col: 23, offset: 3563}, + run: (*parser).callonBitwiseAndOperator1, + expr: &labeledExpr{ + pos: position{line: 130, col: 23, offset: 3563}, + label: "val", + expr: &litMatcher{ + pos: position{line: 130, col: 27, offset: 3567}, + val: "&", + ignoreCase: false, + }, + }, + }, + }, + { + name: "BitwiseAndExpr", + pos: position{line: 134, col: 1, offset: 3633}, + expr: &actionExpr{ + pos: position{line: 134, col: 19, offset: 3651}, + run: (*parser).callonBitwiseAndExpr1, + expr: &seqExpr{ + pos: position{line: 134, col: 19, offset: 3651}, + exprs: []interface{}{ &labeledExpr{ - pos: position{line: 470, col: 61, offset: 13156}, - label: "right", + pos: position{line: 134, col: 19, offset: 3651}, + label: "lhs", expr: &ruleRefExpr{ - pos: position{line: 470, col: 67, offset: 13162}, - name: "Term", + pos: position{line: 134, col: 23, offset: 3655}, + name: "ArithExpr", + }, + }, + &labeledExpr{ + pos: position{line: 134, col: 33, offset: 3665}, + label: "rest", + expr: &zeroOrMoreExpr{ + pos: position{line: 134, col: 38, offset: 3670}, + expr: &seqExpr{ + pos: position{line: 134, col: 40, offset: 3672}, + exprs: []interface{}{ + &ruleRefExpr{ + pos: position{line: 134, col: 40, offset: 3672}, + name: "_", + }, + &ruleRefExpr{ + pos: position{line: 134, col: 42, offset: 3674}, + name: "ArithOperator", + }, + &ruleRefExpr{ + pos: position{line: 134, col: 56, offset: 3688}, + name: "_", + }, + &ruleRefExpr{ + pos: position{line: 134, col: 58, offset: 3690}, + name: "ArithExpr", + }, + }, + }, }, }, }, @@ -1573,45 +1544,101 @@ var g = &grammar{ }, }, { - name: "InfixRelationOp", - pos: position{line: 481, col: 1, offset: 13340}, + name: "ArithOperator", + pos: position{line: 138, col: 1, offset: 3762}, expr: &actionExpr{ - pos: position{line: 481, col: 20, offset: 13359}, - run: (*parser).callonInfixRelationOp1, + pos: position{line: 138, col: 18, offset: 3779}, + run: (*parser).callonArithOperator1, expr: &labeledExpr{ - pos: position{line: 481, col: 20, offset: 13359}, + pos: position{line: 138, col: 18, offset: 3779}, label: "val", expr: &choiceExpr{ - pos: position{line: 481, col: 25, offset: 13364}, + pos: position{line: 138, col: 23, offset: 3784}, alternatives: []interface{}{ &litMatcher{ - pos: position{line: 481, col: 25, offset: 13364}, - val: "=", + pos: position{line: 138, col: 23, offset: 3784}, + val: "+", ignoreCase: false, }, &litMatcher{ - pos: position{line: 481, col: 31, offset: 13370}, - val: "!=", + pos: position{line: 138, col: 29, offset: 3790}, + val: "-", ignoreCase: false, }, - &litMatcher{ - pos: position{line: 481, col: 38, offset: 13377}, - val: "<=", - ignoreCase: false, + }, + }, + }, + }, + }, + { + name: "ArithExpr", + pos: position{line: 142, col: 1, offset: 3857}, + expr: &actionExpr{ + pos: position{line: 142, col: 14, offset: 3870}, + run: (*parser).callonArithExpr1, + expr: &seqExpr{ + pos: position{line: 142, col: 14, offset: 3870}, + exprs: []interface{}{ + &labeledExpr{ + pos: position{line: 142, col: 14, offset: 3870}, + label: "lhs", + expr: &ruleRefExpr{ + pos: position{line: 142, col: 18, offset: 3874}, + name: "FactorExpr", }, - &litMatcher{ - pos: position{line: 481, col: 45, offset: 13384}, - val: ">=", - ignoreCase: false, + }, + &labeledExpr{ + pos: position{line: 142, col: 29, offset: 3885}, + label: "rest", + expr: &zeroOrMoreExpr{ + pos: position{line: 142, col: 34, offset: 3890}, + expr: &seqExpr{ + pos: position{line: 142, col: 36, offset: 3892}, + exprs: []interface{}{ + &ruleRefExpr{ + pos: position{line: 142, col: 36, offset: 3892}, + name: "_", + }, + &ruleRefExpr{ + pos: position{line: 142, col: 38, offset: 3894}, + name: "FactorOperator", + }, + &ruleRefExpr{ + pos: position{line: 142, col: 53, offset: 3909}, + name: "_", + }, + &ruleRefExpr{ + pos: position{line: 142, col: 55, offset: 3911}, + name: "FactorExpr", + }, + }, + }, }, + }, + }, + }, + }, + }, + { + name: "FactorOperator", + pos: position{line: 146, col: 1, offset: 3985}, + expr: &actionExpr{ + pos: position{line: 146, col: 19, offset: 4003}, + run: (*parser).callonFactorOperator1, + expr: &labeledExpr{ + pos: position{line: 146, col: 19, offset: 4003}, + label: "val", + expr: &choiceExpr{ + pos: position{line: 146, col: 24, offset: 4008}, + alternatives: []interface{}{ &litMatcher{ - pos: position{line: 481, col: 52, offset: 13391}, - val: "<", + pos: position{line: 146, col: 24, offset: 4008}, + val: "*", ignoreCase: false, }, &litMatcher{ - pos: position{line: 481, col: 58, offset: 13397}, - val: ">", + pos: position{line: 146, col: 30, offset: 4014}, + val: "/", ignoreCase: false, }, }, @@ -1620,94 +1647,110 @@ var g = &grammar{ }, }, { - name: "PrefixExpr", - pos: position{line: 493, col: 1, offset: 13671}, + name: "FactorExpr", + pos: position{line: 150, col: 1, offset: 4080}, expr: &choiceExpr{ - pos: position{line: 493, col: 15, offset: 13685}, + pos: position{line: 150, col: 15, offset: 4094}, alternatives: []interface{}{ - &ruleRefExpr{ - pos: position{line: 493, col: 15, offset: 13685}, - name: "SetEmpty", + &actionExpr{ + pos: position{line: 150, col: 15, offset: 4094}, + run: (*parser).callonFactorExpr2, + expr: &seqExpr{ + pos: position{line: 150, col: 17, offset: 4096}, + exprs: []interface{}{ + &litMatcher{ + pos: position{line: 150, col: 17, offset: 4096}, + val: "(", + ignoreCase: false, + }, + &ruleRefExpr{ + pos: position{line: 150, col: 21, offset: 4100}, + name: "_", + }, + &labeledExpr{ + pos: position{line: 150, col: 23, offset: 4102}, + label: "expr", + expr: &ruleRefExpr{ + pos: position{line: 150, col: 28, offset: 4107}, + name: "ExprTerm", + }, + }, + &ruleRefExpr{ + pos: position{line: 150, col: 37, offset: 4116}, + name: "_", + }, + &litMatcher{ + pos: position{line: 150, col: 39, offset: 4118}, + val: ")", + ignoreCase: false, + }, + }, + }, }, - &ruleRefExpr{ - pos: position{line: 493, col: 26, offset: 13696}, - name: "Call", + &actionExpr{ + pos: position{line: 152, col: 5, offset: 4151}, + run: (*parser).callonFactorExpr10, + expr: &labeledExpr{ + pos: position{line: 152, col: 5, offset: 4151}, + label: "term", + expr: &ruleRefExpr{ + pos: position{line: 152, col: 10, offset: 4156}, + name: "Term", + }, + }, }, }, }, }, { name: "Call", - pos: position{line: 495, col: 1, offset: 13702}, + pos: position{line: 156, col: 1, offset: 4187}, expr: &actionExpr{ - pos: position{line: 495, col: 9, offset: 13710}, + pos: position{line: 156, col: 9, offset: 4195}, run: (*parser).callonCall1, expr: &seqExpr{ - pos: position{line: 495, col: 9, offset: 13710}, + pos: position{line: 156, col: 9, offset: 4195}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 495, col: 9, offset: 13710}, - label: "name", - expr: &ruleRefExpr{ - pos: position{line: 495, col: 14, offset: 13715}, - name: "Operator", + pos: position{line: 156, col: 9, offset: 4195}, + label: "operator", + expr: &choiceExpr{ + pos: position{line: 156, col: 19, offset: 4205}, + alternatives: []interface{}{ + &ruleRefExpr{ + pos: position{line: 156, col: 19, offset: 4205}, + name: "Ref", + }, + &ruleRefExpr{ + pos: position{line: 156, col: 25, offset: 4211}, + name: "Var", + }, + }, }, }, &litMatcher{ - pos: position{line: 495, col: 23, offset: 13724}, + pos: position{line: 156, col: 30, offset: 4216}, val: "(", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 495, col: 27, offset: 13728}, + pos: position{line: 156, col: 34, offset: 4220}, name: "_", }, &labeledExpr{ - pos: position{line: 495, col: 29, offset: 13730}, - label: "head", - expr: &zeroOrOneExpr{ - pos: position{line: 495, col: 34, offset: 13735}, - expr: &ruleRefExpr{ - pos: position{line: 495, col: 34, offset: 13735}, - name: "Term", - }, - }, - }, - &labeledExpr{ - pos: position{line: 495, col: 40, offset: 13741}, - label: "tail", - expr: &zeroOrMoreExpr{ - pos: position{line: 495, col: 45, offset: 13746}, - expr: &seqExpr{ - pos: position{line: 495, col: 47, offset: 13748}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 495, col: 47, offset: 13748}, - name: "_", - }, - &litMatcher{ - pos: position{line: 495, col: 49, offset: 13750}, - val: ",", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 495, col: 53, offset: 13754}, - name: "_", - }, - &ruleRefExpr{ - pos: position{line: 495, col: 55, offset: 13756}, - name: "Term", - }, - }, - }, + pos: position{line: 156, col: 36, offset: 4222}, + label: "args", + expr: &ruleRefExpr{ + pos: position{line: 156, col: 41, offset: 4227}, + name: "ExprTermList", }, }, &ruleRefExpr{ - pos: position{line: 495, col: 63, offset: 13764}, + pos: position{line: 156, col: 54, offset: 4240}, name: "_", }, &litMatcher{ - pos: position{line: 495, col: 66, offset: 13767}, + pos: position{line: 156, col: 56, offset: 4242}, val: ")", ignoreCase: false, }, @@ -1715,61 +1758,40 @@ var g = &grammar{ }, }, }, - { - name: "Operator", - pos: position{line: 513, col: 1, offset: 14201}, - expr: &actionExpr{ - pos: position{line: 513, col: 13, offset: 14213}, - run: (*parser).callonOperator1, - expr: &labeledExpr{ - pos: position{line: 513, col: 13, offset: 14213}, - label: "val", - expr: &choiceExpr{ - pos: position{line: 513, col: 18, offset: 14218}, - alternatives: []interface{}{ - &ruleRefExpr{ - pos: position{line: 513, col: 18, offset: 14218}, - name: "Ref", - }, - &ruleRefExpr{ - pos: position{line: 513, col: 24, offset: 14224}, - name: "Var", - }, - }, - }, - }, - }, - }, { name: "Term", - pos: position{line: 525, col: 1, offset: 14455}, + pos: position{line: 160, col: 1, offset: 4307}, expr: &actionExpr{ - pos: position{line: 525, col: 9, offset: 14463}, + pos: position{line: 160, col: 9, offset: 4315}, run: (*parser).callonTerm1, expr: &labeledExpr{ - pos: position{line: 525, col: 9, offset: 14463}, + pos: position{line: 160, col: 9, offset: 4315}, label: "val", expr: &choiceExpr{ - pos: position{line: 525, col: 15, offset: 14469}, + pos: position{line: 160, col: 15, offset: 4321}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 525, col: 15, offset: 14469}, + pos: position{line: 160, col: 15, offset: 4321}, name: "Comprehension", }, &ruleRefExpr{ - pos: position{line: 525, col: 31, offset: 14485}, + pos: position{line: 160, col: 31, offset: 4337}, name: "Composite", }, &ruleRefExpr{ - pos: position{line: 525, col: 43, offset: 14497}, + pos: position{line: 160, col: 43, offset: 4349}, name: "Scalar", }, &ruleRefExpr{ - pos: position{line: 525, col: 52, offset: 14506}, + pos: position{line: 160, col: 52, offset: 4358}, + name: "Call", + }, + &ruleRefExpr{ + pos: position{line: 160, col: 59, offset: 4365}, name: "Ref", }, &ruleRefExpr{ - pos: position{line: 525, col: 58, offset: 14512}, + pos: position{line: 160, col: 65, offset: 4371}, name: "Var", }, }, @@ -1777,22 +1799,64 @@ var g = &grammar{ }, }, }, + { + name: "TermPair", + pos: position{line: 164, col: 1, offset: 4402}, + expr: &actionExpr{ + pos: position{line: 164, col: 13, offset: 4414}, + run: (*parser).callonTermPair1, + expr: &seqExpr{ + pos: position{line: 164, col: 13, offset: 4414}, + exprs: []interface{}{ + &labeledExpr{ + pos: position{line: 164, col: 13, offset: 4414}, + label: "key", + expr: &ruleRefExpr{ + pos: position{line: 164, col: 17, offset: 4418}, + name: "Term", + }, + }, + &ruleRefExpr{ + pos: position{line: 164, col: 22, offset: 4423}, + name: "_", + }, + &litMatcher{ + pos: position{line: 164, col: 24, offset: 4425}, + val: ":", + ignoreCase: false, + }, + &ruleRefExpr{ + pos: position{line: 164, col: 28, offset: 4429}, + name: "_", + }, + &labeledExpr{ + pos: position{line: 164, col: 30, offset: 4431}, + label: "value", + expr: &ruleRefExpr{ + pos: position{line: 164, col: 36, offset: 4437}, + name: "Term", + }, + }, + }, + }, + }, + }, { name: "Comprehension", - pos: position{line: 529, col: 1, offset: 14543}, + pos: position{line: 168, col: 1, offset: 4487}, expr: &choiceExpr{ - pos: position{line: 529, col: 18, offset: 14560}, + pos: position{line: 168, col: 18, offset: 4504}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 529, col: 18, offset: 14560}, + pos: position{line: 168, col: 18, offset: 4504}, name: "ArrayComprehension", }, &ruleRefExpr{ - pos: position{line: 529, col: 39, offset: 14581}, + pos: position{line: 168, col: 39, offset: 4525}, name: "ObjectComprehension", }, &ruleRefExpr{ - pos: position{line: 529, col: 61, offset: 14603}, + pos: position{line: 168, col: 61, offset: 4547}, name: "SetComprehension", }, }, @@ -1800,57 +1864,57 @@ var g = &grammar{ }, { name: "ArrayComprehension", - pos: position{line: 531, col: 1, offset: 14621}, + pos: position{line: 170, col: 1, offset: 4565}, expr: &actionExpr{ - pos: position{line: 531, col: 23, offset: 14643}, + pos: position{line: 170, col: 23, offset: 4587}, run: (*parser).callonArrayComprehension1, expr: &seqExpr{ - pos: position{line: 531, col: 23, offset: 14643}, + pos: position{line: 170, col: 23, offset: 4587}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 531, col: 23, offset: 14643}, + pos: position{line: 170, col: 23, offset: 4587}, val: "[", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 531, col: 27, offset: 14647}, + pos: position{line: 170, col: 27, offset: 4591}, name: "_", }, &labeledExpr{ - pos: position{line: 531, col: 29, offset: 14649}, - label: "term", + pos: position{line: 170, col: 29, offset: 4593}, + label: "head", expr: &ruleRefExpr{ - pos: position{line: 531, col: 34, offset: 14654}, + pos: position{line: 170, col: 34, offset: 4598}, name: "Term", }, }, &ruleRefExpr{ - pos: position{line: 531, col: 39, offset: 14659}, + pos: position{line: 170, col: 39, offset: 4603}, name: "_", }, &litMatcher{ - pos: position{line: 531, col: 41, offset: 14661}, + pos: position{line: 170, col: 41, offset: 4605}, val: "|", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 531, col: 45, offset: 14665}, + pos: position{line: 170, col: 45, offset: 4609}, name: "_", }, &labeledExpr{ - pos: position{line: 531, col: 47, offset: 14667}, + pos: position{line: 170, col: 47, offset: 4611}, label: "body", expr: &ruleRefExpr{ - pos: position{line: 531, col: 52, offset: 14672}, + pos: position{line: 170, col: 52, offset: 4616}, name: "WhitespaceBody", }, }, &ruleRefExpr{ - pos: position{line: 531, col: 67, offset: 14687}, + pos: position{line: 170, col: 67, offset: 4631}, name: "_", }, &litMatcher{ - pos: position{line: 531, col: 69, offset: 14689}, + pos: position{line: 170, col: 69, offset: 4633}, val: "]", ignoreCase: false, }, @@ -1860,78 +1924,57 @@ var g = &grammar{ }, { name: "ObjectComprehension", - pos: position{line: 537, col: 1, offset: 14814}, + pos: position{line: 174, col: 1, offset: 4708}, expr: &actionExpr{ - pos: position{line: 537, col: 24, offset: 14837}, + pos: position{line: 174, col: 24, offset: 4731}, run: (*parser).callonObjectComprehension1, expr: &seqExpr{ - pos: position{line: 537, col: 24, offset: 14837}, + pos: position{line: 174, col: 24, offset: 4731}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 537, col: 24, offset: 14837}, + pos: position{line: 174, col: 24, offset: 4731}, val: "{", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 537, col: 28, offset: 14841}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 537, col: 30, offset: 14843}, - label: "key", - expr: &ruleRefExpr{ - pos: position{line: 537, col: 34, offset: 14847}, - name: "Key", - }, - }, - &ruleRefExpr{ - pos: position{line: 537, col: 38, offset: 14851}, - name: "_", - }, - &litMatcher{ - pos: position{line: 537, col: 40, offset: 14853}, - val: ":", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 537, col: 44, offset: 14857}, + pos: position{line: 174, col: 28, offset: 4735}, name: "_", }, &labeledExpr{ - pos: position{line: 537, col: 46, offset: 14859}, - label: "value", + pos: position{line: 174, col: 30, offset: 4737}, + label: "head", expr: &ruleRefExpr{ - pos: position{line: 537, col: 52, offset: 14865}, - name: "Term", + pos: position{line: 174, col: 35, offset: 4742}, + name: "TermPair", }, }, &ruleRefExpr{ - pos: position{line: 537, col: 58, offset: 14871}, + pos: position{line: 174, col: 45, offset: 4752}, name: "_", }, &litMatcher{ - pos: position{line: 537, col: 60, offset: 14873}, + pos: position{line: 174, col: 47, offset: 4754}, val: "|", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 537, col: 64, offset: 14877}, + pos: position{line: 174, col: 51, offset: 4758}, name: "_", }, &labeledExpr{ - pos: position{line: 537, col: 66, offset: 14879}, + pos: position{line: 174, col: 53, offset: 4760}, label: "body", expr: &ruleRefExpr{ - pos: position{line: 537, col: 71, offset: 14884}, + pos: position{line: 174, col: 58, offset: 4765}, name: "WhitespaceBody", }, }, &ruleRefExpr{ - pos: position{line: 537, col: 86, offset: 14899}, + pos: position{line: 174, col: 73, offset: 4780}, name: "_", }, &litMatcher{ - pos: position{line: 537, col: 88, offset: 14901}, + pos: position{line: 174, col: 75, offset: 4782}, val: "}", ignoreCase: false, }, @@ -1941,246 +1984,142 @@ var g = &grammar{ }, { name: "SetComprehension", - pos: position{line: 543, col: 1, offset: 15041}, + pos: position{line: 178, col: 1, offset: 4858}, expr: &actionExpr{ - pos: position{line: 543, col: 21, offset: 15061}, + pos: position{line: 178, col: 21, offset: 4878}, run: (*parser).callonSetComprehension1, expr: &seqExpr{ - pos: position{line: 543, col: 21, offset: 15061}, + pos: position{line: 178, col: 21, offset: 4878}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 543, col: 21, offset: 15061}, + pos: position{line: 178, col: 21, offset: 4878}, val: "{", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 543, col: 25, offset: 15065}, + pos: position{line: 178, col: 25, offset: 4882}, name: "_", }, &labeledExpr{ - pos: position{line: 543, col: 27, offset: 15067}, - label: "term", + pos: position{line: 178, col: 27, offset: 4884}, + label: "head", expr: &ruleRefExpr{ - pos: position{line: 543, col: 32, offset: 15072}, + pos: position{line: 178, col: 32, offset: 4889}, name: "Term", }, }, &ruleRefExpr{ - pos: position{line: 543, col: 37, offset: 15077}, + pos: position{line: 178, col: 37, offset: 4894}, name: "_", }, &litMatcher{ - pos: position{line: 543, col: 39, offset: 15079}, + pos: position{line: 178, col: 39, offset: 4896}, val: "|", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 543, col: 43, offset: 15083}, + pos: position{line: 178, col: 43, offset: 4900}, name: "_", }, &labeledExpr{ - pos: position{line: 543, col: 45, offset: 15085}, + pos: position{line: 178, col: 45, offset: 4902}, label: "body", expr: &ruleRefExpr{ - pos: position{line: 543, col: 50, offset: 15090}, + pos: position{line: 178, col: 50, offset: 4907}, name: "WhitespaceBody", }, }, &ruleRefExpr{ - pos: position{line: 543, col: 65, offset: 15105}, + pos: position{line: 178, col: 65, offset: 4922}, name: "_", }, &litMatcher{ - pos: position{line: 543, col: 67, offset: 15107}, + pos: position{line: 178, col: 67, offset: 4924}, val: "}", ignoreCase: false, }, - }, - }, - }, - }, - { - name: "Composite", - pos: position{line: 549, col: 1, offset: 15230}, - expr: &choiceExpr{ - pos: position{line: 549, col: 14, offset: 15243}, - alternatives: []interface{}{ - &ruleRefExpr{ - pos: position{line: 549, col: 14, offset: 15243}, - name: "Object", - }, - &ruleRefExpr{ - pos: position{line: 549, col: 23, offset: 15252}, - name: "Array", - }, - &ruleRefExpr{ - pos: position{line: 549, col: 31, offset: 15260}, - name: "Set", - }, - }, - }, - }, - { - name: "Scalar", - pos: position{line: 551, col: 1, offset: 15265}, - expr: &choiceExpr{ - pos: position{line: 551, col: 11, offset: 15275}, - alternatives: []interface{}{ - &ruleRefExpr{ - pos: position{line: 551, col: 11, offset: 15275}, - name: "Number", - }, - &ruleRefExpr{ - pos: position{line: 551, col: 20, offset: 15284}, - name: "String", - }, - &ruleRefExpr{ - pos: position{line: 551, col: 29, offset: 15293}, - name: "Bool", - }, - &ruleRefExpr{ - pos: position{line: 551, col: 36, offset: 15300}, - name: "Null", - }, - }, - }, - }, - { - name: "Key", - pos: position{line: 553, col: 1, offset: 15306}, - expr: &choiceExpr{ - pos: position{line: 553, col: 8, offset: 15313}, - alternatives: []interface{}{ - &ruleRefExpr{ - pos: position{line: 553, col: 8, offset: 15313}, - name: "Scalar", - }, - &ruleRefExpr{ - pos: position{line: 553, col: 17, offset: 15322}, - name: "Ref", - }, - &ruleRefExpr{ - pos: position{line: 553, col: 23, offset: 15328}, - name: "Var", - }, - }, - }, - }, - { - name: "Object", - pos: position{line: 555, col: 1, offset: 15333}, - expr: &actionExpr{ - pos: position{line: 555, col: 11, offset: 15343}, - run: (*parser).callonObject1, - expr: &seqExpr{ - pos: position{line: 555, col: 11, offset: 15343}, - exprs: []interface{}{ - &litMatcher{ - pos: position{line: 555, col: 11, offset: 15343}, - val: "{", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 555, col: 15, offset: 15347}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 555, col: 17, offset: 15349}, - label: "head", - expr: &zeroOrOneExpr{ - pos: position{line: 555, col: 22, offset: 15354}, - expr: &seqExpr{ - pos: position{line: 555, col: 23, offset: 15355}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 555, col: 23, offset: 15355}, - name: "Key", - }, - &ruleRefExpr{ - pos: position{line: 555, col: 27, offset: 15359}, - name: "_", - }, - &litMatcher{ - pos: position{line: 555, col: 29, offset: 15361}, - val: ":", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 555, col: 33, offset: 15365}, - name: "_", - }, - &ruleRefExpr{ - pos: position{line: 555, col: 35, offset: 15367}, - name: "Term", - }, - }, - }, - }, - }, - &labeledExpr{ - pos: position{line: 555, col: 42, offset: 15374}, - label: "tail", - expr: &zeroOrMoreExpr{ - pos: position{line: 555, col: 47, offset: 15379}, - expr: &seqExpr{ - pos: position{line: 555, col: 49, offset: 15381}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 555, col: 49, offset: 15381}, - name: "_", - }, - &litMatcher{ - pos: position{line: 555, col: 51, offset: 15383}, - val: ",", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 555, col: 55, offset: 15387}, - name: "_", - }, - &ruleRefExpr{ - pos: position{line: 555, col: 57, offset: 15389}, - name: "Key", - }, - &ruleRefExpr{ - pos: position{line: 555, col: 61, offset: 15393}, - name: "_", - }, - &litMatcher{ - pos: position{line: 555, col: 63, offset: 15395}, - val: ":", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 555, col: 67, offset: 15399}, - name: "_", - }, - &ruleRefExpr{ - pos: position{line: 555, col: 69, offset: 15401}, - name: "Term", - }, - }, - }, - }, - }, + }, + }, + }, + }, + { + name: "Composite", + pos: position{line: 182, col: 1, offset: 4997}, + expr: &choiceExpr{ + pos: position{line: 182, col: 14, offset: 5010}, + alternatives: []interface{}{ + &ruleRefExpr{ + pos: position{line: 182, col: 14, offset: 5010}, + name: "Object", + }, + &ruleRefExpr{ + pos: position{line: 182, col: 23, offset: 5019}, + name: "Array", + }, + &ruleRefExpr{ + pos: position{line: 182, col: 31, offset: 5027}, + name: "Set", + }, + }, + }, + }, + { + name: "Scalar", + pos: position{line: 184, col: 1, offset: 5032}, + expr: &choiceExpr{ + pos: position{line: 184, col: 11, offset: 5042}, + alternatives: []interface{}{ + &ruleRefExpr{ + pos: position{line: 184, col: 11, offset: 5042}, + name: "Number", + }, + &ruleRefExpr{ + pos: position{line: 184, col: 20, offset: 5051}, + name: "String", + }, + &ruleRefExpr{ + pos: position{line: 184, col: 29, offset: 5060}, + name: "Bool", + }, + &ruleRefExpr{ + pos: position{line: 184, col: 36, offset: 5067}, + name: "Null", + }, + }, + }, + }, + { + name: "Object", + pos: position{line: 186, col: 1, offset: 5073}, + expr: &actionExpr{ + pos: position{line: 186, col: 11, offset: 5083}, + run: (*parser).callonObject1, + expr: &seqExpr{ + pos: position{line: 186, col: 11, offset: 5083}, + exprs: []interface{}{ + &litMatcher{ + pos: position{line: 186, col: 11, offset: 5083}, + val: "{", + ignoreCase: false, + }, &ruleRefExpr{ - pos: position{line: 555, col: 77, offset: 15409}, + pos: position{line: 186, col: 15, offset: 5087}, name: "_", }, - &zeroOrOneExpr{ - pos: position{line: 555, col: 79, offset: 15411}, - expr: &litMatcher{ - pos: position{line: 555, col: 79, offset: 15411}, - val: ",", - ignoreCase: false, + &labeledExpr{ + pos: position{line: 186, col: 17, offset: 5089}, + label: "list", + expr: &ruleRefExpr{ + pos: position{line: 186, col: 22, offset: 5094}, + name: "ExprTermPairList", }, }, &ruleRefExpr{ - pos: position{line: 555, col: 84, offset: 15416}, + pos: position{line: 186, col: 39, offset: 5111}, name: "_", }, &litMatcher{ - pos: position{line: 555, col: 86, offset: 15418}, + pos: position{line: 186, col: 41, offset: 5113}, val: "}", ignoreCase: false, }, @@ -2190,80 +2129,36 @@ var g = &grammar{ }, { name: "Array", - pos: position{line: 559, col: 1, offset: 15481}, + pos: position{line: 190, col: 1, offset: 5170}, expr: &actionExpr{ - pos: position{line: 559, col: 10, offset: 15490}, + pos: position{line: 190, col: 10, offset: 5179}, run: (*parser).callonArray1, expr: &seqExpr{ - pos: position{line: 559, col: 10, offset: 15490}, + pos: position{line: 190, col: 10, offset: 5179}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 559, col: 10, offset: 15490}, + pos: position{line: 190, col: 10, offset: 5179}, val: "[", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 559, col: 14, offset: 15494}, + pos: position{line: 190, col: 14, offset: 5183}, name: "_", }, &labeledExpr{ - pos: position{line: 559, col: 17, offset: 15497}, - label: "head", - expr: &zeroOrOneExpr{ - pos: position{line: 559, col: 22, offset: 15502}, - expr: &ruleRefExpr{ - pos: position{line: 559, col: 22, offset: 15502}, - name: "Term", - }, - }, - }, - &labeledExpr{ - pos: position{line: 559, col: 28, offset: 15508}, - label: "tail", - expr: &zeroOrMoreExpr{ - pos: position{line: 559, col: 33, offset: 15513}, - expr: &seqExpr{ - pos: position{line: 559, col: 34, offset: 15514}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 559, col: 34, offset: 15514}, - name: "_", - }, - &litMatcher{ - pos: position{line: 559, col: 36, offset: 15516}, - val: ",", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 559, col: 40, offset: 15520}, - name: "_", - }, - &ruleRefExpr{ - pos: position{line: 559, col: 42, offset: 15522}, - name: "Term", - }, - }, - }, - }, - }, - &ruleRefExpr{ - pos: position{line: 559, col: 49, offset: 15529}, - name: "_", - }, - &zeroOrOneExpr{ - pos: position{line: 559, col: 51, offset: 15531}, - expr: &litMatcher{ - pos: position{line: 559, col: 51, offset: 15531}, - val: ",", - ignoreCase: false, + pos: position{line: 190, col: 16, offset: 5185}, + label: "list", + expr: &ruleRefExpr{ + pos: position{line: 190, col: 21, offset: 5190}, + name: "ExprTermList", }, }, &ruleRefExpr{ - pos: position{line: 559, col: 56, offset: 15536}, + pos: position{line: 190, col: 34, offset: 5203}, name: "_", }, &litMatcher{ - pos: position{line: 559, col: 59, offset: 15539}, + pos: position{line: 190, col: 36, offset: 5205}, val: "]", ignoreCase: false, }, @@ -2273,16 +2168,16 @@ var g = &grammar{ }, { name: "Set", - pos: position{line: 563, col: 1, offset: 15601}, + pos: position{line: 194, col: 1, offset: 5261}, expr: &choiceExpr{ - pos: position{line: 563, col: 8, offset: 15608}, + pos: position{line: 194, col: 8, offset: 5268}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 563, col: 8, offset: 15608}, + pos: position{line: 194, col: 8, offset: 5268}, name: "SetEmpty", }, &ruleRefExpr{ - pos: position{line: 563, col: 19, offset: 15619}, + pos: position{line: 194, col: 19, offset: 5279}, name: "SetNonEmpty", }, }, @@ -2290,24 +2185,24 @@ var g = &grammar{ }, { name: "SetEmpty", - pos: position{line: 565, col: 1, offset: 15632}, + pos: position{line: 196, col: 1, offset: 5292}, expr: &actionExpr{ - pos: position{line: 565, col: 13, offset: 15644}, + pos: position{line: 196, col: 13, offset: 5304}, run: (*parser).callonSetEmpty1, expr: &seqExpr{ - pos: position{line: 565, col: 13, offset: 15644}, + pos: position{line: 196, col: 13, offset: 5304}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 565, col: 13, offset: 15644}, + pos: position{line: 196, col: 13, offset: 5304}, val: "set(", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 565, col: 20, offset: 15651}, + pos: position{line: 196, col: 20, offset: 5311}, name: "_", }, &litMatcher{ - pos: position{line: 565, col: 22, offset: 15653}, + pos: position{line: 196, col: 22, offset: 5313}, val: ")", ignoreCase: false, }, @@ -2317,77 +2212,36 @@ var g = &grammar{ }, { name: "SetNonEmpty", - pos: position{line: 571, col: 1, offset: 15741}, + pos: position{line: 201, col: 1, offset: 5390}, expr: &actionExpr{ - pos: position{line: 571, col: 16, offset: 15756}, + pos: position{line: 201, col: 16, offset: 5405}, run: (*parser).callonSetNonEmpty1, expr: &seqExpr{ - pos: position{line: 571, col: 16, offset: 15756}, + pos: position{line: 201, col: 16, offset: 5405}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 571, col: 16, offset: 15756}, + pos: position{line: 201, col: 16, offset: 5405}, val: "{", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 571, col: 20, offset: 15760}, + pos: position{line: 201, col: 20, offset: 5409}, name: "_", }, &labeledExpr{ - pos: position{line: 571, col: 22, offset: 15762}, - label: "head", + pos: position{line: 201, col: 22, offset: 5411}, + label: "list", expr: &ruleRefExpr{ - pos: position{line: 571, col: 27, offset: 15767}, - name: "Term", - }, - }, - &labeledExpr{ - pos: position{line: 571, col: 32, offset: 15772}, - label: "tail", - expr: &zeroOrMoreExpr{ - pos: position{line: 571, col: 37, offset: 15777}, - expr: &seqExpr{ - pos: position{line: 571, col: 38, offset: 15778}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 571, col: 38, offset: 15778}, - name: "_", - }, - &litMatcher{ - pos: position{line: 571, col: 40, offset: 15780}, - val: ",", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 571, col: 44, offset: 15784}, - name: "_", - }, - &ruleRefExpr{ - pos: position{line: 571, col: 46, offset: 15786}, - name: "Term", - }, - }, - }, - }, - }, - &ruleRefExpr{ - pos: position{line: 571, col: 53, offset: 15793}, - name: "_", - }, - &zeroOrOneExpr{ - pos: position{line: 571, col: 55, offset: 15795}, - expr: &litMatcher{ - pos: position{line: 571, col: 55, offset: 15795}, - val: ",", - ignoreCase: false, + pos: position{line: 201, col: 27, offset: 5416}, + name: "ExprTermList", }, }, &ruleRefExpr{ - pos: position{line: 571, col: 60, offset: 15800}, + pos: position{line: 201, col: 40, offset: 5429}, name: "_", }, &litMatcher{ - pos: position{line: 571, col: 62, offset: 15802}, + pos: position{line: 201, col: 42, offset: 5431}, val: "}", ignoreCase: false, }, @@ -2397,38 +2251,29 @@ var g = &grammar{ }, { name: "Ref", - pos: position{line: 588, col: 1, offset: 16207}, + pos: position{line: 205, col: 1, offset: 5485}, expr: &actionExpr{ - pos: position{line: 588, col: 8, offset: 16214}, + pos: position{line: 205, col: 8, offset: 5492}, run: (*parser).callonRef1, expr: &seqExpr{ - pos: position{line: 588, col: 8, offset: 16214}, + pos: position{line: 205, col: 8, offset: 5492}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 588, col: 8, offset: 16214}, + pos: position{line: 205, col: 8, offset: 5492}, label: "head", expr: &ruleRefExpr{ - pos: position{line: 588, col: 13, offset: 16219}, + pos: position{line: 205, col: 13, offset: 5497}, name: "Var", }, }, &labeledExpr{ - pos: position{line: 588, col: 17, offset: 16223}, - label: "tail", + pos: position{line: 205, col: 17, offset: 5501}, + label: "rest", expr: &oneOrMoreExpr{ - pos: position{line: 588, col: 22, offset: 16228}, - expr: &choiceExpr{ - pos: position{line: 588, col: 24, offset: 16230}, - alternatives: []interface{}{ - &ruleRefExpr{ - pos: position{line: 588, col: 24, offset: 16230}, - name: "RefDot", - }, - &ruleRefExpr{ - pos: position{line: 588, col: 33, offset: 16239}, - name: "RefBracket", - }, - }, + pos: position{line: 205, col: 22, offset: 5506}, + expr: &ruleRefExpr{ + pos: position{line: 205, col: 22, offset: 5506}, + name: "RefOperand", }, }, }, @@ -2437,24 +2282,41 @@ var g = &grammar{ }, }, { - name: "RefDot", - pos: position{line: 601, col: 1, offset: 16478}, + name: "RefOperand", + pos: position{line: 209, col: 1, offset: 5574}, + expr: &choiceExpr{ + pos: position{line: 209, col: 15, offset: 5588}, + alternatives: []interface{}{ + &ruleRefExpr{ + pos: position{line: 209, col: 15, offset: 5588}, + name: "RefOperandDot", + }, + &ruleRefExpr{ + pos: position{line: 209, col: 31, offset: 5604}, + name: "RefOperandCanonical", + }, + }, + }, + }, + { + name: "RefOperandDot", + pos: position{line: 211, col: 1, offset: 5625}, expr: &actionExpr{ - pos: position{line: 601, col: 11, offset: 16488}, - run: (*parser).callonRefDot1, + pos: position{line: 211, col: 18, offset: 5642}, + run: (*parser).callonRefOperandDot1, expr: &seqExpr{ - pos: position{line: 601, col: 11, offset: 16488}, + pos: position{line: 211, col: 18, offset: 5642}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 601, col: 11, offset: 16488}, + pos: position{line: 211, col: 18, offset: 5642}, val: ".", ignoreCase: false, }, &labeledExpr{ - pos: position{line: 601, col: 15, offset: 16492}, + pos: position{line: 211, col: 22, offset: 5646}, label: "val", expr: &ruleRefExpr{ - pos: position{line: 601, col: 19, offset: 16496}, + pos: position{line: 211, col: 26, offset: 5650}, name: "Var", }, }, @@ -2463,46 +2325,29 @@ var g = &grammar{ }, }, { - name: "RefBracket", - pos: position{line: 608, col: 1, offset: 16715}, + name: "RefOperandCanonical", + pos: position{line: 215, col: 1, offset: 5713}, expr: &actionExpr{ - pos: position{line: 608, col: 15, offset: 16729}, - run: (*parser).callonRefBracket1, + pos: position{line: 215, col: 24, offset: 5736}, + run: (*parser).callonRefOperandCanonical1, expr: &seqExpr{ - pos: position{line: 608, col: 15, offset: 16729}, + pos: position{line: 215, col: 24, offset: 5736}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 608, col: 15, offset: 16729}, + pos: position{line: 215, col: 24, offset: 5736}, val: "[", ignoreCase: false, }, &labeledExpr{ - pos: position{line: 608, col: 19, offset: 16733}, + pos: position{line: 215, col: 28, offset: 5740}, label: "val", - expr: &choiceExpr{ - pos: position{line: 608, col: 24, offset: 16738}, - alternatives: []interface{}{ - &ruleRefExpr{ - pos: position{line: 608, col: 24, offset: 16738}, - name: "Composite", - }, - &ruleRefExpr{ - pos: position{line: 608, col: 36, offset: 16750}, - name: "Ref", - }, - &ruleRefExpr{ - pos: position{line: 608, col: 42, offset: 16756}, - name: "Scalar", - }, - &ruleRefExpr{ - pos: position{line: 608, col: 51, offset: 16765}, - name: "Var", - }, - }, + expr: &ruleRefExpr{ + pos: position{line: 215, col: 32, offset: 5744}, + name: "ExprTerm", }, }, &litMatcher{ - pos: position{line: 608, col: 56, offset: 16770}, + pos: position{line: 215, col: 41, offset: 5753}, val: "]", ignoreCase: false, }, @@ -2512,15 +2357,15 @@ var g = &grammar{ }, { name: "Var", - pos: position{line: 612, col: 1, offset: 16799}, + pos: position{line: 219, col: 1, offset: 5782}, expr: &actionExpr{ - pos: position{line: 612, col: 8, offset: 16806}, + pos: position{line: 219, col: 8, offset: 5789}, run: (*parser).callonVar1, expr: &labeledExpr{ - pos: position{line: 612, col: 8, offset: 16806}, + pos: position{line: 219, col: 8, offset: 5789}, label: "val", expr: &ruleRefExpr{ - pos: position{line: 612, col: 12, offset: 16810}, + pos: position{line: 219, col: 12, offset: 5793}, name: "VarChecked", }, }, @@ -2528,20 +2373,20 @@ var g = &grammar{ }, { name: "VarChecked", - pos: position{line: 617, col: 1, offset: 16932}, + pos: position{line: 223, col: 1, offset: 5848}, expr: &seqExpr{ - pos: position{line: 617, col: 15, offset: 16946}, + pos: position{line: 223, col: 15, offset: 5862}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 617, col: 15, offset: 16946}, + pos: position{line: 223, col: 15, offset: 5862}, label: "val", expr: &ruleRefExpr{ - pos: position{line: 617, col: 19, offset: 16950}, + pos: position{line: 223, col: 19, offset: 5866}, name: "VarUnchecked", }, }, ¬CodeExpr{ - pos: position{line: 617, col: 32, offset: 16963}, + pos: position{line: 223, col: 32, offset: 5879}, run: (*parser).callonVarChecked4, }, }, @@ -2549,28 +2394,28 @@ var g = &grammar{ }, { name: "VarUnchecked", - pos: position{line: 621, col: 1, offset: 17028}, + pos: position{line: 227, col: 1, offset: 5944}, expr: &actionExpr{ - pos: position{line: 621, col: 17, offset: 17044}, + pos: position{line: 227, col: 17, offset: 5960}, run: (*parser).callonVarUnchecked1, expr: &seqExpr{ - pos: position{line: 621, col: 17, offset: 17044}, + pos: position{line: 227, col: 17, offset: 5960}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 621, col: 17, offset: 17044}, + pos: position{line: 227, col: 17, offset: 5960}, name: "AsciiLetter", }, &zeroOrMoreExpr{ - pos: position{line: 621, col: 29, offset: 17056}, + pos: position{line: 227, col: 29, offset: 5972}, expr: &choiceExpr{ - pos: position{line: 621, col: 30, offset: 17057}, + pos: position{line: 227, col: 30, offset: 5973}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 621, col: 30, offset: 17057}, + pos: position{line: 227, col: 30, offset: 5973}, name: "AsciiLetter", }, &ruleRefExpr{ - pos: position{line: 621, col: 44, offset: 17071}, + pos: position{line: 227, col: 44, offset: 5987}, name: "DecimalDigit", }, }, @@ -2582,30 +2427,30 @@ var g = &grammar{ }, { name: "Number", - pos: position{line: 628, col: 1, offset: 17214}, + pos: position{line: 231, col: 1, offset: 6054}, expr: &actionExpr{ - pos: position{line: 628, col: 11, offset: 17224}, + pos: position{line: 231, col: 11, offset: 6064}, run: (*parser).callonNumber1, expr: &seqExpr{ - pos: position{line: 628, col: 11, offset: 17224}, + pos: position{line: 231, col: 11, offset: 6064}, exprs: []interface{}{ &zeroOrOneExpr{ - pos: position{line: 628, col: 11, offset: 17224}, + pos: position{line: 231, col: 11, offset: 6064}, expr: &litMatcher{ - pos: position{line: 628, col: 11, offset: 17224}, + pos: position{line: 231, col: 11, offset: 6064}, val: "-", ignoreCase: false, }, }, &choiceExpr{ - pos: position{line: 628, col: 18, offset: 17231}, + pos: position{line: 231, col: 18, offset: 6071}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 628, col: 18, offset: 17231}, + pos: position{line: 231, col: 18, offset: 6071}, name: "Float", }, &ruleRefExpr{ - pos: position{line: 628, col: 26, offset: 17239}, + pos: position{line: 231, col: 26, offset: 6079}, name: "Integer", }, }, @@ -2616,16 +2461,16 @@ var g = &grammar{ }, { name: "Float", - pos: position{line: 641, col: 1, offset: 17630}, + pos: position{line: 235, col: 1, offset: 6144}, expr: &choiceExpr{ - pos: position{line: 641, col: 10, offset: 17639}, + pos: position{line: 235, col: 10, offset: 6153}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 641, col: 10, offset: 17639}, + pos: position{line: 235, col: 10, offset: 6153}, name: "ExponentFloat", }, &ruleRefExpr{ - pos: position{line: 641, col: 26, offset: 17655}, + pos: position{line: 235, col: 26, offset: 6169}, name: "PointFloat", }, }, @@ -2633,25 +2478,25 @@ var g = &grammar{ }, { name: "ExponentFloat", - pos: position{line: 643, col: 1, offset: 17667}, + pos: position{line: 237, col: 1, offset: 6181}, expr: &seqExpr{ - pos: position{line: 643, col: 18, offset: 17684}, + pos: position{line: 237, col: 18, offset: 6198}, exprs: []interface{}{ &choiceExpr{ - pos: position{line: 643, col: 20, offset: 17686}, + pos: position{line: 237, col: 20, offset: 6200}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 643, col: 20, offset: 17686}, + pos: position{line: 237, col: 20, offset: 6200}, name: "PointFloat", }, &ruleRefExpr{ - pos: position{line: 643, col: 33, offset: 17699}, + pos: position{line: 237, col: 33, offset: 6213}, name: "Integer", }, }, }, &ruleRefExpr{ - pos: position{line: 643, col: 43, offset: 17709}, + pos: position{line: 237, col: 43, offset: 6223}, name: "Exponent", }, }, @@ -2659,19 +2504,19 @@ var g = &grammar{ }, { name: "PointFloat", - pos: position{line: 645, col: 1, offset: 17719}, + pos: position{line: 239, col: 1, offset: 6233}, expr: &seqExpr{ - pos: position{line: 645, col: 15, offset: 17733}, + pos: position{line: 239, col: 15, offset: 6247}, exprs: []interface{}{ &zeroOrOneExpr{ - pos: position{line: 645, col: 15, offset: 17733}, + pos: position{line: 239, col: 15, offset: 6247}, expr: &ruleRefExpr{ - pos: position{line: 645, col: 15, offset: 17733}, + pos: position{line: 239, col: 15, offset: 6247}, name: "Integer", }, }, &ruleRefExpr{ - pos: position{line: 645, col: 24, offset: 17742}, + pos: position{line: 239, col: 24, offset: 6256}, name: "Fraction", }, }, @@ -2679,19 +2524,19 @@ var g = &grammar{ }, { name: "Fraction", - pos: position{line: 647, col: 1, offset: 17752}, + pos: position{line: 241, col: 1, offset: 6266}, expr: &seqExpr{ - pos: position{line: 647, col: 13, offset: 17764}, + pos: position{line: 241, col: 13, offset: 6278}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 647, col: 13, offset: 17764}, + pos: position{line: 241, col: 13, offset: 6278}, val: ".", ignoreCase: false, }, &oneOrMoreExpr{ - pos: position{line: 647, col: 17, offset: 17768}, + pos: position{line: 241, col: 17, offset: 6282}, expr: &ruleRefExpr{ - pos: position{line: 647, col: 17, offset: 17768}, + pos: position{line: 241, col: 17, offset: 6282}, name: "DecimalDigit", }, }, @@ -2700,19 +2545,19 @@ var g = &grammar{ }, { name: "Exponent", - pos: position{line: 649, col: 1, offset: 17783}, + pos: position{line: 243, col: 1, offset: 6297}, expr: &seqExpr{ - pos: position{line: 649, col: 13, offset: 17795}, + pos: position{line: 243, col: 13, offset: 6309}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 649, col: 13, offset: 17795}, + pos: position{line: 243, col: 13, offset: 6309}, val: "e", ignoreCase: true, }, &zeroOrOneExpr{ - pos: position{line: 649, col: 18, offset: 17800}, + pos: position{line: 243, col: 18, offset: 6314}, expr: &charClassMatcher{ - pos: position{line: 649, col: 18, offset: 17800}, + pos: position{line: 243, col: 18, offset: 6314}, val: "[+-]", chars: []rune{'+', '-'}, ignoreCase: false, @@ -2720,9 +2565,9 @@ var g = &grammar{ }, }, &oneOrMoreExpr{ - pos: position{line: 649, col: 24, offset: 17806}, + pos: position{line: 243, col: 24, offset: 6320}, expr: &ruleRefExpr{ - pos: position{line: 649, col: 24, offset: 17806}, + pos: position{line: 243, col: 24, offset: 6320}, name: "DecimalDigit", }, }, @@ -2731,26 +2576,26 @@ var g = &grammar{ }, { name: "Integer", - pos: position{line: 651, col: 1, offset: 17821}, + pos: position{line: 245, col: 1, offset: 6335}, expr: &choiceExpr{ - pos: position{line: 651, col: 12, offset: 17832}, + pos: position{line: 245, col: 12, offset: 6346}, alternatives: []interface{}{ &litMatcher{ - pos: position{line: 651, col: 12, offset: 17832}, + pos: position{line: 245, col: 12, offset: 6346}, val: "0", ignoreCase: false, }, &seqExpr{ - pos: position{line: 651, col: 20, offset: 17840}, + pos: position{line: 245, col: 20, offset: 6354}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 651, col: 20, offset: 17840}, + pos: position{line: 245, col: 20, offset: 6354}, name: "NonZeroDecimalDigit", }, &zeroOrMoreExpr{ - pos: position{line: 651, col: 40, offset: 17860}, + pos: position{line: 245, col: 40, offset: 6374}, expr: &ruleRefExpr{ - pos: position{line: 651, col: 40, offset: 17860}, + pos: position{line: 245, col: 40, offset: 6374}, name: "DecimalDigit", }, }, @@ -2761,16 +2606,16 @@ var g = &grammar{ }, { name: "String", - pos: position{line: 653, col: 1, offset: 17877}, + pos: position{line: 247, col: 1, offset: 6391}, expr: &choiceExpr{ - pos: position{line: 653, col: 11, offset: 17887}, + pos: position{line: 247, col: 11, offset: 6401}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 653, col: 11, offset: 17887}, + pos: position{line: 247, col: 11, offset: 6401}, name: "QuotedString", }, &ruleRefExpr{ - pos: position{line: 653, col: 26, offset: 17902}, + pos: position{line: 247, col: 26, offset: 6416}, name: "RawString", }, }, @@ -2778,27 +2623,27 @@ var g = &grammar{ }, { name: "QuotedString", - pos: position{line: 655, col: 1, offset: 17913}, + pos: position{line: 249, col: 1, offset: 6427}, expr: &actionExpr{ - pos: position{line: 655, col: 17, offset: 17929}, + pos: position{line: 249, col: 17, offset: 6443}, run: (*parser).callonQuotedString1, expr: &seqExpr{ - pos: position{line: 655, col: 17, offset: 17929}, + pos: position{line: 249, col: 17, offset: 6443}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 655, col: 17, offset: 17929}, + pos: position{line: 249, col: 17, offset: 6443}, val: "\"", ignoreCase: false, }, &zeroOrMoreExpr{ - pos: position{line: 655, col: 21, offset: 17933}, + pos: position{line: 249, col: 21, offset: 6447}, expr: &ruleRefExpr{ - pos: position{line: 655, col: 21, offset: 17933}, + pos: position{line: 249, col: 21, offset: 6447}, name: "Char", }, }, &litMatcher{ - pos: position{line: 655, col: 27, offset: 17939}, + pos: position{line: 249, col: 27, offset: 6453}, val: "\"", ignoreCase: false, }, @@ -2808,22 +2653,22 @@ var g = &grammar{ }, { name: "RawString", - pos: position{line: 663, col: 1, offset: 18094}, + pos: position{line: 253, col: 1, offset: 6512}, expr: &actionExpr{ - pos: position{line: 663, col: 14, offset: 18107}, + pos: position{line: 253, col: 14, offset: 6525}, run: (*parser).callonRawString1, expr: &seqExpr{ - pos: position{line: 663, col: 14, offset: 18107}, + pos: position{line: 253, col: 14, offset: 6525}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 663, col: 14, offset: 18107}, + pos: position{line: 253, col: 14, offset: 6525}, val: "`", ignoreCase: false, }, &zeroOrMoreExpr{ - pos: position{line: 663, col: 18, offset: 18111}, + pos: position{line: 253, col: 18, offset: 6529}, expr: &charClassMatcher{ - pos: position{line: 663, col: 18, offset: 18111}, + pos: position{line: 253, col: 18, offset: 6529}, val: "[^`]", chars: []rune{'`'}, ignoreCase: false, @@ -2831,7 +2676,7 @@ var g = &grammar{ }, }, &litMatcher{ - pos: position{line: 663, col: 24, offset: 18117}, + pos: position{line: 253, col: 24, offset: 6535}, val: "`", ignoreCase: false, }, @@ -2841,26 +2686,26 @@ var g = &grammar{ }, { name: "Bool", - pos: position{line: 672, col: 1, offset: 18284}, - expr: &choiceExpr{ - pos: position{line: 672, col: 9, offset: 18292}, - alternatives: []interface{}{ - &actionExpr{ - pos: position{line: 672, col: 9, offset: 18292}, - run: (*parser).callonBool2, - expr: &litMatcher{ - pos: position{line: 672, col: 9, offset: 18292}, - val: "true", - ignoreCase: false, - }, - }, - &actionExpr{ - pos: position{line: 676, col: 5, offset: 18392}, - run: (*parser).callonBool4, - expr: &litMatcher{ - pos: position{line: 676, col: 5, offset: 18392}, - val: "false", - ignoreCase: false, + pos: position{line: 257, col: 1, offset: 6597}, + expr: &actionExpr{ + pos: position{line: 257, col: 9, offset: 6605}, + run: (*parser).callonBool1, + expr: &labeledExpr{ + pos: position{line: 257, col: 9, offset: 6605}, + label: "val", + expr: &choiceExpr{ + pos: position{line: 257, col: 14, offset: 6610}, + alternatives: []interface{}{ + &litMatcher{ + pos: position{line: 257, col: 14, offset: 6610}, + val: "true", + ignoreCase: false, + }, + &litMatcher{ + pos: position{line: 257, col: 23, offset: 6619}, + val: "false", + ignoreCase: false, + }, }, }, }, @@ -2868,12 +2713,12 @@ var g = &grammar{ }, { name: "Null", - pos: position{line: 682, col: 1, offset: 18493}, + pos: position{line: 261, col: 1, offset: 6681}, expr: &actionExpr{ - pos: position{line: 682, col: 9, offset: 18501}, + pos: position{line: 261, col: 9, offset: 6689}, run: (*parser).callonNull1, expr: &litMatcher{ - pos: position{line: 682, col: 9, offset: 18501}, + pos: position{line: 261, col: 9, offset: 6689}, val: "null", ignoreCase: false, }, @@ -2881,9 +2726,9 @@ var g = &grammar{ }, { name: "AsciiLetter", - pos: position{line: 688, col: 1, offset: 18596}, + pos: position{line: 265, col: 1, offset: 6741}, expr: &charClassMatcher{ - pos: position{line: 688, col: 16, offset: 18611}, + pos: position{line: 265, col: 16, offset: 6756}, val: "[A-Za-z_]", chars: []rune{'_'}, ranges: []rune{'A', 'Z', 'a', 'z'}, @@ -2893,35 +2738,35 @@ var g = &grammar{ }, { name: "Char", - pos: position{line: 690, col: 1, offset: 18622}, + pos: position{line: 267, col: 1, offset: 6767}, expr: &choiceExpr{ - pos: position{line: 690, col: 9, offset: 18630}, + pos: position{line: 267, col: 9, offset: 6775}, alternatives: []interface{}{ &seqExpr{ - pos: position{line: 690, col: 11, offset: 18632}, + pos: position{line: 267, col: 11, offset: 6777}, exprs: []interface{}{ ¬Expr{ - pos: position{line: 690, col: 11, offset: 18632}, + pos: position{line: 267, col: 11, offset: 6777}, expr: &ruleRefExpr{ - pos: position{line: 690, col: 12, offset: 18633}, + pos: position{line: 267, col: 12, offset: 6778}, name: "EscapedChar", }, }, &anyMatcher{ - line: 690, col: 24, offset: 18645, + line: 267, col: 24, offset: 6790, }, }, }, &seqExpr{ - pos: position{line: 690, col: 32, offset: 18653}, + pos: position{line: 267, col: 32, offset: 6798}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 690, col: 32, offset: 18653}, + pos: position{line: 267, col: 32, offset: 6798}, val: "\\", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 690, col: 37, offset: 18658}, + pos: position{line: 267, col: 37, offset: 6803}, name: "EscapeSequence", }, }, @@ -2931,9 +2776,9 @@ var g = &grammar{ }, { name: "EscapedChar", - pos: position{line: 692, col: 1, offset: 18676}, + pos: position{line: 269, col: 1, offset: 6821}, expr: &charClassMatcher{ - pos: position{line: 692, col: 16, offset: 18691}, + pos: position{line: 269, col: 16, offset: 6836}, val: "[\\x00-\\x1f\"\\\\]", chars: []rune{'"', '\\'}, ranges: []rune{'\x00', '\x1f'}, @@ -2943,16 +2788,16 @@ var g = &grammar{ }, { name: "EscapeSequence", - pos: position{line: 694, col: 1, offset: 18707}, + pos: position{line: 271, col: 1, offset: 6852}, expr: &choiceExpr{ - pos: position{line: 694, col: 19, offset: 18725}, + pos: position{line: 271, col: 19, offset: 6870}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 694, col: 19, offset: 18725}, + pos: position{line: 271, col: 19, offset: 6870}, name: "SingleCharEscape", }, &ruleRefExpr{ - pos: position{line: 694, col: 38, offset: 18744}, + pos: position{line: 271, col: 38, offset: 6889}, name: "UnicodeEscape", }, }, @@ -2960,9 +2805,9 @@ var g = &grammar{ }, { name: "SingleCharEscape", - pos: position{line: 696, col: 1, offset: 18759}, + pos: position{line: 273, col: 1, offset: 6904}, expr: &charClassMatcher{ - pos: position{line: 696, col: 21, offset: 18779}, + pos: position{line: 273, col: 21, offset: 6924}, val: "[ \" \\\\ / b f n r t ]", chars: []rune{' ', '"', ' ', '\\', ' ', '/', ' ', 'b', ' ', 'f', ' ', 'n', ' ', 'r', ' ', 't', ' '}, ignoreCase: false, @@ -2971,29 +2816,29 @@ var g = &grammar{ }, { name: "UnicodeEscape", - pos: position{line: 698, col: 1, offset: 18801}, + pos: position{line: 275, col: 1, offset: 6946}, expr: &seqExpr{ - pos: position{line: 698, col: 18, offset: 18818}, + pos: position{line: 275, col: 18, offset: 6963}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 698, col: 18, offset: 18818}, + pos: position{line: 275, col: 18, offset: 6963}, val: "u", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 698, col: 22, offset: 18822}, + pos: position{line: 275, col: 22, offset: 6967}, name: "HexDigit", }, &ruleRefExpr{ - pos: position{line: 698, col: 31, offset: 18831}, + pos: position{line: 275, col: 31, offset: 6976}, name: "HexDigit", }, &ruleRefExpr{ - pos: position{line: 698, col: 40, offset: 18840}, + pos: position{line: 275, col: 40, offset: 6985}, name: "HexDigit", }, &ruleRefExpr{ - pos: position{line: 698, col: 49, offset: 18849}, + pos: position{line: 275, col: 49, offset: 6994}, name: "HexDigit", }, }, @@ -3001,9 +2846,9 @@ var g = &grammar{ }, { name: "DecimalDigit", - pos: position{line: 700, col: 1, offset: 18859}, + pos: position{line: 277, col: 1, offset: 7004}, expr: &charClassMatcher{ - pos: position{line: 700, col: 17, offset: 18875}, + pos: position{line: 277, col: 17, offset: 7020}, val: "[0-9]", ranges: []rune{'0', '9'}, ignoreCase: false, @@ -3012,9 +2857,9 @@ var g = &grammar{ }, { name: "NonZeroDecimalDigit", - pos: position{line: 702, col: 1, offset: 18882}, + pos: position{line: 279, col: 1, offset: 7027}, expr: &charClassMatcher{ - pos: position{line: 702, col: 24, offset: 18905}, + pos: position{line: 279, col: 24, offset: 7050}, val: "[1-9]", ranges: []rune{'1', '9'}, ignoreCase: false, @@ -3023,9 +2868,9 @@ var g = &grammar{ }, { name: "HexDigit", - pos: position{line: 704, col: 1, offset: 18912}, + pos: position{line: 281, col: 1, offset: 7057}, expr: &charClassMatcher{ - pos: position{line: 704, col: 13, offset: 18924}, + pos: position{line: 281, col: 13, offset: 7069}, val: "[0-9a-fA-F]", ranges: []rune{'0', '9', 'a', 'f', 'A', 'F'}, ignoreCase: false, @@ -3035,11 +2880,11 @@ var g = &grammar{ { name: "ws", displayName: "\"whitespace\"", - pos: position{line: 706, col: 1, offset: 18937}, + pos: position{line: 283, col: 1, offset: 7082}, expr: &oneOrMoreExpr{ - pos: position{line: 706, col: 20, offset: 18956}, + pos: position{line: 283, col: 20, offset: 7101}, expr: &charClassMatcher{ - pos: position{line: 706, col: 20, offset: 18956}, + pos: position{line: 283, col: 20, offset: 7101}, val: "[ \\t\\r\\n]", chars: []rune{' ', '\t', '\r', '\n'}, ignoreCase: false, @@ -3050,21 +2895,21 @@ var g = &grammar{ { name: "_", displayName: "\"whitespace\"", - pos: position{line: 708, col: 1, offset: 18968}, + pos: position{line: 285, col: 1, offset: 7113}, expr: &zeroOrMoreExpr{ - pos: position{line: 708, col: 19, offset: 18986}, + pos: position{line: 285, col: 19, offset: 7131}, expr: &choiceExpr{ - pos: position{line: 708, col: 21, offset: 18988}, + pos: position{line: 285, col: 21, offset: 7133}, alternatives: []interface{}{ &charClassMatcher{ - pos: position{line: 708, col: 21, offset: 18988}, + pos: position{line: 285, col: 21, offset: 7133}, val: "[ \\t\\r\\n]", chars: []rune{' ', '\t', '\r', '\n'}, ignoreCase: false, inverted: false, }, &ruleRefExpr{ - pos: position{line: 708, col: 33, offset: 19000}, + pos: position{line: 285, col: 33, offset: 7145}, name: "Comment", }, }, @@ -3073,17 +2918,17 @@ var g = &grammar{ }, { name: "Comment", - pos: position{line: 710, col: 1, offset: 19012}, + pos: position{line: 287, col: 1, offset: 7157}, expr: &actionExpr{ - pos: position{line: 710, col: 12, offset: 19023}, + pos: position{line: 287, col: 12, offset: 7168}, run: (*parser).callonComment1, expr: &seqExpr{ - pos: position{line: 710, col: 12, offset: 19023}, + pos: position{line: 287, col: 12, offset: 7168}, exprs: []interface{}{ &zeroOrMoreExpr{ - pos: position{line: 710, col: 12, offset: 19023}, + pos: position{line: 287, col: 12, offset: 7168}, expr: &charClassMatcher{ - pos: position{line: 710, col: 12, offset: 19023}, + pos: position{line: 287, col: 12, offset: 7168}, val: "[ \\t]", chars: []rune{' ', '\t'}, ignoreCase: false, @@ -3091,17 +2936,17 @@ var g = &grammar{ }, }, &litMatcher{ - pos: position{line: 710, col: 19, offset: 19030}, + pos: position{line: 287, col: 19, offset: 7175}, val: "#", ignoreCase: false, }, &labeledExpr{ - pos: position{line: 710, col: 23, offset: 19034}, + pos: position{line: 287, col: 23, offset: 7179}, label: "text", expr: &zeroOrMoreExpr{ - pos: position{line: 710, col: 28, offset: 19039}, + pos: position{line: 287, col: 28, offset: 7184}, expr: &charClassMatcher{ - pos: position{line: 710, col: 28, offset: 19039}, + pos: position{line: 287, col: 28, offset: 7184}, val: "[^\\r\\n]", chars: []rune{'\r', '\n'}, ignoreCase: false, @@ -3115,11 +2960,11 @@ var g = &grammar{ }, { name: "EOF", - pos: position{line: 721, col: 1, offset: 19315}, + pos: position{line: 291, col: 1, offset: 7231}, expr: ¬Expr{ - pos: position{line: 721, col: 8, offset: 19322}, + pos: position{line: 291, col: 8, offset: 7238}, expr: &anyMatcher{ - line: 721, col: 9, offset: 19323, + line: 291, col: 9, offset: 7239, }, }, }, @@ -3127,21 +2972,7 @@ var g = &grammar{ } func (c *current) onProgram1(vals interface{}) (interface{}, error) { - var buf []interface{} - - if vals == nil { - return buf, nil - } - - ifaceSlice := vals.([]interface{}) - head := ifaceSlice[0] - buf = append(buf, head) - for _, tail := range ifaceSlice[1].([]interface{}) { - stmt := tail.([]interface{})[1] - buf = append(buf, stmt) - } - - return program{buf, c.globalStore[commentsKey]}, nil + return makeProgram(c, vals) } func (p *parser) callonProgram1() (interface{}, error) { @@ -3161,37 +2992,8 @@ func (p *parser) callonStmt1() (interface{}, error) { } func (c *current) onPackage1(val interface{}) (interface{}, error) { - // All packages are implicitly declared under the default root document. - term := val.(*Term) - path := Ref{DefaultRootDocument.Copy().SetLocation(term.Location)} - switch v := term.Value.(type) { - case Ref: - // Convert head of package Ref to String because it will be prefixed - // with the root document variable. - head := StringTerm(string(v[0].Value.(Var))).SetLocation(v[0].Location) - tail := v[1:] - if !tail.IsGround() { - return nil, fmt.Errorf("package name cannot contain variables: %v", v) - } + return makePackage(currentLocation(c), val) - // We do not allow non-string values in package names. - // Because documents are typically represented as JSON, non-string keys are - // not allowed for now. - // TODO(tsandall): consider special syntax for namespacing under arrays. - for _, p := range tail { - _, ok := p.Value.(String) - if !ok { - return nil, fmt.Errorf("package name cannot contain non-string values: %v", v) - } - } - path = append(path, head) - path = append(path, tail...) - case Var: - s := StringTerm(string(v)).SetLocation(term.Location) - path = append(path, s) - } - pkg := &Package{Location: currentLocation(c), Path: path} - return pkg, nil } func (p *parser) callonPackage1() (interface{}, error) { @@ -3201,19 +3003,7 @@ func (p *parser) callonPackage1() (interface{}, error) { } func (c *current) onImport1(path, alias interface{}) (interface{}, error) { - imp := &Import{} - imp.Location = currentLocation(c) - imp.Path = path.(*Term) - if err := IsValidImportPath(imp.Path.Value); err != nil { - return nil, err - } - if alias == nil { - return imp, nil - } - aliasSlice := alias.([]interface{}) - // Import definition above describes the "alias" slice. We only care about the "Var" element. - imp.Alias = aliasSlice[3].(*Term).Value.(Var) - return imp, nil + return makeImport(currentLocation(c), path, alias) } func (p *parser) callonImport1() (interface{}, error) { @@ -3223,441 +3013,326 @@ func (p *parser) callonImport1() (interface{}, error) { } func (c *current) onDefaultRules1(name, value interface{}) (interface{}, error) { + return makeDefaultRule(currentLocation(c), name, value) +} - term := value.(*Term) - var err error - - vis := NewGenericVisitor(func(x interface{}) bool { - if err != nil { - return true - } - switch x.(type) { - case *ArrayComprehension, *ObjectComprehension, *SetComprehension: // skip closures - return true - case Ref, Var: - err = fmt.Errorf("default rule value cannot contain %v", TypeName(x)) - return true - } - return false - }) +func (p *parser) callonDefaultRules1() (interface{}, error) { + stack := p.vstack[len(p.vstack)-1] + _ = stack + return p.cur.onDefaultRules1(stack["name"], stack["value"]) +} - Walk(vis, term) +func (c *current) onNormalRules1(head, rest interface{}) (interface{}, error) { + return makeRule(currentLocation(c), head, rest) +} - if err != nil { - return nil, err - } +func (p *parser) callonNormalRules1() (interface{}, error) { + stack := p.vstack[len(p.vstack)-1] + _ = stack + return p.cur.onNormalRules1(stack["head"], stack["rest"]) +} - loc := currentLocation(c) - body := NewBody(NewExpr(BooleanTerm(true).SetLocation(loc))) +func (c *current) onRuleHead1(name, args, key, value interface{}) (interface{}, error) { + return makeRuleHead(currentLocation(c), name, args, key, value) +} - rule := &Rule{ - Location: loc, - Default: true, - Head: &Head{ - Location: currentLocation(c), - Name: name.(*Term).Value.(Var), - Value: value.(*Term), - }, - Body: body, - } - rule.Body[0].Location = currentLocation(c) +func (p *parser) callonRuleHead1() (interface{}, error) { + stack := p.vstack[len(p.vstack)-1] + _ = stack + return p.cur.onRuleHead1(stack["name"], stack["args"], stack["key"], stack["value"]) +} - return []*Rule{rule}, nil +func (c *current) onArgs1(list interface{}) (interface{}, error) { + return makeArgs(list) } -func (p *parser) callonDefaultRules1() (interface{}, error) { +func (p *parser) callonArgs1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onDefaultRules1(stack["name"], stack["value"]) + return p.cur.onArgs1(stack["list"]) } -func (c *current) onNormalRules1(head, b interface{}) (interface{}, error) { +func (c *current) onElse1(value, body interface{}) (interface{}, error) { + return makeRuleExt(currentLocation(c), value, body) +} - if head == nil { - return nil, nil - } +func (p *parser) callonElse1() (interface{}, error) { + stack := p.vstack[len(p.vstack)-1] + _ = stack + return p.cur.onElse1(stack["value"], stack["body"]) +} + +func (c *current) onRuleDup1(b interface{}) (interface{}, error) { + return ruleExt{loc: currentLocation(c), body: b.(Body)}, nil +} - sl := b.([]interface{}) +func (p *parser) callonRuleDup1() (interface{}, error) { + stack := p.vstack[len(p.vstack)-1] + _ = stack + return p.cur.onRuleDup1(stack["b"]) +} - rules := []*Rule{ - &Rule{ - Location: currentLocation(c), - Head: head.(*Head), - Body: sl[0].(Body), - }, +func (c *current) onNonEmptyBraceEnclosedBody1(val interface{}) (interface{}, error) { + if val == nil { + panic("body must be non-empty") } + return val, nil +} - var ordered bool - prev := rules[0] - - for i, elem := range sl[1].([]interface{}) { +func (p *parser) callonNonEmptyBraceEnclosedBody1() (interface{}, error) { + stack := p.vstack[len(p.vstack)-1] + _ = stack + return p.cur.onNonEmptyBraceEnclosedBody1(stack["val"]) +} - next := elem.([]interface{}) - re := next[1].(ruleExt) +func (c *current) onBraceEnclosedBody1(val interface{}) (interface{}, error) { + return makeBraceEnclosedBody(currentLocation(c), val) +} - if re.term == nil { - if ordered { - return nil, fmt.Errorf("expected 'else' keyword") - } - rules = append(rules, &Rule{ - Location: re.loc, - Head: prev.Head.Copy(), - Body: re.body, - }) - } else { - if (rules[0].Head.DocKind() != CompleteDoc) || (i != 0 && !ordered) { - return nil, fmt.Errorf("unexpected 'else' keyword") - } - ordered = true - curr := &Rule{ - Location: re.loc, - Head: &Head{ - Name: prev.Head.Name, - Args: prev.Head.Args.Copy(), - Value: re.term, - Location: re.term.Location, - }, - Body: re.body, - } - prev.Else = curr - prev = curr - } - } +func (p *parser) callonBraceEnclosedBody1() (interface{}, error) { + stack := p.vstack[len(p.vstack)-1] + _ = stack + return p.cur.onBraceEnclosedBody1(stack["val"]) +} - return rules, nil +func (c *current) onWhitespaceBody1(head, tail interface{}) (interface{}, error) { + return makeBody(head, tail, 2) } -func (p *parser) callonNormalRules1() (interface{}, error) { +func (p *parser) callonWhitespaceBody1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onNormalRules1(stack["head"], stack["b"]) + return p.cur.onWhitespaceBody1(stack["head"], stack["tail"]) } -func (c *current) onRuleHead1(name, args, key, value interface{}) (interface{}, error) { - - head := &Head{} - - head.Location = currentLocation(c) - head.Name = name.(*Term).Value.(Var) - - if args != nil && key != nil { - return nil, fmt.Errorf("partial %v/%v %vs cannot take arguments", SetTypeName, ObjectTypeName, RuleTypeName) - } - - if args != nil { - argSlice := args.([]interface{}) - head.Args = argSlice[3].(Args) - } - - if key != nil { - keySlice := key.([]interface{}) - // Head definition above describes the "key" slice. We care about the "Term" element. - head.Key = keySlice[3].(*Term) - } - - if value != nil { - valueSlice := value.([]interface{}) - // Head definition above describes the "value" slice. We care about the "Term" element. - head.Value = valueSlice[len(valueSlice)-1].(*Term) - } - - if key == nil && value == nil { - head.Value = BooleanTerm(true).SetLocation(head.Location) - } +func (c *current) onNonWhitespaceBody1(head, tail interface{}) (interface{}, error) { + return makeBody(head, tail, 3) +} - if key != nil && value != nil { - switch head.Key.Value.(type) { - case Var, String, Ref: // nop - default: - return nil, fmt.Errorf("object key must be one of %v, %v, %v not %v", StringTypeName, VarTypeName, RefTypeName, TypeName(head.Key.Value)) - } - } +func (p *parser) callonNonWhitespaceBody1() (interface{}, error) { + stack := p.vstack[len(p.vstack)-1] + _ = stack + return p.cur.onNonWhitespaceBody1(stack["head"], stack["tail"]) +} - return head, nil +func (c *current) onLiteral1(negated, value, with interface{}) (interface{}, error) { + return makeLiteral(negated, value, with) } -func (p *parser) callonRuleHead1() (interface{}, error) { +func (p *parser) callonLiteral1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onRuleHead1(stack["name"], stack["args"], stack["key"], stack["value"]) + return p.cur.onLiteral1(stack["negated"], stack["value"], stack["with"]) } -func (c *current) onArgs1(head, tail interface{}) (interface{}, error) { - return makeArgs(head, tail, currentLocation(c)) +func (c *current) onLiteralExpr1(lhs, rest interface{}) (interface{}, error) { + return makeLiteralExpr(currentLocation(c), lhs, rest) } -func (p *parser) callonArgs1() (interface{}, error) { +func (p *parser) callonLiteralExpr1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onArgs1(stack["head"], stack["tail"]) + return p.cur.onLiteralExpr1(stack["lhs"], stack["rest"]) } -func (c *current) onElse1(val, b interface{}) (interface{}, error) { - bs := b.([]interface{}) - body := bs[1].(Body) +func (c *current) onLiteralExprOperator1(val interface{}) (interface{}, error) { + return makeInfixOperator(currentLocation(c), c.text) +} - if val == nil { - term := BooleanTerm(true) - term.Location = currentLocation(c) - return ruleExt{term.Location, term, body}, nil - } +func (p *parser) callonLiteralExprOperator1() (interface{}, error) { + stack := p.vstack[len(p.vstack)-1] + _ = stack + return p.cur.onLiteralExprOperator1(stack["val"]) +} - vs := val.([]interface{}) - t := vs[3].(*Term) - return ruleExt{currentLocation(c), t, body}, nil +func (c *current) onNotKeyword1(val interface{}) (interface{}, error) { + return val != nil, nil } -func (p *parser) callonElse1() (interface{}, error) { +func (p *parser) callonNotKeyword1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onElse1(stack["val"], stack["b"]) + return p.cur.onNotKeyword1(stack["val"]) } -func (c *current) onRuleDup1(b interface{}) (interface{}, error) { - return ruleExt{loc: currentLocation(c), body: b.(Body)}, nil +func (c *current) onWithKeywordList1(head, rest interface{}) (interface{}, error) { + return makeWithKeywordList(head, rest) } -func (p *parser) callonRuleDup1() (interface{}, error) { +func (p *parser) callonWithKeywordList1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onRuleDup1(stack["b"]) + return p.cur.onWithKeywordList1(stack["head"], stack["rest"]) } -func (c *current) onNonEmptyBraceEnclosedBody1(val interface{}) (interface{}, error) { - if val == nil { - panic("body must be non-empty") - } - return val, nil +func (c *current) onWithKeyword1(target, value interface{}) (interface{}, error) { + return makeWithKeyword(currentLocation(c), target, value) } -func (p *parser) callonNonEmptyBraceEnclosedBody1() (interface{}, error) { +func (p *parser) callonWithKeyword1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onNonEmptyBraceEnclosedBody1(stack["val"]) + return p.cur.onWithKeyword1(stack["target"], stack["value"]) } -func (c *current) onBraceEnclosedBody1(val interface{}) (interface{}, error) { +func (c *current) onExprTerm1(lhs, rest interface{}) (interface{}, error) { + return makeExprTerm(currentLocation(c), lhs, rest) +} - if val == nil { - loc := currentLocation(c) - body := NewBody(NewExpr(ObjectTerm().SetLocation(loc))) - body[0].Location = loc - return body, nil - } +func (p *parser) callonExprTerm1() (interface{}, error) { + stack := p.vstack[len(p.vstack)-1] + _ = stack + return p.cur.onExprTerm1(stack["lhs"], stack["rest"]) +} - return val, nil +func (c *current) onExprTermPairList1(head, tail interface{}) (interface{}, error) { + return makeExprTermPairList(head, tail) } -func (p *parser) callonBraceEnclosedBody1() (interface{}, error) { +func (p *parser) callonExprTermPairList1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onBraceEnclosedBody1(stack["val"]) + return p.cur.onExprTermPairList1(stack["head"], stack["tail"]) } -func (c *current) onWhitespaceBody1(head, tail interface{}) (interface{}, error) { - return ifacesToBody(head, tail.([]interface{})...), nil +func (c *current) onExprTermList1(head, tail interface{}) (interface{}, error) { + return makeExprTermList(head, tail) } -func (p *parser) callonWhitespaceBody1() (interface{}, error) { +func (p *parser) callonExprTermList1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onWhitespaceBody1(stack["head"], stack["tail"]) + return p.cur.onExprTermList1(stack["head"], stack["tail"]) } -func (c *current) onNonWhitespaceBody1(head, tail interface{}) (interface{}, error) { - return ifacesToBody(head, tail.([]interface{})...), nil +func (c *current) onExprTermPair1(key, value interface{}) (interface{}, error) { + return makeExprTermPair(key, value) } -func (p *parser) callonNonWhitespaceBody1() (interface{}, error) { +func (p *parser) callonExprTermPair1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onNonWhitespaceBody1(stack["head"], stack["tail"]) + return p.cur.onExprTermPair1(stack["key"], stack["value"]) } -func (c *current) onLiteral1(neg, val, with interface{}) (interface{}, error) { - var expr *Expr - switch val := val.(type) { - case *Expr: - expr = val - case *Term: - expr = &Expr{Terms: val} - } - expr.Location = currentLocation(c) - expr.Negated = neg != nil - - if with != nil { - sl := with.([]interface{}) - if head, ok := sl[1].(*With); ok { - expr.With = []*With{head} - if sl, ok := sl[2].([]interface{}); ok { - for i := range sl { - if w, ok := sl[i].([]interface{})[1].(*With); ok { - expr.With = append(expr.With, w) - } - } - } - } - } - - return expr, nil +func (c *current) onRelationOperator1(val interface{}) (interface{}, error) { + return makeInfixOperator(currentLocation(c), c.text) } -func (p *parser) callonLiteral1() (interface{}, error) { +func (p *parser) callonRelationOperator1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onLiteral1(stack["neg"], stack["val"], stack["with"]) + return p.cur.onRelationOperator1(stack["val"]) } -func (c *current) onWith1(target, value interface{}) (interface{}, error) { - with := &With{} - with.Location = currentLocation(c) - with.Target = target.(*Term) - if err := IsValidImportPath(with.Target.Value); err != nil { - return nil, err - } - with.Value = value.(*Term) - return with, nil +func (c *current) onRelationExpr1(lhs, rest interface{}) (interface{}, error) { + return makeExprTerm(currentLocation(c), lhs, rest) } -func (p *parser) callonWith1() (interface{}, error) { +func (p *parser) callonRelationExpr1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onWith1(stack["target"], stack["value"]) + return p.cur.onRelationExpr1(stack["lhs"], stack["rest"]) } -func (c *current) onInfixCallExpr1(output, operator, args interface{}) (interface{}, error) { - return makeInfixCallExpr(operator, args, output) +func (c *current) onBitwiseOrOperator1(val interface{}) (interface{}, error) { + return makeInfixOperator(currentLocation(c), c.text) } -func (p *parser) callonInfixCallExpr1() (interface{}, error) { +func (p *parser) callonBitwiseOrOperator1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onInfixCallExpr1(stack["output"], stack["operator"], stack["args"]) + return p.cur.onBitwiseOrOperator1(stack["val"]) } -func (c *current) onInfixCallExprReverse1(operator, args, output interface{}) (interface{}, error) { - return makeInfixCallExpr(operator, args, output) +func (c *current) onBitwiseOrExpr1(lhs, rest interface{}) (interface{}, error) { + return makeExprTerm(currentLocation(c), lhs, rest) } -func (p *parser) callonInfixCallExprReverse1() (interface{}, error) { +func (p *parser) callonBitwiseOrExpr1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onInfixCallExprReverse1(stack["operator"], stack["args"], stack["output"]) + return p.cur.onBitwiseOrExpr1(stack["lhs"], stack["rest"]) } -func (c *current) onInfixArithExpr1(output, left, operator, right interface{}) (interface{}, error) { - return makeInfixCallExpr(operator, Args{left.(*Term), right.(*Term)}, output) +func (c *current) onBitwiseAndOperator1(val interface{}) (interface{}, error) { + return makeInfixOperator(currentLocation(c), c.text) } -func (p *parser) callonInfixArithExpr1() (interface{}, error) { +func (p *parser) callonBitwiseAndOperator1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onInfixArithExpr1(stack["output"], stack["left"], stack["operator"], stack["right"]) + return p.cur.onBitwiseAndOperator1(stack["val"]) } -func (c *current) onInfixArithExprReverse1(left, operator, right, output interface{}) (interface{}, error) { - return makeInfixCallExpr(operator, Args{left.(*Term), right.(*Term)}, output) +func (c *current) onBitwiseAndExpr1(lhs, rest interface{}) (interface{}, error) { + return makeExprTerm(currentLocation(c), lhs, rest) } -func (p *parser) callonInfixArithExprReverse1() (interface{}, error) { +func (p *parser) callonBitwiseAndExpr1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onInfixArithExprReverse1(stack["left"], stack["operator"], stack["right"], stack["output"]) + return p.cur.onBitwiseAndExpr1(stack["lhs"], stack["rest"]) } -func (c *current) onArithInfixOp1(val interface{}) (interface{}, error) { - op := string(c.text) - for _, b := range Builtins { - if string(b.Infix) == op { - op = string(b.Name) - } - } - loc := currentLocation(c) - operator := RefTerm(VarTerm(op).SetLocation(loc)).SetLocation(loc) - return operator, nil +func (c *current) onArithOperator1(val interface{}) (interface{}, error) { + return makeInfixOperator(currentLocation(c), c.text) } -func (p *parser) callonArithInfixOp1() (interface{}, error) { +func (p *parser) callonArithOperator1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onArithInfixOp1(stack["val"]) + return p.cur.onArithOperator1(stack["val"]) } -func (c *current) onInfixRelationExpr1(left, operator, right interface{}) (interface{}, error) { - return &Expr{ - Terms: []*Term{ - operator.(*Term), - left.(*Term), - right.(*Term), - }, - Infix: true, - }, nil +func (c *current) onArithExpr1(lhs, rest interface{}) (interface{}, error) { + return makeExprTerm(currentLocation(c), lhs, rest) } -func (p *parser) callonInfixRelationExpr1() (interface{}, error) { +func (p *parser) callonArithExpr1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onInfixRelationExpr1(stack["left"], stack["operator"], stack["right"]) + return p.cur.onArithExpr1(stack["lhs"], stack["rest"]) } -func (c *current) onInfixRelationOp1(val interface{}) (interface{}, error) { - op := string(c.text) - for _, b := range Builtins { - if string(b.Infix) == op { - op = string(b.Name) - } - } - loc := currentLocation(c) - operator := RefTerm(VarTerm(op).SetLocation(loc)).SetLocation(loc) - return operator, nil +func (c *current) onFactorOperator1(val interface{}) (interface{}, error) { + return makeInfixOperator(currentLocation(c), c.text) } -func (p *parser) callonInfixRelationOp1() (interface{}, error) { +func (p *parser) callonFactorOperator1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onInfixRelationOp1(stack["val"]) + return p.cur.onFactorOperator1(stack["val"]) } -func (c *current) onCall1(name, head, tail interface{}) (interface{}, error) { - buf := []*Term{name.(*Term)} - if head == nil { - return &Expr{Terms: buf}, nil - } - - buf = append(buf, head.(*Term)) +func (c *current) onFactorExpr2(expr interface{}) (interface{}, error) { + return expr, nil +} - // PrefixExpr above describes the "tail" structure. We only care about the "Term" elements. - tailSlice := tail.([]interface{}) - for _, v := range tailSlice { - s := v.([]interface{}) - buf = append(buf, s[len(s)-1].(*Term)) - } +func (p *parser) callonFactorExpr2() (interface{}, error) { + stack := p.vstack[len(p.vstack)-1] + _ = stack + return p.cur.onFactorExpr2(stack["expr"]) +} - return &Expr{Terms: buf}, nil +func (c *current) onFactorExpr10(term interface{}) (interface{}, error) { + return term, nil } -func (p *parser) callonCall1() (interface{}, error) { +func (p *parser) callonFactorExpr10() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onCall1(stack["name"], stack["head"], stack["tail"]) + return p.cur.onFactorExpr10(stack["term"]) } -func (c *current) onOperator1(val interface{}) (interface{}, error) { - term := val.(*Term) - switch term.Value.(type) { - case Ref: - return val, nil - case Var: - return RefTerm(term).SetLocation(currentLocation(c)), nil - default: - panic("unreachable") - } +func (c *current) onCall1(operator, args interface{}) (interface{}, error) { + return makeCall(currentLocation(c), operator, args) } -func (p *parser) callonOperator1() (interface{}, error) { +func (p *parser) callonCall1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onOperator1(stack["val"]) + return p.cur.onCall1(stack["operator"], stack["args"]) } func (c *current) onTerm1(val interface{}) (interface{}, error) { @@ -3670,66 +3345,69 @@ func (p *parser) callonTerm1() (interface{}, error) { return p.cur.onTerm1(stack["val"]) } -func (c *current) onArrayComprehension1(term, body interface{}) (interface{}, error) { - ac := ArrayComprehensionTerm(term.(*Term), body.(Body)) - ac.Location = currentLocation(c) - return ac, nil +func (c *current) onTermPair1(key, value interface{}) (interface{}, error) { + return makeExprTermPair(key, value) +} + +func (p *parser) callonTermPair1() (interface{}, error) { + stack := p.vstack[len(p.vstack)-1] + _ = stack + return p.cur.onTermPair1(stack["key"], stack["value"]) +} + +func (c *current) onArrayComprehension1(head, body interface{}) (interface{}, error) { + return makeArrayComprehension(currentLocation(c), head, body) } func (p *parser) callonArrayComprehension1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onArrayComprehension1(stack["term"], stack["body"]) + return p.cur.onArrayComprehension1(stack["head"], stack["body"]) } -func (c *current) onObjectComprehension1(key, value, body interface{}) (interface{}, error) { - oc := ObjectComprehensionTerm(key.(*Term), value.(*Term), body.(Body)) - oc.Location = currentLocation(c) - return oc, nil +func (c *current) onObjectComprehension1(head, body interface{}) (interface{}, error) { + return makeObjectComprehension(currentLocation(c), head, body) } func (p *parser) callonObjectComprehension1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onObjectComprehension1(stack["key"], stack["value"], stack["body"]) + return p.cur.onObjectComprehension1(stack["head"], stack["body"]) } -func (c *current) onSetComprehension1(term, body interface{}) (interface{}, error) { - sc := SetComprehensionTerm(term.(*Term), body.(Body)) - sc.Location = currentLocation(c) - return sc, nil +func (c *current) onSetComprehension1(head, body interface{}) (interface{}, error) { + return makeSetComprehension(currentLocation(c), head, body) } func (p *parser) callonSetComprehension1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onSetComprehension1(stack["term"], stack["body"]) + return p.cur.onSetComprehension1(stack["head"], stack["body"]) } -func (c *current) onObject1(head, tail interface{}) (interface{}, error) { - return makeObject(head, tail, currentLocation(c)) +func (c *current) onObject1(list interface{}) (interface{}, error) { + return makeObject(currentLocation(c), list) } func (p *parser) callonObject1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onObject1(stack["head"], stack["tail"]) + return p.cur.onObject1(stack["list"]) } -func (c *current) onArray1(head, tail interface{}) (interface{}, error) { - return makeArray(head, tail, currentLocation(c)) +func (c *current) onArray1(list interface{}) (interface{}, error) { + return makeArray(currentLocation(c), list) } func (p *parser) callonArray1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onArray1(stack["head"], stack["tail"]) + return p.cur.onArray1(stack["list"]) } func (c *current) onSetEmpty1() (interface{}, error) { - set := SetTerm() - set.Location = currentLocation(c) - return set, nil + var empty []*Term + return makeSet(currentLocation(c), empty) } func (p *parser) callonSetEmpty1() (interface{}, error) { @@ -3738,69 +3416,44 @@ func (p *parser) callonSetEmpty1() (interface{}, error) { return p.cur.onSetEmpty1() } -func (c *current) onSetNonEmpty1(head, tail interface{}) (interface{}, error) { - set := SetTerm() - set.Location = currentLocation(c) - - val := set.Value.(*Set) - val.Add(head.(*Term)) - - tailSlice := tail.([]interface{}) - for _, v := range tailSlice { - s := v.([]interface{}) - // SetNonEmpty definition above describes the "tail" structure. We only care about the "Term" elements. - val.Add(s[len(s)-1].(*Term)) - } - - return set, nil +func (c *current) onSetNonEmpty1(list interface{}) (interface{}, error) { + return makeSet(currentLocation(c), list) } func (p *parser) callonSetNonEmpty1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onSetNonEmpty1(stack["head"], stack["tail"]) + return p.cur.onSetNonEmpty1(stack["list"]) } -func (c *current) onRef1(head, tail interface{}) (interface{}, error) { - - ref := RefTerm(head.(*Term)) - ref.Location = currentLocation(c) - - tailSlice := tail.([]interface{}) - for _, v := range tailSlice { - ref.Value = append(ref.Value.(Ref), v.(*Term)) - } - - return ref, nil +func (c *current) onRef1(head, rest interface{}) (interface{}, error) { + return makeRef(currentLocation(c), head, rest) } func (p *parser) callonRef1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onRef1(stack["head"], stack["tail"]) + return p.cur.onRef1(stack["head"], stack["rest"]) } -func (c *current) onRefDot1(val interface{}) (interface{}, error) { - // Convert the Var into a string because 'foo.bar.baz' is equivalent to 'foo["bar"]["baz"]'. - str := StringTerm(string(val.(*Term).Value.(Var))) - str.Location = currentLocation(c) - return str, nil +func (c *current) onRefOperandDot1(val interface{}) (interface{}, error) { + return makeRefOperandDot(currentLocation(c), val) } -func (p *parser) callonRefDot1() (interface{}, error) { +func (p *parser) callonRefOperandDot1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onRefDot1(stack["val"]) + return p.cur.onRefOperandDot1(stack["val"]) } -func (c *current) onRefBracket1(val interface{}) (interface{}, error) { +func (c *current) onRefOperandCanonical1(val interface{}) (interface{}, error) { return val, nil } -func (p *parser) callonRefBracket1() (interface{}, error) { +func (p *parser) callonRefOperandCanonical1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onRefBracket1(stack["val"]) + return p.cur.onRefOperandCanonical1(stack["val"]) } func (c *current) onVar1(val interface{}) (interface{}, error) { @@ -3824,10 +3477,7 @@ func (p *parser) callonVarChecked4() (bool, error) { } func (c *current) onVarUnchecked1() (interface{}, error) { - str := string(c.text) - variable := VarTerm(str) - variable.Location = currentLocation(c) - return variable, nil + return makeVar(currentLocation(c), c.text) } func (p *parser) callonVarUnchecked1() (interface{}, error) { @@ -3837,16 +3487,7 @@ func (p *parser) callonVarUnchecked1() (interface{}, error) { } func (c *current) onNumber1() (interface{}, error) { - f, ok := new(big.Float).SetString(string(c.text)) - if !ok { - // This indicates the grammar is out-of-sync with what the string - // representation of floating point numbers. This should not be - // possible. - panic("illegal value") - } - num := NumberTerm(json.Number(f.String())) - num.Location = currentLocation(c) - return num, nil + return makeNumber(currentLocation(c), c.text) } func (p *parser) callonNumber1() (interface{}, error) { @@ -3856,11 +3497,7 @@ func (p *parser) callonNumber1() (interface{}, error) { } func (c *current) onQuotedString1() (interface{}, error) { - var v string - err := json.Unmarshal([]byte(c.text), &v) - str := StringTerm(v) - str.Location = currentLocation(c) - return str, err + return makeString(currentLocation(c), c.text) } func (p *parser) callonQuotedString1() (interface{}, error) { @@ -3870,12 +3507,7 @@ func (p *parser) callonQuotedString1() (interface{}, error) { } func (c *current) onRawString1() (interface{}, error) { - s := string(c.text) - s = s[1 : len(s)-1] // Trim surrounding quotes. - - str := StringTerm(s) - str.Location = currentLocation(c) - return str, nil + return makeRawString(currentLocation(c), c.text) } func (p *parser) callonRawString1() (interface{}, error) { @@ -3884,34 +3516,18 @@ func (p *parser) callonRawString1() (interface{}, error) { return p.cur.onRawString1() } -func (c *current) onBool2() (interface{}, error) { - bol := BooleanTerm(true) - bol.Location = currentLocation(c) - return bol, nil -} - -func (p *parser) callonBool2() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onBool2() -} - -func (c *current) onBool4() (interface{}, error) { - bol := BooleanTerm(false) - bol.Location = currentLocation(c) - return bol, nil +func (c *current) onBool1(val interface{}) (interface{}, error) { + return makeBool(currentLocation(c), c.text) } -func (p *parser) callonBool4() (interface{}, error) { +func (p *parser) callonBool1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onBool4() + return p.cur.onBool1(stack["val"]) } func (c *current) onNull1() (interface{}, error) { - null := NullTerm() - null.Location = currentLocation(c) - return null, nil + return makeNull(currentLocation(c)) } func (p *parser) callonNull1() (interface{}, error) { @@ -3921,14 +3537,7 @@ func (p *parser) callonNull1() (interface{}, error) { } func (c *current) onComment1(text interface{}) (interface{}, error) { - comment := NewComment(ifaceSliceToByteSlice(text)) - comment.Location = currentLocation(c) - - comments := c.globalStore[commentsKey].([]*Comment) - comments = append(comments, comment) - c.globalStore[commentsKey] = comments - - return comment, nil + return makeComments(c, text) } func (p *parser) callonComment1() (interface{}, error) { @@ -3941,15 +3550,85 @@ var ( // errNoRule is returned when the grammar to parse has no rule. errNoRule = errors.New("grammar has no rule") + // errInvalidEntrypoint is returned when the specified entrypoint rule + // does not exit. + errInvalidEntrypoint = errors.New("invalid entrypoint") + // errInvalidEncoding is returned when the source is not properly // utf8-encoded. errInvalidEncoding = errors.New("invalid encoding") + + // errMaxExprCnt is used to signal that the maximum number of + // expressions have been parsed. + errMaxExprCnt = errors.New("max number of expresssions parsed") ) // Option is a function that can set an option on the parser. It returns // the previous setting as an Option. type Option func(*parser) Option +// MaxExpressions creates an Option to stop parsing after the provided +// number of expressions have been parsed, if the value is 0 then the parser will +// parse for as many steps as needed (possibly an infinite number). +// +// The default for maxExprCnt is 0. +func MaxExpressions(maxExprCnt uint64) Option { + return func(p *parser) Option { + oldMaxExprCnt := p.maxExprCnt + p.maxExprCnt = maxExprCnt + return MaxExpressions(oldMaxExprCnt) + } +} + +// Entrypoint creates an Option to set the rule name to use as entrypoint. +// The rule name must have been specified in the -alternate-entrypoints +// if generating the parser with the -optimize-grammar flag, otherwise +// it may have been optimized out. Passing an empty string sets the +// entrypoint to the first rule in the grammar. +// +// The default is to start parsing at the first rule in the grammar. +func Entrypoint(ruleName string) Option { + return func(p *parser) Option { + oldEntrypoint := p.entrypoint + p.entrypoint = ruleName + if ruleName == "" { + p.entrypoint = g.rules[0].name + } + return Entrypoint(oldEntrypoint) + } +} + +// Statistics adds a user provided Stats struct to the parser to allow +// the user to process the results after the parsing has finished. +// Also the key for the "no match" counter is set. +// +// Example usage: +// +// input := "input" +// stats := Stats{} +// _, err := Parse("input-file", []byte(input), Statistics(&stats, "no match")) +// if err != nil { +// log.Panicln(err) +// } +// b, err := json.MarshalIndent(stats.ChoiceAltCnt, "", " ") +// if err != nil { +// log.Panicln(err) +// } +// fmt.Println(string(b)) +// +func Statistics(stats *Stats, choiceNoMatch string) Option { + return func(p *parser) Option { + oldStats := p.Stats + p.Stats = stats + oldChoiceNoMatch := p.choiceNoMatch + p.choiceNoMatch = choiceNoMatch + if p.Stats.ChoiceAltCnt == nil { + p.Stats.ChoiceAltCnt = make(map[string]map[string]int) + } + return Statistics(oldStats, oldChoiceNoMatch) + } +} + // Debug creates an Option to set the debug flag to b. When set to true, // debugging information is printed to stdout while parsing. // @@ -3976,6 +3655,20 @@ func Memoize(b bool) Option { } } +// AllowInvalidUTF8 creates an Option to allow invalid UTF-8 bytes. +// Every invalid UTF-8 byte is treated as a utf8.RuneError (U+FFFD) +// by character class matchers and is matched by the any matcher. +// The returned matched value, c.text and c.offset are NOT affected. +// +// The default is false. +func AllowInvalidUTF8(b bool) Option { + return func(p *parser) Option { + old := p.allowInvalidUTF8 + p.allowInvalidUTF8 = b + return AllowInvalidUTF8(old) + } +} + // Recover creates an Option to set the recover flag to b. When set to // true, this causes the parser to recover from panics and convert it // to an error. Setting it to false can be useful while debugging to @@ -4000,6 +3693,16 @@ func GlobalStore(key string, value interface{}) Option { } } +// InitState creates an Option to set a key to a certain value in +// the global "state" store. +func InitState(key string, value interface{}) Option { + return func(p *parser) Option { + old := p.cur.state[key] + p.cur.state[key] = value + return InitState(key, old) + } +} + // ParseFile parses the file identified by filename. func ParseFile(filename string, opts ...Option) (i interface{}, err error) { f, err := os.Open(filename) @@ -4052,10 +3755,21 @@ type current struct { pos position // start position of the match text []byte // raw text of the match - // the globalStore allows the parser to store arbitrary values - globalStore map[string]interface{} + // state is a store for arbitrary key,value pairs that the user wants to be + // tied to the backtracking of the parser. + // This is always rolled back if a parsing rule fails. + state storeDict + + // globalStore is a general store for the user to store arbitrary key-value + // pairs that they need to manage and that they do not want tied to the + // backtracking of the parser. This is only modified by the user and never + // rolled back by the parser. It is always up to the user to keep this in a + // consistent state. + globalStore storeDict } +type storeDict map[string]interface{} + // the AST types... type grammar struct { @@ -4081,11 +3795,23 @@ type actionExpr struct { run func(*parser) (interface{}, error) } +type recoveryExpr struct { + pos position + expr interface{} + recoverExpr interface{} + failureLabel []string +} + type seqExpr struct { pos position exprs []interface{} } +type throwExpr struct { + pos position + label string +} + type labeledExpr struct { pos position label string @@ -4108,6 +3834,11 @@ type ruleRefExpr struct { name string } +type stateCodeExpr struct { + pos position + run func(*parser) error +} + type andCodeExpr struct { pos position run func(*parser) (bool, error) @@ -4199,6 +3930,10 @@ func (p *parserError) Error() string { // newParser creates a parser with the specified input source and options. func newParser(filename string, b []byte, opts ...Option) *parser { + stats := Stats{ + ChoiceAltCnt: make(map[string]map[string]int), + } + p := &parser{ filename: filename, errs: new(errList), @@ -4206,12 +3941,22 @@ func newParser(filename string, b []byte, opts ...Option) *parser { pt: savepoint{position: position{line: 1}}, recover: true, cur: current{ - globalStore: make(map[string]interface{}), + state: make(storeDict), + globalStore: make(storeDict), }, maxFailPos: position{col: 1, line: 1}, maxFailExpected: make([]string, 0, 20), + Stats: &stats, + // start rule is rule [0] unless an alternate entrypoint is specified + entrypoint: g.rules[0].name, + emptyState: make(storeDict), } p.setOptions(opts) + + if p.maxExprCnt == 0 { + p.maxExprCnt = math.MaxUint64 + } + return p } @@ -4228,6 +3973,30 @@ type resultTuple struct { end savepoint } +const choiceNoMatch = -1 + +// Stats stores some statistics, gathered during parsing +type Stats struct { + // ExprCnt counts the number of expressions processed during parsing + // This value is compared to the maximum number of expressions allowed + // (set by the MaxExpressions option). + ExprCnt uint64 + + // ChoiceAltCnt is used to count for each ordered choice expression, + // which alternative is used how may times. + // These numbers allow to optimize the order of the ordered choice expression + // to increase the performance of the parser + // + // The outer key of ChoiceAltCnt is composed of the name of the rule as well + // as the line and the column of the ordered choice. + // The inner key of ChoiceAltCnt is the number (one-based) of the matching alternative. + // For each alternative the number of matches are counted. If an ordered choice does not + // match, a special counter is incremented. The name of this counter is set with + // the parser option Statistics. + // For an alternative to be included in ChoiceAltCnt, it has to match at least once. + ChoiceAltCnt map[string]map[string]int +} + type parser struct { filename string pt savepoint @@ -4252,13 +4021,26 @@ type parser struct { // rule stack, allows identification of the current rule in errors rstack []*rule - // stats - exprCnt int - // parse fail maxFailPos position maxFailExpected []string maxFailInvertExpected bool + + // max number of expressions to be parsed + maxExprCnt uint64 + // entrypoint for the parser + entrypoint string + + allowInvalidUTF8 bool + + *Stats + + choiceNoMatch string + // recovery expression stack, keeps track of the currently available recovery expression, these are traversed in reverse + recoveryStack []map[string]interface{} + + // emptyState contains an empty storeDict, which is used to optimize cloneState if global "state" store is not used. + emptyState storeDict } // push a variable set on the vstack. @@ -4293,6 +4075,31 @@ func (p *parser) popV() { p.vstack = p.vstack[:len(p.vstack)-1] } +// push a recovery expression with its labels to the recoveryStack +func (p *parser) pushRecovery(labels []string, expr interface{}) { + if cap(p.recoveryStack) == len(p.recoveryStack) { + // create new empty slot in the stack + p.recoveryStack = append(p.recoveryStack, nil) + } else { + // slice to 1 more + p.recoveryStack = p.recoveryStack[:len(p.recoveryStack)+1] + } + + m := make(map[string]interface{}, len(labels)) + for _, fl := range labels { + m[fl] = expr + } + p.recoveryStack[len(p.recoveryStack)-1] = m +} + +// pop a recovery expression from the recoveryStack +func (p *parser) popRecovery() { + // GC that map + p.recoveryStack[len(p.recoveryStack)-1] = nil + + p.recoveryStack = p.recoveryStack[:len(p.recoveryStack)-1] +} + func (p *parser) print(prefix, s string) string { if !p.debug { return s @@ -4372,8 +4179,8 @@ func (p *parser) read() { p.pt.col = 0 } - if rn == utf8.RuneError { - if n == 1 { + if rn == utf8.RuneError && n == 1 { // see utf8.DecodeRune + if !p.allowInvalidUTF8 { p.addErr(errInvalidEncoding) } } @@ -4390,6 +4197,50 @@ func (p *parser) restore(pt savepoint) { p.pt = pt } +// Cloner is implemented by any value that has a Clone method, which returns a +// copy of the value. This is mainly used for types which are not passed by +// value (e.g map, slice, chan) or structs that contain such types. +// +// This is used in conjunction with the global state feature to create proper +// copies of the state to allow the parser to properly restore the state in +// the case of backtracking. +type Cloner interface { + Clone() interface{} +} + +// clone and return parser current state. +func (p *parser) cloneState() storeDict { + if p.debug { + defer p.out(p.in("cloneState")) + } + + if len(p.cur.state) == 0 { + if len(p.emptyState) > 0 { + p.emptyState = make(storeDict) + } + return p.emptyState + } + + state := make(storeDict, len(p.cur.state)) + for k, v := range p.cur.state { + if c, ok := v.(Cloner); ok { + state[k] = c.Clone() + } else { + state[k] = v + } + } + return state +} + +// restore parser current state to the state storeDict. +// every restoreState should applied only one time for every cloned state +func (p *parser) restoreState(state storeDict) { + if p.debug { + defer p.out(p.in("restoreState")) + } + p.cur.state = state +} + // get the slice of bytes from the savepoint start to the current position. func (p *parser) sliceFrom(start savepoint) []byte { return p.data[start.position.offset:p.pt.position.offset] @@ -4455,9 +4306,14 @@ func (p *parser) parse(g *grammar) (val interface{}, err error) { }() } - // start rule is rule [0] + startRule, ok := p.rules[p.entrypoint] + if !ok { + p.addErr(errInvalidEntrypoint) + return nil, p.errs.err() + } + p.read() // advance to first rune - val, ok := p.parseRule(g.rules[0]) + val, ok = p.parseRule(startRule) if !ok { if len(*p.errs) == 0 { // If parsing fails, but no errors have been recorded, the expected values @@ -4481,6 +4337,7 @@ func (p *parser) parse(g *grammar) (val interface{}, err error) { } p.addErrAt(errors.New("no match found, expected: "+listJoin(expected, ", ", "or")), p.maxFailPos, expected) } + return nil, p.errs.err() } return val, p.errs.err() @@ -4538,7 +4395,11 @@ func (p *parser) parseExpr(expr interface{}) (interface{}, bool) { pt = p.pt } - p.exprCnt++ + p.ExprCnt++ + if p.ExprCnt > p.maxExprCnt { + panic(errMaxExprCnt) + } + var val interface{} var ok bool switch expr := expr.(type) { @@ -4564,10 +4425,16 @@ func (p *parser) parseExpr(expr interface{}) (interface{}, bool) { val, ok = p.parseNotExpr(expr) case *oneOrMoreExpr: val, ok = p.parseOneOrMoreExpr(expr) + case *recoveryExpr: + val, ok = p.parseRecoveryExpr(expr) case *ruleRefExpr: val, ok = p.parseRuleRefExpr(expr) case *seqExpr: val, ok = p.parseSeqExpr(expr) + case *stateCodeExpr: + val, ok = p.parseStateCodeExpr(expr) + case *throwExpr: + val, ok = p.parseThrowExpr(expr) case *zeroOrMoreExpr: val, ok = p.parseZeroOrMoreExpr(expr) case *zeroOrOneExpr: @@ -4591,10 +4458,13 @@ func (p *parser) parseActionExpr(act *actionExpr) (interface{}, bool) { if ok { p.cur.pos = start.position p.cur.text = p.sliceFrom(start) + state := p.cloneState() actVal, err := act.run(p) if err != nil { p.addErrAt(err, start.position, []string{}) } + p.restoreState(state) + val = actVal } if ok && p.debug { @@ -4608,10 +4478,14 @@ func (p *parser) parseAndCodeExpr(and *andCodeExpr) (interface{}, bool) { defer p.out(p.in("parseAndCodeExpr")) } + state := p.cloneState() + ok, err := and.run(p) if err != nil { p.addErr(err) } + p.restoreState(state) + return nil, ok } @@ -4621,10 +4495,13 @@ func (p *parser) parseAndExpr(and *andExpr) (interface{}, bool) { } pt := p.pt + state := p.cloneState() p.pushV() _, ok := p.parseExpr(and.expr) p.popV() + p.restoreState(state) p.restore(pt) + return nil, ok } @@ -4633,14 +4510,15 @@ func (p *parser) parseAnyMatcher(any *anyMatcher) (interface{}, bool) { defer p.out(p.in("parseAnyMatcher")) } - if p.pt.rn != utf8.RuneError { - start := p.pt - p.read() - p.failAt(true, start.position, ".") - return p.sliceFrom(start), true + if p.pt.rn == utf8.RuneError && p.pt.w == 0 { + // EOF - see utf8.DecodeRune + p.failAt(false, p.pt.position, ".") + return nil, false } - p.failAt(false, p.pt.position, ".") - return nil, false + start := p.pt + p.read() + p.failAt(true, start.position, ".") + return p.sliceFrom(start), true } func (p *parser) parseCharClassMatcher(chr *charClassMatcher) (interface{}, bool) { @@ -4652,7 +4530,7 @@ func (p *parser) parseCharClassMatcher(chr *charClassMatcher) (interface{}, bool start := p.pt // can't match EOF - if cur == utf8.RuneError { + if cur == utf8.RuneError && p.pt.w == 0 { // see utf8.DecodeRune p.failAt(false, start.position, chr.val) return nil, false } @@ -4709,19 +4587,42 @@ func (p *parser) parseCharClassMatcher(chr *charClassMatcher) (interface{}, bool return nil, false } +func (p *parser) incChoiceAltCnt(ch *choiceExpr, altI int) { + choiceIdent := fmt.Sprintf("%s %d:%d", p.rstack[len(p.rstack)-1].name, ch.pos.line, ch.pos.col) + m := p.ChoiceAltCnt[choiceIdent] + if m == nil { + m = make(map[string]int) + p.ChoiceAltCnt[choiceIdent] = m + } + // We increment altI by 1, so the keys do not start at 0 + alt := strconv.Itoa(altI + 1) + if altI == choiceNoMatch { + alt = p.choiceNoMatch + } + m[alt]++ +} + func (p *parser) parseChoiceExpr(ch *choiceExpr) (interface{}, bool) { if p.debug { defer p.out(p.in("parseChoiceExpr")) } - for _, alt := range ch.alternatives { + for altI, alt := range ch.alternatives { + // dummy assignment to prevent compile error if optimized + _ = altI + + state := p.cloneState() + p.pushV() val, ok := p.parseExpr(alt) p.popV() if ok { + p.incChoiceAltCnt(ch, altI) return val, ok } + p.restoreState(state) } + p.incChoiceAltCnt(ch, choiceNoMatch) return nil, false } @@ -4772,10 +4673,14 @@ func (p *parser) parseNotCodeExpr(not *notCodeExpr) (interface{}, bool) { defer p.out(p.in("parseNotCodeExpr")) } + state := p.cloneState() + ok, err := not.run(p) if err != nil { p.addErr(err) } + p.restoreState(state) + return nil, !ok } @@ -4785,12 +4690,15 @@ func (p *parser) parseNotExpr(not *notExpr) (interface{}, bool) { } pt := p.pt + state := p.cloneState() p.pushV() p.maxFailInvertExpected = !p.maxFailInvertExpected _, ok := p.parseExpr(not.expr) p.maxFailInvertExpected = !p.maxFailInvertExpected p.popV() + p.restoreState(state) p.restore(pt) + return nil, !ok } @@ -4816,6 +4724,18 @@ func (p *parser) parseOneOrMoreExpr(expr *oneOrMoreExpr) (interface{}, bool) { } } +func (p *parser) parseRecoveryExpr(recover *recoveryExpr) (interface{}, bool) { + if p.debug { + defer p.out(p.in("parseRecoveryExpr (" + strings.Join(recover.failureLabel, ",") + ")")) + } + + p.pushRecovery(recover.failureLabel, recover.recoverExpr) + val, ok := p.parseExpr(recover.expr) + p.popRecovery() + + return val, ok +} + func (p *parser) parseRuleRefExpr(ref *ruleRefExpr) (interface{}, bool) { if p.debug { defer p.out(p.in("parseRuleRefExpr " + ref.name)) @@ -4841,9 +4761,11 @@ func (p *parser) parseSeqExpr(seq *seqExpr) (interface{}, bool) { vals := make([]interface{}, 0, len(seq.exprs)) pt := p.pt + state := p.cloneState() for _, expr := range seq.exprs { val, ok := p.parseExpr(expr) if !ok { + p.restoreState(state) p.restore(pt) return nil, false } @@ -4852,6 +4774,34 @@ func (p *parser) parseSeqExpr(seq *seqExpr) (interface{}, bool) { return vals, true } +func (p *parser) parseStateCodeExpr(state *stateCodeExpr) (interface{}, bool) { + if p.debug { + defer p.out(p.in("parseStateCodeExpr")) + } + + err := state.run(p) + if err != nil { + p.addErr(err) + } + return nil, true +} + +func (p *parser) parseThrowExpr(expr *throwExpr) (interface{}, bool) { + if p.debug { + defer p.out(p.in("parseThrowExpr")) + } + + for i := len(p.recoveryStack) - 1; i >= 0; i-- { + if recoverExpr, ok := p.recoveryStack[i][expr.label]; ok { + if val, ok := p.parseExpr(recoverExpr); ok { + return val, ok + } + } + } + + return nil, false +} + func (p *parser) parseZeroOrMoreExpr(expr *zeroOrMoreExpr) (interface{}, bool) { if p.debug { defer p.out(p.in("parseZeroOrMoreExpr")) diff --git a/github.com/open-policy-agent/opa/ast/parser_ext.go b/github.com/open-policy-agent/opa/ast/parser_ext.go index fb97c98e..9562d543 100644 --- a/github.com/open-policy-agent/opa/ast/parser_ext.go +++ b/github.com/open-policy-agent/opa/ast/parser_ext.go @@ -121,7 +121,7 @@ func MustParseTerm(input string) *Term { func ParseRuleFromBody(module *Module, body Body) (*Rule, error) { if len(body) != 1 { - return nil, fmt.Errorf("multiple %vs cannot be used for %v", ExprTypeName, HeadTypeName) + return nil, fmt.Errorf("multiple expressions cannot be used for rule head") } return ParseRuleFromExpr(module, body[0]) @@ -132,22 +132,25 @@ func ParseRuleFromBody(module *Module, body Body) (*Rule, error) { func ParseRuleFromExpr(module *Module, expr *Expr) (*Rule, error) { if len(expr.With) > 0 { - return nil, fmt.Errorf("%vs using %v cannot be used for %v", ExprTypeName, WithTypeName, HeadTypeName) + return nil, fmt.Errorf("expressions using with keyword cannot be used for rule head") } if expr.Negated { - return nil, fmt.Errorf("negated %v cannot be used for %v", TypeName(expr), RuleTypeName) + return nil, fmt.Errorf("negated expressions cannot be used for rule head") } - if !expr.IsCall() { - return ParsePartialSetDocRuleFromTerm(module, expr.Terms.(*Term)) + if term, ok := expr.Terms.(*Term); ok { + switch v := term.Value.(type) { + case Ref: + return ParsePartialSetDocRuleFromTerm(module, term) + default: + return nil, fmt.Errorf("%v cannot be used for rule name", TypeName(v)) + } } - if !expr.IsEquality() { - for _, bi := range Builtins { - if expr.Operator().Equal(bi.Ref()) { - return nil, fmt.Errorf("%v name conflicts with built-in function", RuleTypeName) - } + if !expr.IsEquality() && expr.IsCall() { + if _, ok := BuiltinMap[expr.Operator().String()]; ok { + return nil, fmt.Errorf("rule name conflicts with built-in function") } return ParseRuleFromCallExpr(module, expr.Terms.([]*Term)) } @@ -159,6 +162,11 @@ func ParseRuleFromExpr(module *Module, expr *Expr) (*Rule, error) { return rule, nil } + rule, err = ParseRuleFromCallEqExpr(module, lhs, rhs) + if err == nil { + return rule, nil + } + return ParsePartialObjectDocRuleFromEqExpr(module, lhs, rhs) } @@ -173,7 +181,7 @@ func ParseCompleteDocRuleFromEqExpr(module *Module, lhs, rhs *Term) (*Rule, erro } else if v, ok := lhs.Value.(Var); ok { name = v } else { - return nil, fmt.Errorf("%v cannot be used for name of %v", TypeName(lhs.Value), RuleTypeName) + return nil, fmt.Errorf("%v cannot be used for rule name", TypeName(lhs.Value)) } rule := &Rule{ @@ -189,8 +197,6 @@ func ParseCompleteDocRuleFromEqExpr(module *Module, lhs, rhs *Term) (*Rule, erro Module: module, } - rule.Body[0].Location = rhs.Location - return rule, nil } @@ -200,7 +206,7 @@ func ParsePartialObjectDocRuleFromEqExpr(module *Module, lhs, rhs *Term) (*Rule, ref, ok := lhs.Value.(Ref) if !ok || len(ref) != 2 { - return nil, fmt.Errorf("%v cannot be used for name of %v", TypeName(lhs.Value), RuleTypeName) + return nil, fmt.Errorf("%v cannot be used for rule name", TypeName(lhs.Value)) } name := ref[0].Value.(Var) @@ -220,7 +226,6 @@ func ParsePartialObjectDocRuleFromEqExpr(module *Module, lhs, rhs *Term) (*Rule, Module: module, } - rule.Body[0].Location = rhs.Location return rule, nil } @@ -230,11 +235,11 @@ func ParsePartialSetDocRuleFromTerm(module *Module, term *Term) (*Rule, error) { ref, ok := term.Value.(Ref) if !ok { - return nil, fmt.Errorf("%vs cannot be used for %v", TypeName(term.Value), HeadTypeName) + return nil, fmt.Errorf("%vs cannot be used for rule head", TypeName(term.Value)) } if len(ref) != 2 { - return nil, fmt.Errorf("%v cannot be used for %v", RefTypeName, RuleTypeName) + return nil, fmt.Errorf("refs cannot be used for rule") } rule := &Rule{ @@ -253,24 +258,42 @@ func ParsePartialSetDocRuleFromTerm(module *Module, term *Term) (*Rule, error) { return rule, nil } +// ParseRuleFromCallEqExpr returns a rule if the term can be interpreted as a +// function definition (e.g., f(x) = y => f(x) = y { true }). +func ParseRuleFromCallEqExpr(module *Module, lhs, rhs *Term) (*Rule, error) { + + call, ok := lhs.Value.(Call) + if !ok { + return nil, fmt.Errorf("must be call") + } + + rule := &Rule{ + Location: lhs.Location, + Head: &Head{ + Location: lhs.Location, + Name: call[0].Value.(Ref)[0].Value.(Var), + Args: Args(call[1:]), + Value: rhs, + }, + Body: NewBody(NewExpr(BooleanTerm(true).SetLocation(rhs.Location).SetLocation(rhs.Location))), + Module: module, + } + + return rule, nil +} + // ParseRuleFromCallExpr returns a rule if the terms can be interpreted as a -// function returning true or some value (e.g., f(x) => f(x) = true { true }, -// f(x) = y => f(x) = y { true }). +// function returning true or some value (e.g., f(x) => f(x) = true { true }). func ParseRuleFromCallExpr(module *Module, terms []*Term) (*Rule, error) { - var args Args - var value *Term - loc := terms[0].Location if len(terms) <= 1 { - return nil, fmt.Errorf("%ss with %v must take at least one argument", RuleTypeName, ArgsTypeName) - } else if len(terms) == 2 { - args = Args{terms[1]} - value = BooleanTerm(true).SetLocation(loc) - } else { - args = terms[1 : len(terms)-1] - value = terms[len(terms)-1] + return nil, fmt.Errorf("rule argument list must take at least one argument") } + loc := terms[0].Location + args := terms[1:] + value := BooleanTerm(true).SetLocation(loc) + rule := &Rule{ Location: loc, Head: &Head{ @@ -502,7 +525,7 @@ func parseModule(stmts []Statement, comments []*Comment) (*Module, error) { _package, ok := stmts[0].(*Package) if !ok { loc := stmts[0].(Statement).Loc() - errs = append(errs, NewError(ParseErr, loc, "expected %v", PackageTypeName)) + errs = append(errs, NewError(ParseErr, loc, "package expected")) } mod := &Module{ @@ -527,7 +550,7 @@ func parseModule(stmts []Statement, comments []*Comment) (*Module, error) { mod.Rules = append(mod.Rules, rule) } case *Package: - errs = append(errs, NewError(ParseErr, stmt.Loc(), "unexpected "+PackageTypeName)) + errs = append(errs, NewError(ParseErr, stmt.Loc(), "unexpected package")) case *Comment: // Ignore comments, they're handled above. default: panic("illegal value") // Indicates grammar is out-of-sync with code. @@ -597,10 +620,10 @@ func setExprIndices(x interface{}) { } func mangleWildcards(stmts []Statement) { - - mangler := &wildcardMangler{} - for _, stmt := range stmts { - Walk(mangler, stmt) + m := &wildcardMangler{} + for i := range stmts { + stmt, _ := Transform(m, stmts[i]) + stmts[i] = stmt.(Statement) } } @@ -608,17 +631,15 @@ type wildcardMangler struct { c int } -func (vis *wildcardMangler) Visit(x interface{}) Visitor { - term, ok := x.(*Term) - if !ok { - return vis - } - if term.Equal(Wildcard) { - name := fmt.Sprintf("%s%d", WildcardPrefix, vis.c) - term.Value = Var(name) - vis.c++ +func (m *wildcardMangler) Transform(x interface{}) (interface{}, error) { + if term, ok := x.(Var); ok { + if term.Equal(Wildcard.Value) { + name := fmt.Sprintf("%s%d", WildcardPrefix, m.c) + m.c++ + return Var(name), nil + } } - return vis + return x, nil } func setRuleModule(rule *Rule, module *Module) { diff --git a/github.com/open-policy-agent/opa/ast/parser_internal.go b/github.com/open-policy-agent/opa/ast/parser_internal.go new file mode 100644 index 00000000..ffcccca4 --- /dev/null +++ b/github.com/open-policy-agent/opa/ast/parser_internal.go @@ -0,0 +1,565 @@ +// Copyright 2018 The OPA Authors. All rights reserved. +// Use of this source code is governed by an Apache2 +// license that can be found in the LICENSE file.op + +package ast + +import ( + "bytes" + "encoding/json" + "fmt" + "math/big" +) + +const ( + // commentsKey is the global map key for the comments slice. + commentsKey = "comments" + + // filenameKey is the global map key for the filename. + filenameKey = "filename" +) + +type program struct { + buf []interface{} + comments interface{} +} + +type ruleExt struct { + loc *Location + term *Term + body Body +} + +// currentLocation converts the parser context to a Location object. +func currentLocation(c *current) *Location { + return NewLocation(c.text, c.globalStore[filenameKey].(string), c.pos.line, c.pos.col) +} + +func makeProgram(c *current, vals interface{}) (interface{}, error) { + var buf []interface{} + if vals == nil { + return buf, nil + } + ifaceSlice := vals.([]interface{}) + head := ifaceSlice[0] + buf = append(buf, head) + for _, tail := range ifaceSlice[1].([]interface{}) { + stmt := tail.([]interface{})[1] + buf = append(buf, stmt) + } + return program{buf, c.globalStore[commentsKey]}, nil +} + +func makePackage(loc *Location, value interface{}) (interface{}, error) { + // All packages are implicitly declared under the default root document. + term := value.(*Term) + path := Ref{DefaultRootDocument.Copy().SetLocation(term.Location)} + switch v := term.Value.(type) { + case Ref: + // Convert head of package Ref to String because it will be prefixed + // with the root document variable. + head := StringTerm(string(v[0].Value.(Var))).SetLocation(v[0].Location) + tail := v[1:] + if !tail.IsGround() { + return nil, fmt.Errorf("package name cannot contain variables: %v", v) + } + + // We do not allow non-string values in package names. + // Because documents are typically represented as JSON, non-string keys are + // not allowed for now. + // TODO(tsandall): consider special syntax for namespacing under arrays. + for _, p := range tail { + _, ok := p.Value.(String) + if !ok { + return nil, fmt.Errorf("package name cannot contain non-string values: %v", v) + } + } + path = append(path, head) + path = append(path, tail...) + case Var: + s := StringTerm(string(v)).SetLocation(term.Location) + path = append(path, s) + } + pkg := &Package{Location: loc, Path: path} + return pkg, nil +} + +func makeImport(loc *Location, path, alias interface{}) (interface{}, error) { + imp := &Import{} + imp.Location = loc + imp.Path = path.(*Term) + if err := IsValidImportPath(imp.Path.Value); err != nil { + return nil, err + } + if alias == nil { + return imp, nil + } + aliasSlice := alias.([]interface{}) + // Import definition above describes the "alias" slice. We only care about the "Var" element. + imp.Alias = aliasSlice[3].(*Term).Value.(Var) + return imp, nil +} + +func makeDefaultRule(loc *Location, name, value interface{}) (interface{}, error) { + + term := value.(*Term) + var err error + + vis := NewGenericVisitor(func(x interface{}) bool { + if err != nil { + return true + } + switch x.(type) { + case *ArrayComprehension, *ObjectComprehension, *SetComprehension: // skip closures + return true + case Ref, Var: + err = fmt.Errorf("default rule value cannot contain %v", TypeName(x)) + return true + } + return false + }) + + Walk(vis, term) + + if err != nil { + return nil, err + } + + body := NewBody(NewExpr(BooleanTerm(true).SetLocation(loc))) + + rule := &Rule{ + Location: loc, + Default: true, + Head: &Head{ + Location: loc, + Name: name.(*Term).Value.(Var), + Value: value.(*Term), + }, + Body: body, + } + rule.Body[0].Location = loc + + return []*Rule{rule}, nil +} + +func makeRule(loc *Location, head, rest interface{}) (interface{}, error) { + + if head == nil { + return nil, nil + } + + sl := rest.([]interface{}) + + rules := []*Rule{ + &Rule{ + Location: loc, + Head: head.(*Head), + Body: sl[0].(Body), + }, + } + + var ordered bool + prev := rules[0] + + for i, elem := range sl[1].([]interface{}) { + + next := elem.([]interface{}) + re := next[1].(ruleExt) + + if re.term == nil { + if ordered { + return nil, fmt.Errorf("expected 'else' keyword") + } + rules = append(rules, &Rule{ + Location: re.loc, + Head: prev.Head.Copy(), + Body: re.body, + }) + } else { + if (rules[0].Head.DocKind() != CompleteDoc) || (i != 0 && !ordered) { + return nil, fmt.Errorf("unexpected 'else' keyword") + } + ordered = true + curr := &Rule{ + Location: re.loc, + Head: &Head{ + Name: prev.Head.Name, + Args: prev.Head.Args.Copy(), + Value: re.term, + Location: re.term.Location, + }, + Body: re.body, + } + prev.Else = curr + prev = curr + } + } + + return rules, nil +} + +func makeRuleHead(loc *Location, name, args, key, value interface{}) (interface{}, error) { + + head := &Head{} + + head.Location = loc + head.Name = name.(*Term).Value.(Var) + + if args != nil && key != nil { + return nil, fmt.Errorf("partial rules cannot take arguments") + } + + if args != nil { + argSlice := args.([]interface{}) + head.Args = argSlice[3].(Args) + } + + if key != nil { + keySlice := key.([]interface{}) + // Head definition above describes the "key" slice. We care about the "Term" element. + head.Key = keySlice[3].(*Term) + } + + if value != nil { + valueSlice := value.([]interface{}) + // Head definition above describes the "value" slice. We care about the "Term" element. + head.Value = valueSlice[len(valueSlice)-1].(*Term) + } + + if key == nil && value == nil { + head.Value = BooleanTerm(true).SetLocation(head.Location) + } + + if key != nil && value != nil { + switch head.Key.Value.(type) { + case Var, String, Ref: // nop + default: + return nil, fmt.Errorf("object key must be string, var, or ref, not %v", TypeName(head.Key.Value)) + } + } + + return head, nil +} + +func makeArgs(list interface{}) (interface{}, error) { + termSlice := list.([]*Term) + args := make(Args, len(termSlice)) + for i := 0; i < len(args); i++ { + args[i] = termSlice[i] + } + return args, nil +} + +func makeRuleExt(loc *Location, val, b interface{}) (interface{}, error) { + bs := b.([]interface{}) + body := bs[1].(Body) + + if val == nil { + term := BooleanTerm(true) + term.Location = loc + return ruleExt{term.Location, term, body}, nil + } + + vs := val.([]interface{}) + t := vs[3].(*Term) + return ruleExt{loc, t, body}, nil +} + +func makeLiteral(negated, value, with interface{}) (interface{}, error) { + + expr := value.(*Expr) + + expr.Negated = negated.(bool) + + if with != nil { + expr.With = with.([]*With) + } + + return expr, nil +} + +func makeLiteralExpr(loc *Location, lhs, rest interface{}) (interface{}, error) { + + if rest == nil { + if call, ok := lhs.(*Term).Value.(Call); ok { + return NewExpr([]*Term(call)).SetLocation(loc), nil + } + return NewExpr(lhs).SetLocation(loc), nil + } + + termSlice := rest.([]interface{}) + terms := []*Term{ + termSlice[1].(*Term), + lhs.(*Term), + termSlice[3].(*Term), + } + + expr := NewExpr(terms).SetLocation(loc) + + return expr, nil +} + +func makeWithKeywordList(head, tail interface{}) (interface{}, error) { + var withs []*With + + if head == nil { + return withs, nil + } + + sl := tail.([]interface{}) + + withs = make([]*With, 0, len(sl)+1) + withs = append(withs, head.(*With)) + + for i := range sl { + withSlice := sl[i].([]interface{}) + withs = append(withs, withSlice[1].(*With)) + } + + return withs, nil +} + +func makeWithKeyword(loc *Location, target, value interface{}) (interface{}, error) { + w := &With{ + Target: target.(*Term), + Value: value.(*Term), + } + return w.SetLocation(loc), nil +} + +func makeExprTerm(loc *Location, lhs, rest interface{}) (interface{}, error) { + + if rest == nil { + return lhs, nil + } + + sl := rest.([]interface{}) + + if len(sl) == 0 { + return lhs, nil + } + + for i := range sl { + termSlice := sl[i].([]interface{}) + call := Call{ + termSlice[1].(*Term), + lhs.(*Term), + termSlice[3].(*Term), + } + lhs = NewTerm(call).SetLocation(loc) + } + + return lhs, nil +} + +func makeCall(loc *Location, operator, args interface{}) (interface{}, error) { + + termSlice := args.([]*Term) + termOperator := operator.(*Term) + + call := make(Call, len(termSlice)+1) + + if _, ok := termOperator.Value.(Var); ok { + termOperator = RefTerm(termOperator).SetLocation(loc) + } + + call[0] = termOperator + + for i := 1; i < len(call); i++ { + call[i] = termSlice[i-1] + } + + return NewTerm(call).SetLocation(loc), nil +} + +func makeBraceEnclosedBody(loc *Location, body interface{}) (interface{}, error) { + if body != nil { + return body, nil + } + return NewBody(NewExpr(ObjectTerm().SetLocation(loc)).SetLocation(loc)), nil +} + +func makeBody(head, tail interface{}, pos int) (interface{}, error) { + + sl := tail.([]interface{}) + body := make(Body, len(sl)+1) + body[0] = head.(*Expr) + + for i := 1; i < len(body); i++ { + body[i] = sl[i-1].([]interface{})[pos].(*Expr) + } + + return body, nil +} + +func makeExprTermList(head, tail interface{}) (interface{}, error) { + + var terms []*Term + + if head == nil { + return terms, nil + } + + sl := tail.([]interface{}) + + terms = make([]*Term, 0, len(sl)+1) + terms = append(terms, head.(*Term)) + + for i := range sl { + termSlice := sl[i].([]interface{}) + terms = append(terms, termSlice[3].(*Term)) + } + + return terms, nil +} + +func makeExprTermPairList(head, tail interface{}) (interface{}, error) { + + var terms [][2]*Term + + if head == nil { + return terms, nil + } + + sl := tail.([]interface{}) + + terms = make([][2]*Term, 0, len(sl)+1) + terms = append(terms, head.([2]*Term)) + + for i := range sl { + termSlice := sl[i].([]interface{}) + terms = append(terms, termSlice[3].([2]*Term)) + } + + return terms, nil +} + +func makeExprTermPair(key, value interface{}) (interface{}, error) { + return [2]*Term{key.(*Term), value.(*Term)}, nil +} + +func makeInfixOperator(loc *Location, text []byte) (interface{}, error) { + op := string(text) + for _, b := range Builtins { + if string(b.Infix) == op { + op = string(b.Name) + } + } + operator := RefTerm(VarTerm(op).SetLocation(loc)).SetLocation(loc) + return operator, nil +} + +func makeArray(loc *Location, list interface{}) (interface{}, error) { + termSlice := list.([]*Term) + return ArrayTerm(termSlice...).SetLocation(loc), nil +} + +func makeObject(loc *Location, list interface{}) (interface{}, error) { + termPairSlice := list.([][2]*Term) + return ObjectTerm(termPairSlice...).SetLocation(loc), nil +} + +func makeSet(loc *Location, list interface{}) (interface{}, error) { + termSlice := list.([]*Term) + return SetTerm(termSlice...).SetLocation(loc), nil +} + +func makeArrayComprehension(loc *Location, head, body interface{}) (interface{}, error) { + return ArrayComprehensionTerm(head.(*Term), body.(Body)).SetLocation(loc), nil +} + +func makeSetComprehension(loc *Location, head, body interface{}) (interface{}, error) { + return SetComprehensionTerm(head.(*Term), body.(Body)).SetLocation(loc), nil +} + +func makeObjectComprehension(loc *Location, head, body interface{}) (interface{}, error) { + pair := head.([2]*Term) + return ObjectComprehensionTerm(pair[0], pair[1], body.(Body)).SetLocation(loc), nil +} + +func makeRef(loc *Location, head, rest interface{}) (interface{}, error) { + + headTerm := head.(*Term) + ifaceSlice := rest.([]interface{}) + + ref := make(Ref, len(ifaceSlice)+1) + ref[0] = headTerm + + for i := 1; i < len(ref); i++ { + ref[i] = ifaceSlice[i-1].(*Term) + } + + return NewTerm(ref).SetLocation(loc), nil +} + +func makeRefOperandDot(loc *Location, val interface{}) (interface{}, error) { + return StringTerm(string(val.(*Term).Value.(Var))).SetLocation(loc), nil +} + +func makeVar(loc *Location, text interface{}) (interface{}, error) { + str := string(text.([]byte)) + return VarTerm(str).SetLocation(loc), nil +} + +func makeNumber(loc *Location, text interface{}) (interface{}, error) { + f, ok := new(big.Float).SetString(string(text.([]byte))) + if !ok { + // This indicates the grammar is out-of-sync with what the string + // representation of floating point numbers. This should not be + // possible. + panic("illegal value") + } + return NumberTerm(json.Number(f.String())).SetLocation(loc), nil +} + +func makeString(loc *Location, text interface{}) (interface{}, error) { + var v string + err := json.Unmarshal(text.([]byte), &v) + return StringTerm(v).SetLocation(loc), err +} + +func makeRawString(loc *Location, text interface{}) (interface{}, error) { + s := string(text.([]byte)) + s = s[1 : len(s)-1] // Trim surrounding quotes. + return StringTerm(s).SetLocation(loc), nil +} + +func makeBool(loc *Location, text interface{}) (interface{}, error) { + var term *Term + if string(text.([]byte)) == "true" { + term = BooleanTerm(true) + } else { + term = BooleanTerm(false) + } + return term.SetLocation(loc), nil +} + +func makeNull(loc *Location) (interface{}, error) { + return NullTerm().SetLocation(loc), nil +} + +func makeComments(c *current, text interface{}) (interface{}, error) { + + var buf bytes.Buffer + for _, x := range text.([]interface{}) { + buf.Write(x.([]byte)) + } + + comment := NewComment(buf.Bytes()) + comment.Location = currentLocation(c) + comments := c.globalStore[commentsKey].([]*Comment) + comments = append(comments, comment) + c.globalStore[commentsKey] = comments + + return comment, nil +} + +func ifacesToBody(i interface{}, a ...interface{}) Body { + var buf Body + buf = append(buf, i.(*Expr)) + for _, s := range a { + expr := s.([]interface{})[3].(*Expr) + buf = append(buf, expr) + } + return buf +} diff --git a/github.com/open-policy-agent/opa/ast/policy.go b/github.com/open-policy-agent/opa/ast/policy.go index eae57c05..031d01f8 100644 --- a/github.com/open-policy-agent/opa/ast/policy.go +++ b/github.com/open-policy-agent/opa/ast/policy.go @@ -6,12 +6,20 @@ package ast import ( "fmt" + "math/rand" "strings" + "time" - "github.com/open-policy-agent/opa/types" "github.com/open-policy-agent/opa/util" ) +// Initialize seed for term hashing. This is intentionally placed before the +// root document sets are constructed to ensure they use the same hash seed as +// subsequent lookups. If the hash seeds are out of sync, lookups will fail. +var hashSeed = rand.New(rand.NewSource(time.Now().UnixNano())) +var hashSeed0 = (uint64(hashSeed.Uint32()) << 32) | uint64(hashSeed.Uint32()) +var hashSeed1 = (uint64(hashSeed.Uint32()) << 32) | uint64(hashSeed.Uint32()) + // DefaultRootDocument is the default root document. // // All package directives inside source files are implicitly prefixed with the @@ -23,10 +31,10 @@ var InputRootDocument = VarTerm("input") // RootDocumentNames contains the names of top-level documents that can be // referred to in modules and queries. -var RootDocumentNames = &Set{ +var RootDocumentNames = NewSet( DefaultRootDocument, InputRootDocument, -} +) // DefaultRootRef is a reference to the root of the default document. // @@ -40,10 +48,10 @@ var InputRootRef = Ref{InputRootDocument} // RootDocumentRefs contains the prefixes of top-level documents that all // non-local references start with. -var RootDocumentRefs = &Set{ +var RootDocumentRefs = NewSet( NewTerm(DefaultRootRef), NewTerm(InputRootRef), -} +) // SystemDocumentKey is the name of the top-level key that identifies the system // document. @@ -166,7 +174,6 @@ type ( Negated bool `json:"negated,omitempty"` Terms interface{} `json:"terms"` With []*With `json:"with,omitempty"` - Infix bool `json:"infix,omitempty"` } // With represents a modifier on an expression. @@ -307,11 +314,11 @@ func IsValidImportPath(v Value) (err error) { } for _, e := range v[1:] { if _, ok := e.Value.(String); !ok { - return fmt.Errorf("invalid path %v: path elements must be %vs", v, StringTypeName) + return fmt.Errorf("invalid path %v: path elements must be strings", v) } } default: - return fmt.Errorf("invalid path %v: path must be %v or %v", v, RefTypeName, VarTypeName) + return fmt.Errorf("invalid path %v: path must be ref or var", v) } return nil } @@ -617,6 +624,13 @@ func (body *Body) Append(expr *Expr) { *body = append(*body, expr) } +// Set sets the expr in the body at the specified position and updates the +// expr's index accordingly. +func (body Body) Set(expr *Expr, pos int) { + body[pos] = expr + expr.Index = pos +} + // Compare returns an integer indicating whether body is less than, equal to, // or greater than other. // @@ -688,16 +702,6 @@ func (body Body) Loc() *Location { return body[0].Location } -// OutputVars returns a VarSet containing the variables that would be bound by evaluating -// the body. -func (body Body) OutputVars(safe VarSet) VarSet { - o := safe.Copy() - for _, e := range body { - o.Update(e.OutputVars(o)) - } - return o.Diff(safe) -} - func (body Body) String() string { var buf []string for _, v := range body { @@ -860,6 +864,15 @@ func (expr *Expr) IsEquality() bool { return terms[0].Value.Compare(Equality.Ref()) == 0 } +// IsAssignment returns true if this an assignment expression. +func (expr *Expr) IsAssignment() bool { + terms, ok := expr.Terms.([]*Term) + if !ok { + return false + } + return terms[0].Value.Compare(Assign.Ref()) == 0 +} + // IsCall returns true if this expression calls a function. func (expr *Expr) IsCall() bool { _, ok := expr.Terms.([]*Term) @@ -914,33 +927,11 @@ func (expr *Expr) IsGround() bool { return true } -// OutputVars returns a VarSet containing variables that would be bound by evaluating -// this expression. -func (expr *Expr) OutputVars(safe VarSet) VarSet { - if !expr.Negated { - - // Currently the with modifier does not produce any outputs. Any - // variables in the value must be safe before the expression can be - // evaluated. - if !expr.withModifierSafe(safe) { - return VarSet{} - } - - switch terms := expr.Terms.(type) { - case *Term: - return expr.outputVarsRefs(safe) - case []*Term: - name := terms[0].String() - if b := BuiltinMap[name]; b != nil { - if b.Name == Equality.Name { - return expr.outputVarsEquality(safe) - } - return expr.outputVarsBuiltins(b, safe) - } - return expr.outputVarsFunc(safe, terms) - } - } - return VarSet{} +// SetOperator sets the expr's operator and returns the expr itself. If expr is +// not a call expr, this function will panic. +func (expr *Expr) SetOperator(term *Term) *Expr { + expr.Terms.([]*Term)[0] = term + return expr } // SetLocation sets the expr's location and returns the expr itself. @@ -956,27 +947,11 @@ func (expr *Expr) String() string { } switch t := expr.Terms.(type) { case []*Term: - name := t[0].String() - bi := BuiltinMap[name] - var s string - // Handle infix operators (e.g., =, !=, >=, +, /, etc.) - if bi != nil && bi.Infix != "" { - if types.Compare(bi.Decl.Result(), types.T) == 0 { - s = fmt.Sprintf("%v %v %v", t[1], bi.Infix, t[2]) - } else { - s = fmt.Sprintf("%v = %v %v %v", t[3], t[1], bi.Infix, t[2]) - } - } - // Handle infix call expressions. - if len(s) == 0 && expr.Infix { - s = fmt.Sprintf("%v = %v%v", t[len(t)-1], t[0], Args(t[1:len(t)-1])) + if expr.IsEquality() { + buf = append(buf, fmt.Sprintf("%v %v %v", t[1], Equality.Infix, t[2])) + } else { + buf = append(buf, Call(t).String()) } - // Handle anything else. - if len(s) == 0 { - s = fmt.Sprintf("%v%v", t[0], Args(t[1:])) - } - buf = append(buf, s) - case *Term: buf = append(buf, t.String()) } @@ -1005,120 +980,6 @@ func (expr *Expr) Vars(params VarVisitorParams) VarSet { return vis.Vars() } -func (expr *Expr) outputVarsBuiltins(b *Builtin, safe VarSet) VarSet { - - o := expr.outputVarsRefs(safe) - terms := expr.Terms.([]*Term) - - // Check that all input terms are ground or safe. - for i, t := range terms[1:] { - if b.IsTargetPos(i) { - continue - } - if t.Value.IsGround() { - continue - } - vis := NewVarVisitor().WithParams(VarVisitorParams{ - SkipClosures: true, - SkipObjectKeys: true, - SkipRefHead: true, - }) - Walk(vis, t) - unsafe := vis.Vars().Diff(o).Diff(safe) - if len(unsafe) > 0 { - return VarSet{} - } - } - - // Add vars in target positions to result. - for i, t := range terms[1:] { - if b.IsTargetPos(i) { - vis := NewVarVisitor().WithParams(VarVisitorParams{ - SkipRefHead: true, - SkipSets: true, - SkipObjectKeys: true, - SkipClosures: true, - }) - Walk(vis, t) - o.Update(vis.vars) - } - } - - return o -} - -func (expr *Expr) outputVarsEquality(safe VarSet) VarSet { - ts := expr.Terms.([]*Term) - o := expr.outputVarsRefs(safe) - o.Update(safe) - o.Update(Unify(o, ts[1], ts[2])) - return o.Diff(safe) -} - -func (expr *Expr) outputVarsFunc(safe VarSet, terms []*Term) VarSet { - - // Functions called with 0 or 1 args cannot produce output vars. - if len(expr.Operands()) < 2 { - return VarSet{} - } - - o := expr.outputVarsRefs(safe) - - // Find unsafe input vars. - args := Args(terms[:len(terms)-1]) - vis := NewVarVisitor().WithParams(VarVisitorParams{ - SkipClosures: true, - SkipObjectKeys: true, - SkipRefHead: true, - }) - Walk(vis, args) - unsafe := vis.Vars().Diff(o).Diff(safe) - if len(unsafe) > 0 { - return VarSet{} - } - - // Find safe output vars. - vis = NewVarVisitor().WithParams(VarVisitorParams{ - SkipRefHead: true, - SkipSets: true, - SkipObjectKeys: true, - SkipClosures: true, - }) - Walk(vis, terms[len(terms)-1]) - o.Update(vis.vars) - - return o -} - -func (expr *Expr) outputVarsRefs(safe VarSet) VarSet { - o := VarSet{} - WalkRefs(expr, func(r Ref) bool { - if safe.Contains(r[0].Value.(Var)) { - o.Update(r.OutputVars()) - return false - } - return true - }) - return o -} - -func (expr *Expr) withModifierSafe(safe VarSet) bool { - for _, with := range expr.With { - unsafe := false - WalkVars(with, func(v Var) bool { - if !safe.Contains(v) { - unsafe = true - return true - } - return false - }) - if unsafe { - return false - } - } - return true -} - // NewBuiltinExpr creates a new Expr object with the supplied terms. // The builtin operator must be the first term. func NewBuiltinExpr(terms ...*Term) *Expr { @@ -1164,6 +1025,12 @@ func (w With) Hash() int { return w.Target.Hash() + w.Value.Hash() } +// SetLocation sets the location on w. +func (w *With) SetLocation(loc *Location) *With { + w.Location = loc + return w +} + // RuleSet represents a collection of rules that produce a virtual document. type RuleSet []*Rule diff --git a/github.com/open-policy-agent/opa/ast/pretty.go b/github.com/open-policy-agent/opa/ast/pretty.go new file mode 100644 index 00000000..fa6bfeb8 --- /dev/null +++ b/github.com/open-policy-agent/opa/ast/pretty.go @@ -0,0 +1,84 @@ +// Copyright 2018 The OPA Authors. All rights reserved. +// Use of this source code is governed by an Apache2 +// license that can be found in the LICENSE file. + +package ast + +import ( + "fmt" + "io" + "strings" +) + +// Pretty writes a pretty representation of the AST rooted at x to w. +// +// This is function is intended for debug purposes when inspecting ASTs. +func Pretty(w io.Writer, x interface{}) { + pp := &prettyPrinter{ + depth: -1, + w: w, + } + WalkBeforeAndAfter(pp, x) +} + +type prettyPrinter struct { + depth int + w io.Writer +} + +func (pp *prettyPrinter) Before(x interface{}) { + switch x.(type) { + case *Term: + default: + pp.depth++ + } +} + +func (pp *prettyPrinter) After(x interface{}) { + switch x.(type) { + case *Term: + default: + pp.depth-- + } +} + +func (pp *prettyPrinter) Visit(x interface{}) Visitor { + switch x := x.(type) { + case *Term: + return pp + case Args: + if len(x) == 0 { + return pp + } + pp.writeType(x) + case *Expr: + extras := []string{} + if x.Negated { + extras = append(extras, "negated") + } + extras = append(extras, fmt.Sprintf("index=%d", x.Index)) + pp.writeIndent("%v %v", TypeName(x), strings.Join(extras, " ")) + case Null, Boolean, Number, String, Var: + pp.writeValue(x) + default: + pp.writeType(x) + } + return pp +} + +func (pp *prettyPrinter) writeValue(x interface{}) { + pp.writeIndent(fmt.Sprint(x)) +} + +func (pp *prettyPrinter) writeType(x interface{}) { + pp.writeIndent(TypeName(x)) +} + +func (pp *prettyPrinter) writeIndent(f string, a ...interface{}) { + pad := strings.Repeat(" ", pp.depth) + pp.write(pad+f, a...) +} + +func (pp *prettyPrinter) write(f string, a ...interface{}) { + fmt.Fprintf(pp.w, f+"\n", a...) +} diff --git a/github.com/open-policy-agent/opa/ast/strings.go b/github.com/open-policy-agent/opa/ast/strings.go index d115dd12..8f992801 100644 --- a/github.com/open-policy-agent/opa/ast/strings.go +++ b/github.com/open-policy-agent/opa/ast/strings.go @@ -13,25 +13,3 @@ import ( func TypeName(x interface{}) string { return strings.ToLower(reflect.Indirect(reflect.ValueOf(x)).Type().Name()) } - -// The type names provide consistent strings for types in error messages. -const ( - NullTypeName = "null" - BooleanTypeName = "boolean" - StringTypeName = "string" - NumberTypeName = "number" - VarTypeName = "var" - RefTypeName = "ref" - ArrayTypeName = "array" - ObjectTypeName = "object" - SetTypeName = "set" - ArrayComprehensionTypeName = "arraycomprehension" - ExprTypeName = "expr" - WithTypeName = "with" - BodyTypeName = "body" - HeadTypeName = "head" - RuleTypeName = "rule" - ArgsTypeName = "args" - ImportTypeName = "import" - PackageTypeName = "package" -) diff --git a/github.com/open-policy-agent/opa/ast/term.go b/github.com/open-policy-agent/opa/ast/term.go index cbd1fbb1..550508d9 100644 --- a/github.com/open-policy-agent/opa/ast/term.go +++ b/github.com/open-policy-agent/opa/ast/term.go @@ -8,16 +8,13 @@ import ( "bytes" "encoding/json" "fmt" - "math/rand" "regexp" + "sort" "strconv" "strings" - "time" - "unsafe" "github.com/dchest/siphash" "github.com/open-policy-agent/opa/util" - "github.com/pkg/errors" ) @@ -80,7 +77,8 @@ func (loc *Location) String() string { // - Null, Boolean, Number, String // - Object, Array, Set // - Variables, References -// - Array Comprehensions +// - Array, Set, and Object Comprehensions +// - Calls type Value interface { Compare(other Value) int // Compare returns <0, 0, or >0 if this Value is less than, equal to, or greater than other, respectively. Find(path Ref) (Value, error) // Find returns value referred to by path or an error if path is not found. @@ -117,7 +115,7 @@ func InterfaceToValue(x interface{}) (Value, error) { } return r, nil case map[string]interface{}: - r := Object{} + r := NewObject() for k, v := range x { k, err := InterfaceToValue(k) if err != nil { @@ -127,11 +125,11 @@ func InterfaceToValue(x interface{}) (Value, error) { if err != nil { return nil, err } - r = append(r, Item(&Term{Value: k}, &Term{Value: v})) + r.Insert(NewTerm(k), NewTerm(v)) } return r, nil case map[string]string: - r := Object{} + r := NewObject() for k, v := range x { k, err := InterfaceToValue(k) if err != nil { @@ -141,7 +139,7 @@ func InterfaceToValue(x interface{}) (Value, error) { if err != nil { return nil, err } - r = append(r, Item(&Term{Value: k}, &Term{Value: v})) + r.Insert(NewTerm(k), NewTerm(v)) } return r, nil default: @@ -190,36 +188,44 @@ func ValueToInterface(v Value, resolver Resolver) (interface{}, error) { return buf, nil case Object: buf := map[string]interface{}{} - for _, x := range v { - k, err := ValueToInterface(x[0].Value, resolver) + err := v.Iter(func(k, v *Term) error { + ki, err := ValueToInterface(k.Value, resolver) if err != nil { - return nil, err + return err } - asStr, stringKey := k.(string) + asStr, stringKey := ki.(string) if !stringKey { - return nil, fmt.Errorf("object value has non-string key (%T)", k) + return fmt.Errorf("object value has non-string key (%T)", ki) } - v, err := ValueToInterface(x[1].Value, resolver) + vi, err := ValueToInterface(v.Value, resolver) if err != nil { - return nil, err + return err } - buf[asStr] = v + buf[asStr] = vi + return nil + }) + if err != nil { + return nil, err } return buf, nil - case *Set: + case Set: buf := []interface{}{} - for _, x := range *v { + err := v.Iter(func(x *Term) error { x1, err := ValueToInterface(x.Value, resolver) if err != nil { - return nil, err + return err } buf = append(buf, x1) + return nil + }) + if err != nil { + return nil, err } return buf, nil case Ref: return resolver.Resolve(v) default: - return nil, fmt.Errorf("value requires evaluation (%T)", v) + return nil, fmt.Errorf("%v requires evaluation", TypeName(v)) } } @@ -275,7 +281,7 @@ func (term *Term) Copy() *Term { cpy.Value = v.Copy() case Array: cpy.Value = v.Copy() - case *Set: + case Set: cpy.Value = v.Copy() case Object: cpy.Value = v.Copy() @@ -285,6 +291,8 @@ func (term *Term) Copy() *Term { cpy.Value = v.Copy() case *SetComprehension: cpy.Value = v.Copy() + case Call: + cpy.Value = v.Copy() } return &cpy @@ -305,6 +313,21 @@ func (term *Term) Equal(other *Term) bool { return term.Value.Compare(other.Value) == 0 } +// Get returns a value referred to by name from the term. +func (term *Term) Get(name *Term) *Term { + switch v := term.Value.(type) { + case Array: + return v.Get(name) + case Object: + return v.Get(name) + case Set: + if v.Contains(name) { + return name + } + } + return nil +} + // Hash returns the hash code of the Term's value. func (term *Term) Hash() int { return term.Value.Hash() @@ -358,7 +381,7 @@ func IsConstant(v Value) bool { Walk(&GenericVisitor{ func(x interface{}) bool { switch x.(type) { - case Var, Ref, *ArrayComprehension, *ObjectComprehension, *SetComprehension: + case Var, Ref, *ArrayComprehension, *ObjectComprehension, *SetComprehension, Call: found = true return true } @@ -559,8 +582,9 @@ func (num Number) Find(path Ref) (Value, error) { func (num Number) Hash() int { f, err := json.Number(num).Float64() if err != nil { - s := string(num) - return hashString(&s) + bs := []byte(num) + h := siphash.Hash(hashSeed0, hashSeed1, bs) + return int(h) } return int(f) } @@ -643,8 +667,9 @@ func (str String) String() string { // Hash returns the hash code for the Value. func (str String) Hash() int { - s := string(str) - return hashString(&s) + bs := []byte(str) + h := siphash.Hash(hashSeed0, hashSeed1, bs) + return int(h) } // Var represents a variable as defined by the language. @@ -682,7 +707,8 @@ func (v Var) Find(path Ref) (Value, error) { // Hash returns the hash code for the Value. func (v Var) Hash() int { - h := siphash.Hash(hashSeed0, hashSeed1, *(*[]byte)(unsafe.Pointer(&v))) + bs := []byte(v) + h := siphash.Hash(hashSeed0, hashSeed1, bs) return int(h) } @@ -734,14 +760,24 @@ func (ref Ref) Append(term *Term) Ref { return dst } -// Dynamic returns the offset of the first non-constant operand of ref. -func (ref Ref) Dynamic() int { - for i := 1; i < len(ref); i++ { - if !IsConstant(ref[i].Value) { - return i - } +// Insert returns a copy of the ref with x inserted at pos. If pos < len(ref), +// existing elements are shifted to the right. If pos > len(ref)+1 this +// function panics. +func (ref Ref) Insert(x *Term, pos int) Ref { + if pos == len(ref) { + return ref.Append(x) + } else if pos > len(ref)+1 { + panic("illegal index") } - return -1 + cpy := make(Ref, len(ref)+1) + for i := 0; i < pos; i++ { + cpy[i] = ref[i] + } + cpy[pos] = x + for i := pos; i < len(ref); i++ { + cpy[i+1] = ref[i] + } + return cpy } // Extend returns a copy of ref with the terms from other appended. The head of @@ -761,6 +797,16 @@ func (ref Ref) Extend(other Ref) Ref { return dst } +// Dynamic returns the offset of the first non-constant operand of ref. +func (ref Ref) Dynamic() int { + for i := 1; i < len(ref); i++ { + if !IsConstant(ref[i].Value) { + return i + } + } + return -1 +} + // Copy returns a deep copy of ref. func (ref Ref) Copy() Ref { return termSliceCopy(ref) @@ -951,6 +997,16 @@ func (arr Array) Get(pos *Term) *Term { return nil } +// Sorted returns a new Array that contains the sorted elements of arr. +func (arr Array) Sorted() Array { + cpy := make(Array, len(arr)) + for i := range cpy { + cpy[i] = arr[i] + } + sort.Sort(termSlice(cpy)) + return cpy +} + // Hash returns the hash code for the Value. func (arr Array) Hash() int { return termSliceHash(arr) @@ -978,65 +1034,114 @@ func (arr Array) String() string { } // Set represents a set as defined by the language. -type Set []*Term - -// SetTerm returns a new Term representing a set containing terms t. -func SetTerm(t ...*Term) *Term { - s := &Set{} +type Set interface { + Value + Len() int + Copy() Set + Diff(Set) Set + Intersect(Set) Set + Union(Set) Set + Add(*Term) + Iter(func(*Term) error) error + Until(func(*Term) bool) bool + Foreach(func(*Term)) + Contains(*Term) bool + Map(func(*Term) (*Term, error)) (Set, error) + Reduce(*Term, func(*Term, *Term) (*Term, error)) (*Term, error) + Sorted() Array +} + +// NewSet returns a new Set containing t. +func NewSet(t ...*Term) Set { + s := &set{ + elems: map[int]*setElem{}, + } for i := range t { s.Add(t[i]) } + return s +} + +// SetTerm returns a new Term representing a set containing terms t. +func SetTerm(t ...*Term) *Term { + set := NewSet(t...) return &Term{ - Value: s, + Value: set, } } +type set struct { + elems map[int]*setElem + keys []*Term +} + +type setElem struct { + elem *Term + next *setElem +} + +func (s *setElem) String() string { + buf := []string{} + for c := s; c != nil; c = c.next { + buf = append(buf, fmt.Sprint(c.elem)) + } + return strings.Join(buf, "->") +} + // Copy returns a deep copy of s. -func (s *Set) Copy() *Set { - cpy := Set(termSliceCopy(*s)) - return &cpy +func (s *set) Copy() Set { + cpy := NewSet() + s.Foreach(func(x *Term) { + cpy.Add(x) + }) + return cpy } // IsGround returns true if all terms in s are ground. -func (s *Set) IsGround() bool { - return termSliceIsGround(*s) +func (s *set) IsGround() bool { + return !s.Until(func(x *Term) bool { + return !x.IsGround() + }) } // Hash returns a hash code for s. -func (s *Set) Hash() int { - return termSliceHash(*s) +func (s *set) Hash() int { + var hash int + s.Foreach(func(x *Term) { + hash += x.Hash() + }) + return hash } -func (s *Set) String() string { - - sl := *s - - if len(sl) == 0 { +func (s *set) String() string { + if s.Len() == 0 { return "set()" } - - buf := make([]string, len(sl)) - - for i := range sl { - buf[i] = sl[i].String() - } - + buf := []string{} + s.Foreach(func(x *Term) { + buf = append(buf, x.String()) + }) return "{" + strings.Join(buf, ", ") + "}" } -// Equal returns true if s is equal to v. -func (s *Set) Equal(v Value) bool { - return Compare(s, v) == 0 -} - // Compare compares s to other, return <0, 0, or >0 if it is less than, equal to, // or greater than other. -func (s *Set) Compare(other Value) int { - return Compare(s, other) +func (s *set) Compare(other Value) int { + o1 := sortOrder(s) + o2 := sortOrder(other) + if o1 < o2 { + return -1 + } else if o1 > o2 { + return 1 + } + t := other.(*set) + sort.Sort(termSlice(s.keys)) + sort.Sort(termSlice(t.keys)) + return termSliceCompare(s.keys, t.keys) } // Find returns the current value or a not found error. -func (s *Set) Find(path Ref) (Value, error) { +func (s *set) Find(path Ref) (Value, error) { if len(path) == 0 { return s, nil } @@ -1044,69 +1149,89 @@ func (s *Set) Find(path Ref) (Value, error) { } // Diff returns elements in s that are not in other. -func (s *Set) Diff(other *Set) *Set { - r := &Set{} - for _, x := range *s { +func (s *set) Diff(other Set) Set { + r := NewSet() + s.Foreach(func(x *Term) { if !other.Contains(x) { r.Add(x) } - } + }) return r } // Intersect returns the set containing elements in both s and other. -func (s *Set) Intersect(other *Set) *Set { - r := &Set{} - for _, x := range *s { +func (s *set) Intersect(other Set) Set { + r := NewSet() + s.Foreach(func(x *Term) { if other.Contains(x) { r.Add(x) } - } + }) return r } // Union returns the set containing all elements of s and other. -func (s *Set) Union(other *Set) *Set { - r := &Set{} - for _, x := range *s { +func (s *set) Union(other Set) Set { + r := NewSet() + s.Foreach(func(x *Term) { r.Add(x) - } - for _, x := range *other { + }) + other.Foreach(func(x *Term) { r.Add(x) - } + }) return r } // Add updates s to include t. -func (s *Set) Add(t *Term) { - if s.Contains(t) { - return - } - *s = append(*s, t) +func (s *set) Add(t *Term) { + s.insert(t) } -// Iter calls f on each element in s. If f returns true, iteration stops and the -// return value is true. -func (s *Set) Iter(f func(*Term) bool) (stop bool) { - sl := *s - for i := range sl { - if f(sl[i]) { - return true +// Iter calls f on each element in s. If f returns an error, iteration stops +// and the return value is the error. +func (s *set) Iter(f func(*Term) error) error { + for i := range s.keys { + if err := f(s.keys[i]); err != nil { + return err } } - return false + return nil +} + +var errStop = errors.New("stop") + +// Until calls f on each element in s. If f returns true, iteration stops. +func (s *set) Until(f func(*Term) bool) bool { + err := s.Iter(func(t *Term) error { + if f(t) { + return errStop + } + return nil + }) + return err != nil +} + +// Foreach calls f on each element in s. +func (s *set) Foreach(f func(*Term)) { + s.Iter(func(t *Term) error { + f(t) + return nil + }) } // Map returns a new Set obtained by applying f to each value in s. -func (s *Set) Map(f func(*Term) (*Term, error)) (*Set, error) { - sl := *s - set := &Set{} - for i := range sl { - term, err := f(sl[i]) +func (s *set) Map(f func(*Term) (*Term, error)) (Set, error) { + set := NewSet() + err := s.Iter(func(x *Term) error { + term, err := f(x) if err != nil { - return nil, err + return err } set.Add(term) + return nil + }) + if err != nil { + return nil, err } return set, nil } @@ -1114,32 +1239,114 @@ func (s *Set) Map(f func(*Term) (*Term, error)) (*Set, error) { // Reduce returns a Term produced by applying f to each value in s. The first // argument to f is the reduced value (starting with i) and the second argument // to f is the element in s. -func (s *Set) Reduce(i *Term, f func(*Term, *Term) (*Term, error)) (*Term, error) { - sl := *s - for _, elem := range sl { +func (s *set) Reduce(i *Term, f func(*Term, *Term) (*Term, error)) (*Term, error) { + err := s.Iter(func(x *Term) error { var err error - i, err = f(i, elem) + i, err = f(i, x) if err != nil { - return nil, err + return err } - } - return i, nil + return nil + }) + return i, err } // Contains returns true if t is in s. -func (s Set) Contains(t *Term) bool { - for i := range s { - if s[i].Equal(t) { - return true +func (s *set) Contains(t *Term) bool { + return s.get(t) != nil +} + +// Len returns the number of elements in the set. +func (s *set) Len() int { + return len(s.keys) +} + +// MarshalJSON returns JSON encoded bytes representing s. +func (s *set) MarshalJSON() ([]byte, error) { + if s.keys == nil { + return json.Marshal([]interface{}{}) + } + return json.Marshal(s.keys) +} + +// Sorted returns an Array that contains the sorted elements of s. +func (s *set) Sorted() Array { + cpy := make(Array, len(s.keys)) + for i := range cpy { + cpy[i] = s.keys[i] + } + sort.Sort(termSlice(cpy)) + return cpy +} + +func (s *set) insert(x *Term) { + hash := x.Hash() + head := s.elems[hash] + for curr := head; curr != nil; curr = curr.next { + if Compare(curr.elem, x) == 0 { + return } } - return false + s.elems[hash] = &setElem{ + elem: x, + next: head, + } + s.keys = append(s.keys, x) +} + +func (s *set) get(x *Term) *setElem { + hash := x.Hash() + for curr := s.elems[hash]; curr != nil; curr = curr.next { + if Compare(curr.elem, x) == 0 { + return curr + } + } + return nil } -// Object represents an object as defined by the language. Objects are similar to -// the same types as defined by JSON with the exception that they can contain -// Vars and References. -type Object [][2]*Term +// Object represents an object as defined by the language. +type Object interface { + Value + Len() int + Get(*Term) *Term + Copy() Object + Insert(*Term, *Term) + Iter(func(*Term, *Term) error) error + Until(func(*Term, *Term) bool) bool + Foreach(func(*Term, *Term)) + Map(func(*Term, *Term) (*Term, *Term, error)) (Object, error) + Diff(other Object) Object + Intersect(other Object) [][3]*Term + Merge(other Object) (Object, bool) + Keys() []*Term +} + +// NewObject creates a new Object with t. +func NewObject(t ...[2]*Term) Object { + obj := &object{ + elems: map[int]*objectElem{}, + } + for i := range t { + obj.Insert(t[i][0], t[i][1]) + } + return obj +} + +// ObjectTerm creates a new Term with an Object value. +func ObjectTerm(o ...[2]*Term) *Term { + return &Term{Value: NewObject(o...)} +} + +type object struct { + elems map[int]*objectElem + keys []*Term +} + +type objectElem struct { + key *Term + value *Term + next *objectElem +} // Item is a helper for constructing an tuple containing two Terms // representing a key/value pair in an Object. @@ -1147,19 +1354,52 @@ func Item(key, value *Term) [2]*Term { return [2]*Term{key, value} } -// Equal returns true if obj is equal to other. -func (obj Object) Equal(other Value) bool { - return Compare(obj, other) == 0 -} - // Compare compares obj to other, return <0, 0, or >0 if it is less than, equal to, // or greater than other. -func (obj Object) Compare(other Value) int { - return Compare(obj, other) +func (obj *object) Compare(other Value) int { + o1 := sortOrder(obj) + o2 := sortOrder(other) + if o1 < o2 { + return -1 + } else if o2 < o1 { + return 1 + } + a := obj + b := other.(*object) + keysA := a.Keys() + keysB := b.Keys() + sort.Sort(termSlice(keysA)) + sort.Sort(termSlice(keysB)) + minLen := a.Len() + if b.Len() < a.Len() { + minLen = b.Len() + } + for i := 0; i < minLen; i++ { + keysCmp := Compare(keysA[i], keysB[i]) + if keysCmp < 0 { + return -1 + } + if keysCmp > 0 { + return 1 + } + valA := a.Get(keysA[i]) + valB := b.Get(keysB[i]) + valCmp := Compare(valA, valB) + if valCmp != 0 { + return valCmp + } + } + if a.Len() < b.Len() { + return -1 + } + if b.Len() < a.Len() { + return 1 + } + return 0 } // Find returns the value at the key or undefined. -func (obj Object) Find(path Ref) (Value, error) { +func (obj *object) Find(path Ref) (Value, error) { if len(path) == 0 { return obj, nil } @@ -1170,101 +1410,136 @@ func (obj Object) Find(path Ref) (Value, error) { return value.Value.Find(path[1:]) } +func (obj *object) Insert(k, v *Term) { + obj.insert(k, v) +} + // Get returns the value of k in obj if k exists, otherwise nil. -func (obj Object) Get(k *Term) *Term { - for _, pair := range obj { - if pair[0].Equal(k) { - return pair[1] - } +func (obj *object) Get(k *Term) *Term { + if elem := obj.get(k); elem != nil { + return elem.value } return nil } // Hash returns the hash code for the Value. -func (obj Object) Hash() int { +func (obj *object) Hash() int { var hash int - for i := range obj { - hash += obj[i][0].Value.Hash() - hash += obj[i][1].Value.Hash() - } + obj.Foreach(func(k, v *Term) { + hash += v.Value.Hash() + hash += v.Value.Hash() + }) return hash } // IsGround returns true if all of the Object key/value pairs are ground. -func (obj Object) IsGround() bool { - for i := range obj { - if !obj[i][0].IsGround() { - return false - } - if !obj[i][1].IsGround() { - return false - } - } - return true -} - -// ObjectTerm creates a new Term with an Object value. -func ObjectTerm(o ...[2]*Term) *Term { - return &Term{Value: Object(o)} +func (obj *object) IsGround() bool { + return !obj.Until(func(k, v *Term) bool { + return !k.IsGround() || !v.IsGround() + }) } // Copy returns a deep copy of obj. -func (obj Object) Copy() Object { - cpy := make(Object, len(obj)) - for i := range obj { - cpy[i] = Item(obj[i][0].Copy(), obj[i][1].Copy()) - } +func (obj *object) Copy() Object { + cpy, _ := obj.Map(func(k, v *Term) (*Term, *Term, error) { + return k.Copy(), v.Copy(), nil + }) return cpy } // Diff returns a new Object that contains only the key/value pairs that exist in obj. -func (obj Object) Diff(other Object) Object { - r := Object{} - for _, i := range obj { - found := false - for _, j := range other { - if j[0].Equal(i[0]) { - found = true - break - } +func (obj *object) Diff(other Object) Object { + r := NewObject() + obj.Foreach(func(k, v *Term) { + if other.Get(k) == nil { + r.Insert(k, v) } - if !found { - r = append(r, i) - } - } + }) return r } // Intersect returns a slice of term triplets that represent the intersection of keys // between obj and other. For each intersecting key, the values from obj and other are included // as the last two terms in the triplet (respectively). -func (obj Object) Intersect(other Object) [][3]*Term { +func (obj *object) Intersect(other Object) [][3]*Term { r := [][3]*Term{} - for _, i := range obj { - for _, j := range other { - if i[0].Equal(j[0]) { - r = append(r, [...]*Term{&Term{Value: i[0].Value}, i[1], j[1]}) - } + obj.Foreach(func(k, v *Term) { + if v2 := other.Get(k); v2 != nil { + r = append(r, [3]*Term{k, v, v2}) } - } + }) return r } -// Keys returns the keys of obj. -func (obj Object) Keys() []*Term { - keys := make([]*Term, len(obj)) - for i, pair := range obj { - keys[i] = pair[0] +// Iter calls the function f for each key-value pair in the object. If f +// returns an error, iteration stops and the error is returned. +func (obj *object) Iter(f func(*Term, *Term) error) error { + for i := range obj.keys { + k := obj.keys[i] + node := obj.get(k) + if node == nil { + panic("corrupt object") + } + if err := f(k, node.value); err != nil { + return err + } + } + return nil +} + +// Until calls f for each key-value pair in the object. If f returns true, +// iteration stops. +func (obj *object) Until(f func(*Term, *Term) bool) bool { + err := obj.Iter(func(k, v *Term) error { + if f(k, v) { + return errStop + } + return nil + }) + return err != nil +} + +// Foreach calls f for each key-value pair in the object. +func (obj *object) Foreach(f func(*Term, *Term)) { + obj.Iter(func(k, v *Term) error { + f(k, v) + return nil + }) +} + +// Map returns a new Object constructed by mapping each element in the object +// using the function f. +func (obj *object) Map(f func(*Term, *Term) (*Term, *Term, error)) (Object, error) { + cpy := &object{ + elems: make(map[int]*objectElem, obj.Len()), + } + err := obj.Iter(func(k, v *Term) error { + var err error + k, v, err = f(k, v) + if err != nil { + return err + } + cpy.insert(k, v) + return nil + }) + if err != nil { + return nil, err } - return keys + return cpy, nil +} + +// Keys returns the keys of obj. +func (obj *object) Keys() []*Term { + return obj.keys } // MarshalJSON returns JSON encoded bytes representing obj. -func (obj Object) MarshalJSON() ([]byte, error) { - if len(obj) == 0 { - return json.Marshal([]interface{}{}) +func (obj *object) MarshalJSON() ([]byte, error) { + sl := make([][2]*Term, obj.Len()) + for i := range obj.keys { + k := obj.keys[i] + sl[i] = Item(k, obj.get(k).value) } - sl := [][2]*Term(obj) return json.Marshal(sl) } @@ -1272,39 +1547,76 @@ func (obj Object) MarshalJSON() ([]byte, error) { // overlapping keys between obj and other, the values of associated with the keys are merged. Only // objects can be merged with other objects. If the values cannot be merged, the second turn value // will be false. -func (obj Object) Merge(other Object) (Object, bool) { - r := Object{} - r = append(r, obj.Diff(other)...) - r = append(r, other.Diff(obj)...) - for _, vs := range obj.Intersect(other) { - var merged Value - switch v1 := vs[1].Value.(type) { - case Object: - switch v2 := vs[2].Value.(type) { - case Object: - m, ok := v1.Merge(v2) - if !ok { - return nil, false - } - merged = m +func (obj object) Merge(other Object) (result Object, ok bool) { + result = NewObject() + stop := obj.Until(func(k, v *Term) bool { + if v2 := other.Get(k); v2 == nil { + result.Insert(k, v) + } else { + obj1, ok1 := v.Value.(Object) + obj2, ok2 := v2.Value.(Object) + if !ok1 || !ok2 { + return true } + obj3, ok := obj1.Merge(obj2) + if !ok { + return true + } + result.Insert(k, NewTerm(obj3)) } - if merged == nil { - return nil, false - } - r = append(r, [2]*Term{vs[0], &Term{Value: merged}}) + return false + }) + if stop { + return nil, false } - return r, true + other.Foreach(func(k, v *Term) { + if v2 := obj.Get(k); v2 == nil { + result.Insert(k, v) + } + }) + return result, true } -func (obj Object) String() string { +// Len returns the number of elements in the object. +func (obj object) Len() int { + return len(obj.keys) +} + +func (obj object) String() string { var buf []string - for _, p := range obj { - buf = append(buf, fmt.Sprintf("%s: %s", p[0], p[1])) - } + obj.Foreach(func(k, v *Term) { + buf = append(buf, fmt.Sprintf("%s: %s", k, v)) + }) return "{" + strings.Join(buf, ", ") + "}" } +func (obj *object) get(k *Term) *objectElem { + hash := k.Hash() + for curr := obj.elems[hash]; curr != nil; curr = curr.next { + if Compare(curr.key, k) == 0 { + return curr + } + } + return nil +} + +func (obj *object) insert(k, v *Term) { + hash := k.Hash() + head := obj.elems[hash] + for curr := head; curr != nil; curr = curr.next { + if Compare(curr.key, k) == 0 { + curr.value = v + return + } + } + obj.elems[hash] = &objectElem{ + key: k, + value: v, + next: head, + } + obj.keys = append(obj.keys, k) +} + // ArrayComprehension represents an array comprehension as defined in the language. type ArrayComprehension struct { Term *Term `json:"term"` @@ -1479,6 +1791,55 @@ func (sc *SetComprehension) String() string { return "{" + sc.Term.String() + " | " + sc.Body.String() + "}" } +// Call represents as function call in the language. +type Call []*Term + +// CallTerm returns a new Term with a Call value defined by terms. The first +// term is the operator and the rest are operands. +func CallTerm(terms ...*Term) *Term { + return NewTerm(Call(terms)) +} + +// Copy returns a deep copy of c. +func (c Call) Copy() Call { + return termSliceCopy(c) +} + +// Compare compares c to other, return <0, 0, or >0 if it is less than, equal to, +// or greater than other. +func (c Call) Compare(other Value) int { + return Compare(c, other) +} + +// Find returns the current value or a not found error. +func (c Call) Find(Ref) (Value, error) { + return nil, fmt.Errorf("find: not found") +} + +// Hash returns the hash code for the Value. +func (c Call) Hash() int { + return termSliceHash(c) +} + +// IsGround returns true if the Value is ground. +func (c Call) IsGround() bool { + return termSliceIsGround(c) +} + +// MakeExpr returns an ew Expr from this call. +func (c Call) MakeExpr(output *Term) *Expr { + terms := []*Term(c) + return NewExpr(append(terms, output)) +} + +func (c Call) String() string { + args := make([]string, len(c)-1) + for i := 1; i < len(c); i++ { + args[i-1] = c[i].String() + } + return fmt.Sprintf("%v(%v)", c[0], strings.Join(args, ", ")) +} + func formatString(s String) string { str := string(s) if varRegexp.MatchString(str) { @@ -1633,7 +1994,7 @@ func unmarshalTermSliceValue(d map[string]interface{}) ([]*Term, error) { if s, ok := d["value"].([]interface{}); ok { return unmarshalTermSlice(s) } - return nil, fmt.Errorf(`ast: unable to unmarshal term (expected {"value": [...], "type": ...} where type is one of: %v, %v, %v)`, ArrayTypeName, SetTypeName, RefTypeName) + return nil, fmt.Errorf(`ast: unable to unmarshal term (expected {"value": [...], "type": ...} where type is one of: ref, array, or set)`) } func unmarshalWith(i interface{}) (*With, error) { @@ -1687,7 +2048,7 @@ func unmarshalValue(d map[string]interface{}) (Value, error) { } case "set": if s, err := unmarshalTermSliceValue(d); err == nil { - set := &Set{} + set := NewSet() for _, x := range s { set.Add(x) } @@ -1695,12 +2056,12 @@ func unmarshalValue(d map[string]interface{}) (Value, error) { } case "object": if s, ok := v.([]interface{}); ok { - buf := Object{} + buf := NewObject() for _, x := range s { if i, ok := x.([]interface{}); ok && len(i) == 2 { p, err := unmarshalTermSlice(i) if err == nil { - buf = append(buf, Item(p[0], p[1])) + buf.Insert(p[0], p[1]) continue } } @@ -1769,25 +2130,11 @@ func unmarshalValue(d map[string]interface{}) (Value, error) { return &ObjectComprehension{Key: key, Value: value, Body: body}, nil } + case "call": + if s, err := unmarshalTermSliceValue(d); err == nil { + return Call(s), nil + } } unmarshal_error: return nil, fmt.Errorf("ast: unable to unmarshal term") } - -func hashString(ptr *string) int { - h := siphash.Hash(hashSeed0, hashSeed1, *(*[]byte)(unsafe.Pointer(ptr))) - return int(h) -} - -var hashSeed0 uint64 -var hashSeed1 uint64 - -func initHashSeed() { - r := rand.New(rand.NewSource(time.Now().UnixNano())) - hashSeed0 = (uint64(r.Uint32()) << 32) | uint64(r.Uint32()) - hashSeed1 = (uint64(r.Uint32()) << 32) | uint64(r.Uint32()) -} - -func init() { - initHashSeed() -} diff --git a/github.com/open-policy-agent/opa/ast/transform.go b/github.com/open-policy-agent/opa/ast/transform.go index 361e0bc2..cebf61a8 100644 --- a/github.com/open-policy-agent/opa/ast/transform.go +++ b/github.com/open-policy-agent/opa/ast/transform.go @@ -179,18 +179,17 @@ func Transform(t Transformer, x interface{}) (interface{}, error) { } return y, nil case Object: - for i, elem := range y { - k, err := transformTerm(t, elem[0]) + return y.Map(func(k, v *Term) (*Term, *Term, error) { + k, err := transformTerm(t, k) if err != nil { - return nil, err + return nil, nil, err } - v, err := transformTerm(t, elem[1]) + v, err = transformTerm(t, v) if err != nil { - return nil, err + return nil, nil, err } - y[i] = Item(k, v) - } - return y, nil + return k, v, nil + }) case Array: for i := range y { if y[i], err = transformTerm(t, y[i]); err != nil { @@ -198,7 +197,7 @@ func Transform(t Transformer, x interface{}) (interface{}, error) { } } return y, nil - case *Set: + case Set: y, err = y.Map(func(term *Term) (*Term, error) { return transformTerm(t, term) }) @@ -233,6 +232,13 @@ func Transform(t Transformer, x interface{}) (interface{}, error) { return nil, err } return y, nil + case Call: + for i := range y { + if y[i], err = transformTerm(t, y[i]); err != nil { + return nil, err + } + } + return y, nil default: return y, nil } @@ -249,6 +255,17 @@ func TransformRefs(x interface{}, f func(Ref) (Value, error)) (interface{}, erro return Transform(t, x) } +// TransformVars calls the function f on all vars under x. +func TransformVars(x interface{}, f func(Var) (Value, error)) (interface{}, error) { + t := &GenericTransformer{func(x interface{}) (interface{}, error) { + if v, ok := x.(Var); ok { + return f(v) + } + return x, nil + }} + return Transform(t, x) +} + // TransformComprehensions calls the functio nf on all comprehensions under x. func TransformComprehensions(x interface{}, f func(interface{}) (Value, error)) (interface{}, error) { t := &GenericTransformer{func(x interface{}) (interface{}, error) { diff --git a/github.com/open-policy-agent/opa/ast/unify.go b/github.com/open-policy-agent/opa/ast/unify.go index 5c899c5c..c02ae1eb 100644 --- a/github.com/open-policy-agent/opa/ast/unify.go +++ b/github.com/open-policy-agent/opa/ast/unify.go @@ -103,10 +103,13 @@ func (u *unifier) unify(a *Term, b *Term) { case Ref: u.markAllSafe(a) case Object: - if len(a) == len(b) { - for i := range a { - u.unify(a[i][1], b[i][1]) - } + if a.Len() == b.Len() { + a.Iter(func(k, v *Term) error { + if v2 := b.Get(k); v2 != nil { + u.unify(v, v2) + } + return nil + }) } } diff --git a/github.com/open-policy-agent/opa/ast/visit.go b/github.com/open-policy-agent/opa/ast/visit.go index 89961a96..e87bcc16 100644 --- a/github.com/open-policy-agent/opa/ast/visit.go +++ b/github.com/open-policy-agent/opa/ast/visit.go @@ -12,9 +12,29 @@ type Visitor interface { Visit(v interface{}) (w Visitor) } +// BeforeAndAfterVisitor wraps Visitor to provie hooks for being called before +// and after the AST has been visited. +type BeforeAndAfterVisitor interface { + Visitor + Before(x interface{}) + After(x interface{}) +} + // Walk iterates the AST by calling the Visit function on the Visitor // v for x before recursing. func Walk(v Visitor, x interface{}) { + wrapped, ok := v.(BeforeAndAfterVisitor) + if !ok { + wrapped = noopBeforeAndAfterVisitor{v} + } + WalkBeforeAndAfter(wrapped, x) +} + +// WalkBeforeAndAfter iterates the AST by calling the Visit function on the +// Visitor v for x before recursing. +func WalkBeforeAndAfter(v BeforeAndAfterVisitor, x interface{}) { + v.Before(x) + defer v.After(x) w := v.Visit(x) if w == nil { return @@ -81,18 +101,18 @@ func Walk(v Visitor, x interface{}) { Walk(w, t) } case Object: - for _, t := range x { - Walk(w, t[0]) - Walk(w, t[1]) - } + x.Foreach(func(k, v *Term) { + Walk(w, k) + Walk(w, v) + }) case Array: for _, t := range x { Walk(w, t) } - case *Set: - for _, t := range *x { + case Set: + x.Foreach(func(t *Term) { Walk(w, t) - } + }) case *ArrayComprehension: Walk(w, x.Term) Walk(w, x.Body) @@ -103,28 +123,32 @@ func Walk(v Visitor, x interface{}) { case *SetComprehension: Walk(w, x.Term) Walk(w, x.Body) + case Call: + for _, t := range x { + Walk(w, t) + } } } -// WalkClosures calls the function f on all closures under x. If the function f +// WalkVars calls the function f on all vars under x. If the function f // returns true, AST nodes under the last node will not be visited. -func WalkClosures(x interface{}, f func(interface{}) bool) { +func WalkVars(x interface{}, f func(Var) bool) { vis := &GenericVisitor{func(x interface{}) bool { - switch x.(type) { - case *ArrayComprehension, *ObjectComprehension, *SetComprehension: - return f(x) + if v, ok := x.(Var); ok { + return f(v) } return false }} Walk(vis, x) } -// WalkExprs calls the function f on all expressions under x. If the function f +// WalkClosures calls the function f on all closures under x. If the function f // returns true, AST nodes under the last node will not be visited. -func WalkExprs(x interface{}, f func(*Expr) bool) { +func WalkClosures(x interface{}, f func(interface{}) bool) { vis := &GenericVisitor{func(x interface{}) bool { - if r, ok := x.(*Expr); ok { - return f(r) + switch x.(type) { + case *ArrayComprehension, *ObjectComprehension, *SetComprehension: + return f(x) } return false }} @@ -143,36 +167,36 @@ func WalkRefs(x interface{}, f func(Ref) bool) { Walk(vis, x) } -// WalkRules calls the function f on all rules under x. If the function f +// WalkTerms calls the function f on all terms under x. If the function f // returns true, AST nodes under the last node will not be visited. -func WalkRules(x interface{}, f func(*Rule) bool) { +func WalkTerms(x interface{}, f func(*Term) bool) { vis := &GenericVisitor{func(x interface{}) bool { - if r, ok := x.(*Rule); ok { - return f(r) + if term, ok := x.(*Term); ok { + return f(term) } return false }} Walk(vis, x) } -// WalkVars calls the function f on all vars under x. If the function f +// WalkWiths calls the function f on all with modifiers under x. If the function f // returns true, AST nodes under the last node will not be visited. -func WalkVars(x interface{}, f func(Var) bool) { +func WalkWiths(x interface{}, f func(*With) bool) { vis := &GenericVisitor{func(x interface{}) bool { - if v, ok := x.(Var); ok { - return f(v) + if w, ok := x.(*With); ok { + return f(w) } return false }} Walk(vis, x) } -// WalkWiths calls the function f on all with modifiers under x. If the function f +// WalkExprs calls the function f on all expressions under x. If the function f // returns true, AST nodes under the last node will not be visited. -func WalkWiths(x interface{}, f func(*With) bool) { +func WalkExprs(x interface{}, f func(*Expr) bool) { vis := &GenericVisitor{func(x interface{}) bool { - if w, ok := x.(*With); ok { - return f(w) + if r, ok := x.(*Expr); ok { + return f(r) } return false }} @@ -191,6 +215,18 @@ func WalkBodies(x interface{}, f func(Body) bool) { Walk(vis, x) } +// WalkRules calls the function f on all rules under x. If the function f +// returns true, AST nodes under the last node will not be visited. +func WalkRules(x interface{}, f func(*Rule) bool) { + vis := &GenericVisitor{func(x interface{}) bool { + if r, ok := x.(*Rule); ok { + return f(r) + } + return false + }} + Walk(vis, x) +} + // GenericVisitor implements the Visitor interface to provide // a utility to walk over AST nodes using a closure. If the closure // returns true, the visitor will not walk over AST nodes under x. @@ -228,7 +264,6 @@ type VarVisitorParams struct { SkipClosures bool SkipWithTarget bool SkipSets bool - SkipFuncVars bool } // NewVarVisitor returns a new VarVisitor object. @@ -253,9 +288,9 @@ func (vis *VarVisitor) Vars() VarSet { func (vis *VarVisitor) Visit(v interface{}) Visitor { if vis.params.SkipObjectKeys { if o, ok := v.(Object); ok { - for _, i := range o { - Walk(vis, i[1]) - } + o.Foreach(func(_, v *Term) { + Walk(vis, v) + }) return nil } } @@ -280,7 +315,7 @@ func (vis *VarVisitor) Visit(v interface{}) Visitor { } } if vis.params.SkipSets { - if _, ok := v.(*Set); ok { + if _, ok := v.(Set); ok { return nil } } @@ -305,3 +340,10 @@ func (vis *VarVisitor) Visit(v interface{}) Visitor { } return vis } + +type noopBeforeAndAfterVisitor struct { + Visitor +} + +func (noopBeforeAndAfterVisitor) Before(interface{}) {} +func (noopBeforeAndAfterVisitor) After(interface{}) {} diff --git a/github.com/open-policy-agent/opa/metrics/metrics.go b/github.com/open-policy-agent/opa/metrics/metrics.go index 45b6c439..6a7d6fbd 100644 --- a/github.com/open-policy-agent/opa/metrics/metrics.go +++ b/github.com/open-policy-agent/opa/metrics/metrics.go @@ -7,6 +7,8 @@ package metrics import ( "time" + + go_metrics "github.com/rcrowley/go-metrics" ) // Well-known metric names. @@ -16,30 +18,30 @@ const ( RegoQueryParse = "rego_query_parse" RegoModuleParse = "rego_module_parse" RegoModuleCompile = "rego_module_compile" + RegoPartialEval = "rego_partial_eval" ) // Metrics defines the interface for a collection of perfomrance metrics in the // policy engine. type Metrics interface { Timer(name string) Timer + Histogram(name string) Histogram + Counter(name string) Counter All() map[string]interface{} Clear() } type metrics struct { - timers map[string]Timer -} - -// Sample defines a common interface to obtain a single metric value. -type Sample interface { - Value() interface{} + timers map[string]Timer + histograms map[string]Histogram + counters map[string]Counter } // New returns a new Metrics object. func New() Metrics { - return &metrics{ - timers: map[string]Timer{}, - } + m := &metrics{} + m.Clear() + return m } func (m *metrics) Timer(name string) Timer { @@ -51,22 +53,53 @@ func (m *metrics) Timer(name string) Timer { return t } +func (m *metrics) Histogram(name string) Histogram { + h, ok := m.histograms[name] + if !ok { + h = newHistogram() + m.histograms[name] = h + } + return h +} + +func (m *metrics) Counter(name string) Counter { + c, ok := m.counters[name] + if !ok { + zero := counter(0) + c = &zero + m.counters[name] = c + } + return c +} + func (m *metrics) All() map[string]interface{} { result := map[string]interface{}{} for name, timer := range m.timers { result[m.formatKey(name, timer)] = timer.Value() } + for name, hist := range m.histograms { + result[m.formatKey(name, hist)] = hist.Value() + } + for name, cntr := range m.counters { + result[m.formatKey(name, cntr)] = cntr.Value() + } return result } func (m *metrics) Clear() { m.timers = map[string]Timer{} + m.histograms = map[string]Histogram{} + m.counters = map[string]Counter{} } -func (m *metrics) formatKey(name string, sample Sample) string { - switch sample.(type) { +func (m *metrics) formatKey(name string, metrics interface{}) string { + switch metrics.(type) { case Timer: return "timer_" + name + "_ns" + case Histogram: + return "histogram_" + name + case Counter: + return "counter_" + name default: return name } @@ -75,9 +108,10 @@ func (m *metrics) formatKey(name string, sample Sample) string { // Timer defines the interface for a restartable timer that accumulates elapsed // time. type Timer interface { - Sample + Value() interface{} + Int64() int64 Start() - Stop() + Stop() int64 } type timer struct { @@ -89,10 +123,82 @@ func (t *timer) Start() { t.start = time.Now() } -func (t *timer) Stop() { - t.value += time.Now().Sub(t.start).Nanoseconds() +func (t *timer) Stop() int64 { + delta := time.Now().Sub(t.start).Nanoseconds() + t.value += delta + return delta } func (t timer) Value() interface{} { + return t.Int64() +} + +func (t timer) Int64() int64 { return t.value } + +// Histogram defines the interface for a histogram with hardcoded percentiles. +type Histogram interface { + Value() interface{} + Update(int64) +} + +type histogram struct { + hist go_metrics.Histogram +} + +func newHistogram() Histogram { + // NOTE(tsandall): the reservoir size and alpha factor are taken from + // https://github.com/rcrowley/go-metrics. They may need to be tweaked in + // the future. + sample := go_metrics.NewExpDecaySample(1028, 0.015) + hist := go_metrics.NewHistogram(sample) + return &histogram{hist} +} + +func (h *histogram) Update(v int64) { + h.hist.Update(v) +} + +func (h *histogram) Value() interface{} { + values := map[string]interface{}{} + snap := h.hist.Snapshot() + percentiles := snap.Percentiles([]float64{ + 0.5, + 0.75, + 0.9, + 0.95, + 0.99, + 0.999, + 0.9999, + }) + values["count"] = snap.Count() + values["min"] = snap.Min() + values["max"] = snap.Max() + values["mean"] = snap.Mean() + values["stddev"] = snap.StdDev() + values["median"] = percentiles[0] + values["75%"] = percentiles[1] + values["90%"] = percentiles[2] + values["95%"] = percentiles[3] + values["99%"] = percentiles[4] + values["99.9%"] = percentiles[5] + values["99.99%"] = percentiles[6] + return values +} + +// Counter defines the interface for a monotonic increasing counter. +type Counter interface { + Value() interface{} + Incr() +} + +type counter uint64 + +func (c *counter) Incr() { + *c++ +} + +func (c *counter) Value() interface{} { + return *c +} diff --git a/github.com/open-policy-agent/opa/rego/rego.go b/github.com/open-policy-agent/opa/rego/rego.go index b7f6100d..74d561c5 100644 --- a/github.com/open-policy-agent/opa/rego/rego.go +++ b/github.com/open-policy-agent/opa/rego/rego.go @@ -17,6 +17,22 @@ import ( "github.com/open-policy-agent/opa/topdown" ) +const defaultPartialNamespace = "partial" + +// PartialResult represents the result of partial evaluation. The result can be +// used to generate a new query that can be run when inputs are known. +type PartialResult struct { + compiler *ast.Compiler + store storage.Store + body ast.Body +} + +// Rego returns an object that can be evaluated to produce a query result. +func (pr PartialResult) Rego(options ...func(*Rego)) *Rego { + options = append(options, Compiler(pr.compiler), Store(pr.store), ParsedQuery(pr.body)) + return New(options...) +} + // Result defines the output of Rego evaluation. type Result struct { Expressions []*ExpressionValue `json:"expressions"` @@ -92,19 +108,26 @@ func (errs Errors) Error() string { // Rego constructs a query and can be evaluated to obtain results. type Rego struct { - query string - pkg string - imports []string - rawInput *interface{} - input ast.Value - modules []rawModule - compiler *ast.Compiler - store storage.Store - txn storage.Transaction - metrics metrics.Metrics - tracer topdown.Tracer - - termVarID int + query string + parsedQuery ast.Body + pkg string + parsedPackage *ast.Package + imports []string + parsedImports []*ast.Import + rawInput *interface{} + input ast.Value + unknowns []string + partialNamespace string + modules []rawModule + compiler *ast.Compiler + store storage.Store + txn storage.Transaction + metrics metrics.Metrics + tracer topdown.Tracer + instrumentation *topdown.Instrumentation + instrument bool + capture map[*ast.Expr]ast.Var // map exprs to generated capture vars + termVarID int } // Query returns an argument that sets the Rego query. @@ -114,6 +137,13 @@ func Query(q string) func(r *Rego) { } } +// ParsedQuery returns an argument that sets the Rego query. +func ParsedQuery(q ast.Body) func(r *Rego) { + return func(r *Rego) { + r.parsedQuery = q + } +} + // Package returns an argument that sets the Rego package on the query's // context. func Package(p string) func(r *Rego) { @@ -122,6 +152,14 @@ func Package(p string) func(r *Rego) { } } +// ParsedPackage returns an argument that sets the Rego package on the query's +// context. +func ParsedPackage(pkg *ast.Package) func(r *Rego) { + return func(r *Rego) { + r.parsedPackage = pkg + } +} + // Imports returns an argument that adds a Rego import to the query's context. func Imports(p []string) func(r *Rego) { return func(r *Rego) { @@ -129,6 +167,14 @@ func Imports(p []string) func(r *Rego) { } } +// ParsedImports returns an argument that adds Rego imports to the query's +// context. +func ParsedImports(imp []*ast.Import) func(r *Rego) { + return func(r *Rego) { + r.parsedImports = append(r.parsedImports, imp...) + } +} + // Input returns an argument that sets the Rego input document. Input should be // a native Go value representing the input document. func Input(x interface{}) func(r *Rego) { @@ -137,6 +183,30 @@ func Input(x interface{}) func(r *Rego) { } } +// ParsedInput returns an argument that set sthe Rego input document. +func ParsedInput(x ast.Value) func(r *Rego) { + return func(r *Rego) { + r.input = x + } +} + +// Unknowns returns an argument that sets the values to treat as unknown during +// partial evaluation. +func Unknowns(unknowns []string) func(r *Rego) { + return func(r *Rego) { + r.unknowns = unknowns + } +} + +// PartialNamespace returns an argument that sets the namespace to use for +// partial evaluation results. The namespace must be a valid package path +// component. +func PartialNamespace(ns string) func(r *Rego) { + return func(r *Rego) { + r.partialNamespace = ns + } +} + // Module returns an argument that adds a Rego module. func Module(filename, input string) func(r *Rego) { return func(r *Rego) { @@ -169,23 +239,36 @@ func Transaction(txn storage.Transaction) func(r *Rego) { } } -// Metrics returns an argument that sets the metrics collection and enables instrumentation. +// Metrics returns an argument that sets the metrics collection. func Metrics(m metrics.Metrics) func(r *Rego) { return func(r *Rego) { r.metrics = m } } +// Instrument returns an argument that enables instrumentation for diagnosing +// performance issues. +func Instrument(yes bool) func(r *Rego) { + return func(r *Rego) { + r.instrument = yes + } +} + // Tracer returns an argument that sets the topdown Tracer. func Tracer(t topdown.Tracer) func(r *Rego) { return func(r *Rego) { - r.tracer = t + if t != nil { + r.tracer = t + } } } // New returns a new Rego object. func New(options ...func(*Rego)) *Rego { - r := &Rego{} + + r := &Rego{ + capture: map[*ast.Expr]ast.Var{}, + } for _, option := range options { option(r) @@ -203,42 +286,44 @@ func New(options ...func(*Rego)) *Rego { r.metrics = metrics.New() } + if r.instrument { + r.instrumentation = topdown.NewInstrumentation(r.metrics) + } + return r } // Eval evaluates this Rego object and returns a ResultSet. func (r *Rego) Eval(ctx context.Context) (ResultSet, error) { - if len(r.query) == 0 { + if len(r.query) == 0 && len(r.parsedQuery) == 0 { return nil, fmt.Errorf("cannot evaluate empty query") } - r.metrics.Timer(metrics.RegoQueryParse).Start() - - // Parse inputs parsed, query, err := r.parse() if err != nil { return nil, err } - r.metrics.Timer(metrics.RegoQueryParse).Stop() - - query = r.captureTerms(query) + err = r.compileModules(parsed) + if err != nil { + return nil, err + } - r.metrics.Timer(metrics.RegoQueryCompile).Start() + qc, compiled, err := r.compileQuery([]extraStage{ + { + after: "ResolveRefs", + stage: r.rewriteQueryToCaptureValue, + }, + }, query) - // Compile inputs - compiled, err := r.compile(parsed, query) if err != nil { return nil, err } - r.metrics.Timer(metrics.RegoQueryCompile).Stop() - txn := r.txn if txn == nil { - // Open transaction for this run if user did not provide one. txn, err = r.store.NewTransaction(ctx) if err != nil { return nil, err @@ -246,11 +331,55 @@ func (r *Rego) Eval(ctx context.Context) (ResultSet, error) { defer r.store.Abort(ctx, txn) } - // Evaluate query - return r.eval(ctx, compiled, txn) + return r.eval(ctx, qc, compiled, txn) +} + +// PartialEval partially evaluates this Rego object and returns a PartialResult. +func (r *Rego) PartialEval(ctx context.Context) (PartialResult, error) { + + if len(r.query) == 0 && len(r.parsedQuery) == 0 { + return PartialResult{}, fmt.Errorf("cannot evaluate empty query") + } + + parsed, query, err := r.parse() + if err != nil { + return PartialResult{}, err + } + + err = r.compileModules(parsed) + if err != nil { + return PartialResult{}, err + } + + _, compiled, err := r.compileQuery([]extraStage{ + { + after: "ResolveRefs", + stage: r.rewriteQueryForPartialEval, + }, + }, query) + + if err != nil { + return PartialResult{}, err + } + + txn := r.txn + + if txn == nil { + txn, err = r.store.NewTransaction(ctx) + if err != nil { + return PartialResult{}, err + } + defer r.store.Abort(ctx, txn) + } + + return r.partialEval(ctx, compiled, txn, ast.Wildcard) } func (r *Rego) parse() (map[string]*ast.Module, ast.Body, error) { + + r.metrics.Timer(metrics.RegoQueryParse).Start() + defer r.metrics.Timer(metrics.RegoQueryParse).Stop() + var errs Errors parsed := map[string]*ast.Module{} @@ -262,75 +391,111 @@ func (r *Rego) parse() (map[string]*ast.Module, ast.Body, error) { parsed[module.filename] = p } - query, err := ast.ParseBody(r.query) - if err != nil { - errs = append(errs, err) - } + var query ast.Body - if len(errs) > 0 { - return nil, nil, errs + if r.parsedQuery != nil { + query = r.parsedQuery + } else { + var err error + query, err = ast.ParseBody(r.query) + if err != nil { + errs = append(errs, err) + } + if len(errs) > 0 { + return nil, nil, errs + } } return parsed, query, nil } -func (r *Rego) compile(modules map[string]*ast.Module, query ast.Body) (ast.Body, error) { +func (r *Rego) compileModules(modules map[string]*ast.Module) error { + + r.metrics.Timer(metrics.RegoModuleCompile).Start() + defer r.metrics.Timer(metrics.RegoModuleCompile).Stop() if len(modules) > 0 { r.compiler.Compile(modules) - if r.compiler.Failed() { var errs Errors for _, err := range r.compiler.Errors { errs = append(errs, err) } - return nil, errs + return errs } } - var qctx *ast.QueryContext + return nil +} + +func (r *Rego) compileQuery(extras []extraStage, query ast.Body) (ast.QueryCompiler, ast.Body, error) { + + r.metrics.Timer(metrics.RegoQueryCompile).Start() + defer r.metrics.Timer(metrics.RegoQueryCompile).Stop() + + var pkg *ast.Package if r.pkg != "" { - pkg, err := ast.ParsePackage(fmt.Sprintf("package %v", r.pkg)) + var err error + pkg, err = ast.ParsePackage(fmt.Sprintf("package %v", r.pkg)) if err != nil { - return nil, err + return nil, nil, err } - qctx = qctx.WithPackage(pkg) + } else { + pkg = r.parsedPackage } + imports := r.parsedImports + if len(r.imports) > 0 { s := make([]string, len(r.imports)) for i := range r.imports { s[i] = fmt.Sprintf("import %v", r.imports[i]) } - imports, err := ast.ParseImports(strings.Join(s, "\n")) + parsed, err := ast.ParseImports(strings.Join(s, "\n")) if err != nil { - return nil, err + return nil, nil, err } - qctx = qctx.WithImports(imports) + imports = append(imports, parsed...) } + var input ast.Value + if r.rawInput != nil { val, err := ast.InterfaceToValue(*r.rawInput) if err != nil { - return nil, err + return nil, nil, err } - qctx = qctx.WithInput(val) + input = val r.input = val + } else { + input = r.input } - return r.compiler.QueryCompiler().WithContext(qctx).Compile(query) -} + qctx := ast.NewQueryContext(). + WithPackage(pkg). + WithImports(imports). + WithInput(input) + + qc := r.compiler.QueryCompiler().WithContext(qctx) + + for _, extra := range extras { + qc = qc.WithStageAfter(extra.after, extra.stage) + } + + compiled, err := qc.Compile(query) + return qc, compiled, err -func (r *Rego) eval(ctx context.Context, compiled ast.Body, txn storage.Transaction) (rs ResultSet, err error) { +} - r.metrics.Timer(metrics.RegoQueryEval).Start() +func (r *Rego) eval(ctx context.Context, qc ast.QueryCompiler, compiled ast.Body, txn storage.Transaction) (rs ResultSet, err error) { q := topdown.NewQuery(compiled). WithCompiler(r.compiler). WithStore(r.store). WithTransaction(txn). - WithMetrics(r.metrics) + WithMetrics(r.metrics). + WithInstrumentation(r.instrumentation) if r.tracer != nil { q = q.WithTracer(r.tracer) @@ -349,29 +514,34 @@ func (r *Rego) eval(ctx context.Context, compiled ast.Body, txn storage.Transact c.Cancel() }) - exprs := map[*ast.Expr]struct{}{} + rewritten := qc.RewrittenVars() err = q.Iter(ctx, func(qr topdown.QueryResult) error { result := newResult() - for key, value := range qr { - val, err := ast.JSON(value.Value) + for k := range qr { + v, err := ast.JSON(qr[k].Value) if err != nil { return err } - if !isTermVar(key) { - if !key.IsWildcard() && !key.IsGenerated() { - result.Bindings[string(key)] = val - } - } else if expr := findExprForTermVar(compiled, key); expr != nil { - result.Expressions = append(result.Expressions, newExpressionValue(expr, val)) - exprs[expr] = struct{}{} + if rw, ok := rewritten[k]; ok { + k = rw + } + if isTermVar(k) || k.IsGenerated() || k.IsWildcard() { + continue } + result.Bindings[string(k)] = v } for _, expr := range compiled { - // Don't include expressions without locations. Lack of location - // indicates it was not parsed and so the caller should not be - // shown it. - if _, ok := exprs[expr]; !ok && expr.Location != nil && !expr.Generated { + if expr.Generated { + continue + } + if k, ok := r.capture[expr]; ok { + v, err := ast.JSON(qr[k].Value) + if err != nil { + return err + } + result.Expressions = append(result.Expressions, newExpressionValue(expr, v)) + } else { result.Expressions = append(result.Expressions, newExpressionValue(expr, true)) } } @@ -387,42 +557,164 @@ func (r *Rego) eval(ctx context.Context, compiled ast.Body, txn storage.Transact return nil, nil } - r.metrics.Timer(metrics.RegoQueryEval).Stop() - return rs, nil } -func (r *Rego) captureTerms(query ast.Body) ast.Body { +func (r *Rego) partialEval(ctx context.Context, compiled ast.Body, txn storage.Transaction, output *ast.Term) (PartialResult, error) { - // If the query contains expressions that consist of a single term, rewrite - // those expressions so that we capture the value of the term in a variable - // that can be included in the result. - extras := map[*ast.Expr]struct{}{} + var unknowns []*ast.Term - for i := range query { - if !query[i].Negated { - if term, ok := query[i].Terms.(*ast.Term); ok { - - // If len(query) > 1 we must still test that evaluated value is - // not false. - if len(query) > 1 { - cpy := query[i].Copy() - // Unset location so that this expression is not included - // in the results. - cpy.Location = nil - extras[cpy] = struct{}{} - } + // Use input document as unknown if caller has not specified any. + if r.unknowns == nil { + unknowns = []*ast.Term{ast.InputRootDocument} + } else { + unknowns = make([]*ast.Term, len(r.unknowns)) + for i := range r.unknowns { + var err error + unknowns[i], err = ast.ParseTerm(r.unknowns[i]) + if err != nil { + return PartialResult{}, err + } + } + } + + partialNamespace := r.partialNamespace + if partialNamespace == "" { + partialNamespace = defaultPartialNamespace + } + + // Check partial namespace to ensure it's valid. + if term, err := ast.ParseTerm(partialNamespace); err != nil { + return PartialResult{}, err + } else if _, ok := term.Value.(ast.Var); !ok { + return PartialResult{}, fmt.Errorf("bad partial namespace") + } + + q := topdown.NewQuery(compiled). + WithCompiler(r.compiler). + WithStore(r.store). + WithTransaction(txn). + WithMetrics(r.metrics). + WithInstrumentation(r.instrumentation). + WithUnknowns(unknowns). + WithPartialNamespace(partialNamespace) + + if r.tracer != nil { + q = q.WithTracer(r.tracer) + } + + if r.input != nil { + q = q.WithInput(ast.NewTerm(r.input)) + } + + // Cancel query if context is cancelled or deadline is reached. + c := topdown.NewCancel() + q = q.WithCancel(c) + exit := make(chan struct{}) + defer close(exit) + go waitForDone(ctx, exit, func() { + c.Cancel() + }) + + partials, support, err := q.PartialRun(ctx) + if err != nil { + return PartialResult{}, err + } + + // Construct module for queries. + module := ast.MustParseModule("package " + partialNamespace) + module.Rules = make([]*ast.Rule, len(partials)) + for i, body := range partials { + module.Rules[i] = &ast.Rule{ + Head: ast.NewHead(ast.Var("__result__"), nil, output), + Body: body, + Module: module, + } + } + + // Update compiler with partial evaluation output. + r.compiler.Modules["__partialresult__"] = module + for i, module := range support { + r.compiler.Modules[fmt.Sprintf("__partialsupport%d__", i)] = module + } + + r.compiler.Compile(r.compiler.Modules) + if r.compiler.Failed() { + return PartialResult{}, r.compiler.Errors + } + + result := PartialResult{ + compiler: r.compiler, + store: r.store, + body: ast.MustParseBody(fmt.Sprintf("data.%v.__result__", partialNamespace)), + } + + return result, nil +} + +func (r *Rego) rewriteQueryToCaptureValue(qc ast.QueryCompiler, query ast.Body) (ast.Body, error) { + + checkCapture := iteration(query) || len(query) > 1 + + for _, expr := range query { + + if expr.Negated { + continue + } + + if expr.IsAssignment() || expr.IsEquality() { + continue + } - query[i].Terms = ast.Equality.Expr(term, r.generateTermVar()).Terms + var capture *ast.Term + + // If the expression can be evaluated as a function, rewrite it to + // capture the return value. E.g., neq(1,2) becomes neq(1,2,x) but + // plus(1,2,x) does not get rewritten. + switch terms := expr.Terms.(type) { + case *ast.Term: + capture = r.generateTermVar() + expr.Terms = ast.Equality.Expr(terms, capture).Terms + r.capture[expr] = capture.Value.(ast.Var) + case []*ast.Term: + if r.compiler.GetArity(expr.Operator()) == len(terms)-1 { + capture = r.generateTermVar() + expr.Terms = append(terms, capture) + r.capture[expr] = capture.Value.(ast.Var) } } + + if capture != nil && checkCapture { + cpy := expr.Copy() + cpy.Terms = capture + cpy.Generated = true + query.Append(cpy) + } + } + + return query, nil +} + +func (r *Rego) rewriteQueryForPartialEval(_ ast.QueryCompiler, query ast.Body) (ast.Body, error) { + if len(query) != 1 { + return nil, fmt.Errorf("partial evaluation requires single ref (not multiple expressions)") } - for expr := range extras { - query.Append(expr) + term, ok := query[0].Terms.(*ast.Term) + if !ok { + return nil, fmt.Errorf("partial evaluation requires ref (not expression)") } - return query + ref, ok := term.Value.(ast.Ref) + if !ok { + return nil, fmt.Errorf("partial evaluation requires ref (not %v)", ast.TypeName(term.Value)) + } + + if !ref.IsGround() { + return nil, fmt.Errorf("partial evaluation requires ground ref") + } + + return ast.NewBody(ast.Equality.Expr(ast.Wildcard, term)), nil } func (r *Rego) generateTermVar() *ast.Term { @@ -463,3 +755,43 @@ type rawModule struct { func (m rawModule) Parse() (*ast.Module, error) { return ast.ParseModule(m.filename, m.module) } + +type extraStage struct { + after string + stage ast.QueryCompilerStage +} + +func iteration(x interface{}) bool { + + var stopped bool + + vis := ast.NewGenericVisitor(func(x interface{}) bool { + switch x := x.(type) { + case *ast.Term: + if ast.IsComprehension(x.Value) { + return true + } + case ast.Ref: + if !stopped { + if bi := ast.BuiltinMap[x.String()]; bi != nil { + if bi.Relation { + stopped = true + return stopped + } + } + for i := 1; i < len(x); i++ { + if _, ok := x[i].Value.(ast.Var); ok { + stopped = true + return stopped + } + } + } + return stopped + } + return stopped + }) + + ast.Walk(vis, x) + + return stopped +} diff --git a/github.com/open-policy-agent/opa/storage/path.go b/github.com/open-policy-agent/opa/storage/path.go index b26cd953..ce0c9c86 100644 --- a/github.com/open-policy-agent/opa/storage/path.go +++ b/github.com/open-policy-agent/opa/storage/path.go @@ -52,7 +52,7 @@ func NewPathForRef(ref ast.Ref) (path Path, err error) { Code: NotFoundErr, Message: fmt.Sprintf("%v: does not exist", ref), } - case ast.Array, ast.Object, *ast.Set: + case ast.Array, ast.Object, ast.Set: return nil, fmt.Errorf("composites cannot be base document keys: %v", ref) default: return nil, fmt.Errorf("unresolved reference (indicates error in caller): %v", ref) diff --git a/github.com/open-policy-agent/opa/topdown/aggregates.go b/github.com/open-policy-agent/opa/topdown/aggregates.go index 8e154c03..0dda8aff 100644 --- a/github.com/open-policy-agent/opa/topdown/aggregates.go +++ b/github.com/open-policy-agent/opa/topdown/aggregates.go @@ -16,13 +16,13 @@ func builtinCount(a ast.Value) (ast.Value, error) { case ast.Array: return ast.IntNumberTerm(len(a)).Value, nil case ast.Object: - return ast.IntNumberTerm(len(a)).Value, nil - case *ast.Set: - return ast.IntNumberTerm(len(*a)).Value, nil + return ast.IntNumberTerm(a.Len()).Value, nil + case ast.Set: + return ast.IntNumberTerm(a.Len()).Value, nil case ast.String: return ast.IntNumberTerm(len(a)).Value, nil } - return nil, builtins.NewOperandTypeErr(1, a, ast.ArrayTypeName, ast.ObjectTypeName, ast.SetTypeName) + return nil, builtins.NewOperandTypeErr(1, a, "array", "object", "set") } func builtinSum(a ast.Value) (ast.Value, error) { @@ -32,23 +32,24 @@ func builtinSum(a ast.Value) (ast.Value, error) { for _, x := range a { n, ok := x.Value.(ast.Number) if !ok { - return nil, builtins.NewOperandElementErr(1, a, x.Value, ast.NumberTypeName) + return nil, builtins.NewOperandElementErr(1, a, x.Value, "number") } sum = new(big.Float).Add(sum, builtins.NumberToFloat(n)) } return builtins.FloatToNumber(sum), nil - case *ast.Set: + case ast.Set: sum := big.NewFloat(0) - for _, x := range *a { + err := a.Iter(func(x *ast.Term) error { n, ok := x.Value.(ast.Number) if !ok { - return nil, builtins.NewOperandElementErr(1, a, x.Value, ast.NumberTypeName) + return builtins.NewOperandElementErr(1, a, x.Value, "number") } sum = new(big.Float).Add(sum, builtins.NumberToFloat(n)) - } - return builtins.FloatToNumber(sum), nil + return nil + }) + return builtins.FloatToNumber(sum), err } - return nil, builtins.NewOperandTypeErr(1, a, ast.SetTypeName, ast.ArrayTypeName) + return nil, builtins.NewOperandTypeErr(1, a, "set", "array") } func builtinProduct(a ast.Value) (ast.Value, error) { @@ -58,23 +59,24 @@ func builtinProduct(a ast.Value) (ast.Value, error) { for _, x := range a { n, ok := x.Value.(ast.Number) if !ok { - return nil, builtins.NewOperandElementErr(1, a, x.Value, ast.NumberTypeName) + return nil, builtins.NewOperandElementErr(1, a, x.Value, "number") } product = new(big.Float).Mul(product, builtins.NumberToFloat(n)) } return builtins.FloatToNumber(product), nil - case *ast.Set: + case ast.Set: product := big.NewFloat(1) - for _, x := range *a { + err := a.Iter(func(x *ast.Term) error { n, ok := x.Value.(ast.Number) if !ok { - return nil, builtins.NewOperandElementErr(1, a, x.Value, ast.NumberTypeName) + return builtins.NewOperandElementErr(1, a, x.Value, "number") } product = new(big.Float).Mul(product, builtins.NumberToFloat(n)) - } - return builtins.FloatToNumber(product), nil + return nil + }) + return builtins.FloatToNumber(product), err } - return nil, builtins.NewOperandTypeErr(1, a, ast.SetTypeName, ast.ArrayTypeName) + return nil, builtins.NewOperandTypeErr(1, a, "set", "array") } func builtinMax(a ast.Value) (ast.Value, error) { @@ -90,8 +92,8 @@ func builtinMax(a ast.Value) (ast.Value, error) { } } return max, nil - case *ast.Set: - if len(*a) == 0 { + case ast.Set: + if a.Len() == 0 { return nil, BuiltinEmpty{} } max, err := a.Reduce(ast.NullTerm(), func(max *ast.Term, elem *ast.Term) (*ast.Term, error) { @@ -103,7 +105,7 @@ func builtinMax(a ast.Value) (ast.Value, error) { return max.Value, err } - return nil, builtins.NewOperandTypeErr(1, a, ast.SetTypeName, ast.ArrayTypeName) + return nil, builtins.NewOperandTypeErr(1, a, "set", "array") } func builtinMin(a ast.Value) (ast.Value, error) { @@ -119,8 +121,8 @@ func builtinMin(a ast.Value) (ast.Value, error) { } } return min, nil - case *ast.Set: - if len(*a) == 0 { + case ast.Set: + if a.Len() == 0 { return nil, BuiltinEmpty{} } min, err := a.Reduce(ast.NullTerm(), func(min *ast.Term, elem *ast.Term) (*ast.Term, error) { @@ -139,7 +141,17 @@ func builtinMin(a ast.Value) (ast.Value, error) { return min.Value, err } - return nil, builtins.NewOperandTypeErr(1, a, ast.SetTypeName, ast.ArrayTypeName) + return nil, builtins.NewOperandTypeErr(1, a, "set", "array") +} + +func builtinSort(a ast.Value) (ast.Value, error) { + switch a := a.(type) { + case ast.Array: + return a.Sorted(), nil + case ast.Set: + return a.Sorted(), nil + } + return nil, builtins.NewOperandTypeErr(1, a, "set", "array") } func init() { @@ -148,4 +160,5 @@ func init() { RegisterFunctionalBuiltin1(ast.Product.Name, builtinProduct) RegisterFunctionalBuiltin1(ast.Max.Name, builtinMax) RegisterFunctionalBuiltin1(ast.Min.Name, builtinMin) + RegisterFunctionalBuiltin1(ast.Sort.Name, builtinSort) } diff --git a/github.com/open-policy-agent/opa/topdown/arithmetic.go b/github.com/open-policy-agent/opa/topdown/arithmetic.go index 00912734..647a103f 100644 --- a/github.com/open-policy-agent/opa/topdown/arithmetic.go +++ b/github.com/open-policy-agent/opa/topdown/arithmetic.go @@ -97,18 +97,18 @@ func builtinMinus(a, b ast.Value) (ast.Value, error) { return builtins.FloatToNumber(f), nil } - s1, ok3 := a.(*ast.Set) - s2, ok4 := b.(*ast.Set) + s1, ok3 := a.(ast.Set) + s2, ok4 := b.(ast.Set) if ok3 && ok4 { return s1.Diff(s2), nil } if !ok1 && !ok3 { - return nil, builtins.NewOperandTypeErr(1, a, ast.NumberTypeName, ast.SetTypeName) + return nil, builtins.NewOperandTypeErr(1, a, "number", "set") } - return nil, builtins.NewOperandTypeErr(2, b, ast.NumberTypeName, ast.SetTypeName) + return nil, builtins.NewOperandTypeErr(2, b, "number", "set") } func init() { diff --git a/github.com/open-policy-agent/opa/topdown/bindings.go b/github.com/open-policy-agent/opa/topdown/bindings.go index b84ceee0..acb89916 100644 --- a/github.com/open-policy-agent/opa/topdown/bindings.go +++ b/github.com/open-policy-agent/opa/topdown/bindings.go @@ -6,6 +6,7 @@ package topdown import ( "fmt" + "strings" "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/util" @@ -31,10 +32,12 @@ func (u *undo) Undo() { } type bindings struct { + id uint64 values *util.HashMap + instr *Instrumentation } -func newBindings() *bindings { +func newBindings(id uint64, instr *Instrumentation) *bindings { eq := func(a, b util.T) bool { v1, ok1 := a.(*ast.Term) @@ -54,10 +57,10 @@ func newBindings() *bindings { values := util.NewHashMap(eq, hash) - return &bindings{values} + return &bindings{id, values, instr} } -func (u *bindings) Iter(iter func(*ast.Term, *ast.Term) error) error { +func (u *bindings) Iter(caller *bindings, iter func(*ast.Term, *ast.Term) error) error { var err error @@ -66,7 +69,7 @@ func (u *bindings) Iter(iter func(*ast.Term, *ast.Term) error) error { return true } term := k.(*ast.Term) - err = iter(term, u.Plug(term)) + err = iter(term, u.PlugNamespaced(term, caller)) return false }) @@ -74,48 +77,69 @@ func (u *bindings) Iter(iter func(*ast.Term, *ast.Term) error) error { } func (u *bindings) Plug(a *ast.Term) *ast.Term { + return u.PlugNamespaced(a, nil) +} + +func (u *bindings) PlugNamespaced(a *ast.Term, caller *bindings) *ast.Term { + if u != nil { + u.instr.startTimer(evalOpPlug) + defer u.instr.stopTimer(evalOpPlug) + } + return u.plugNamespaced(a, caller) +} + +func (u *bindings) plugNamespaced(a *ast.Term, caller *bindings) *ast.Term { switch v := a.Value.(type) { case ast.Var: b, next := u.apply(a) if a != b || u != next { - return next.Plug(b) + return next.plugNamespaced(b, caller) + } + if caller != nil && caller != u { + if name, ok := b.Value.(ast.Var); ok { + return ast.NewTerm(ast.Var(string(name) + fmt.Sprint(u.id))) + } } return b case ast.Array: cpy := *a arr := make(ast.Array, len(v)) for i := 0; i < len(arr); i++ { - arr[i] = u.Plug(v[i]) + arr[i] = u.plugNamespaced(v[i], caller) } cpy.Value = arr return &cpy case ast.Object: cpy := *a - obj := make(ast.Object, len(v)) - for i := 0; i < len(obj); i++ { - obj[i] = ast.Item(u.Plug(v[i][0]), u.Plug(v[i][1])) - } - cpy.Value = obj + cpy.Value, _ = v.Map(func(k, v *ast.Term) (*ast.Term, *ast.Term, error) { + return u.plugNamespaced(k, caller), u.plugNamespaced(v, caller), nil + }) return &cpy - case *ast.Set: + case ast.Set: cpy := *a cpy.Value, _ = v.Map(func(x *ast.Term) (*ast.Term, error) { - return u.Plug(x), nil + return u.plugNamespaced(x, caller), nil }) return &cpy + case ast.Ref: + cpy := *a + ref := make(ast.Ref, len(v)) + ref[0] = v[0] + for i := 1; i < len(ref); i++ { + ref[i] = u.plugNamespaced(v[i], caller) + } + cpy.Value = ref + return &cpy } return a } -func (u *bindings) String() string { - if u == nil { - return "{}" - } - return u.values.String() -} - func (u *bindings) bind(a *ast.Term, b *ast.Term, other *bindings) *undo { - // fmt.Println("bind:", a, b) + // See note in apply about non-var terms. + _, ok := a.Value.(ast.Var) + if !ok { + panic("illegal value") + } u.values.Put(a, value{ u: other, v: b, @@ -124,6 +148,14 @@ func (u *bindings) bind(a *ast.Term, b *ast.Term, other *bindings) *undo { } func (u *bindings) apply(a *ast.Term) (*ast.Term, *bindings) { + // Early exit for non-var terms. Only vars are bound in the binding list, + // so the lookup below will always fail for non-var terms. In some cases, + // the lookup may be expensive as it has to hash the term (which for large + // inputs can be costly.) + _, ok := a.Value.(ast.Var) + if !ok { + return a, u + } val, ok := u.get(a) if !ok { return a, u @@ -146,13 +178,25 @@ func (u *bindings) get(v *ast.Term) (value, bool) { return r.(value), true } +func (u *bindings) String() string { + if u == nil { + return "()" + } + var buf []string + u.values.Iter(func(a, b util.T) bool { + buf = append(buf, fmt.Sprintf("%v: %v", a, b)) + return false + }) + return fmt.Sprintf("({%v}, %v)", strings.Join(buf, ", "), u.id) +} + type value struct { u *bindings v *ast.Term } func (v value) String() string { - return fmt.Sprintf("<%v, %p>", v.v, v.u) + return fmt.Sprintf("(%v, %d)", v.v, v.u.id) } func (v value) equal(other *value) bool { diff --git a/github.com/open-policy-agent/opa/topdown/builtins.go b/github.com/open-policy-agent/opa/topdown/builtins.go index e36718e2..3ab90cc3 100644 --- a/github.com/open-policy-agent/opa/topdown/builtins.go +++ b/github.com/open-policy-agent/opa/topdown/builtins.go @@ -42,16 +42,6 @@ type ( // framework takes care of this. FunctionalBuiltin3 func(op1, op2, op3 ast.Value) (output ast.Value, err error) - // FunctionalBuiltinVoid1 defines an interface for simple functional built-ins. - // - // Implement this interface if your built-in function takes one input and - // produces no outputs. - // - // If an error occurs, the functional built-in should return a descriptive - // message. The message should not be prefixed with the built-in name as the - // framework takes care of this. - FunctionalBuiltinVoid1 func(op1 ast.Value) (err error) - // BuiltinContext contains context from the evaluator that may be used by // built-in functions. BuiltinContext struct { @@ -59,8 +49,12 @@ type ( Location *ast.Location } - // BuiltinFunc defines a generic interface for built-in functions. - BuiltinFunc func(BuiltinContext, []*ast.Term, func(*ast.Term) error) error + // BuiltinFunc defines an interface for implementing built-in functions. + // The built-in function is called with the plugged operands from the call + // (including the output operands.) The implementation should evaluate the + // operands and invoke the iteraror for each successful/defined output + // value. + BuiltinFunc func(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error ) // RegisterBuiltinFunc adds a new built-in function to the evaluation engine. @@ -68,12 +62,6 @@ func RegisterBuiltinFunc(name string, f BuiltinFunc) { builtinFunctions[name] = f } -// RegisterFunctionalBuiltinVoid1 adds a new built-in function to the evaluation -// engine. -func RegisterFunctionalBuiltinVoid1(name string, fun FunctionalBuiltinVoid1) { - builtinFunctions[name] = functionalWrapperVoid1(name, fun) -} - // RegisterFunctionalBuiltin1 adds a new built-in function to the evaluation // engine. func RegisterFunctionalBuiltin1(name string, fun FunctionalBuiltin1) { @@ -102,19 +90,6 @@ func (BuiltinEmpty) Error() string { var builtinFunctions = map[string]BuiltinFunc{} -func functionalWrapperVoid1(name string, fn FunctionalBuiltinVoid1) BuiltinFunc { - return func(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error { - err := fn(args[0].Value) - if err == nil { - return iter(ast.BooleanTerm(true)) - } - if _, empty := err.(BuiltinEmpty); empty { - return nil - } - return handleFunctionalBuiltinEr(name, bctx.Location, err) - } -} - func functionalWrapper1(name string, fn FunctionalBuiltin1) BuiltinFunc { return func(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error { result, err := fn(args[0].Value) @@ -124,7 +99,7 @@ func functionalWrapper1(name string, fn FunctionalBuiltin1) BuiltinFunc { if _, empty := err.(BuiltinEmpty); empty { return nil } - return handleFunctionalBuiltinEr(name, bctx.Location, err) + return handleBuiltinErr(name, bctx.Location, err) } } @@ -137,7 +112,7 @@ func functionalWrapper2(name string, fn FunctionalBuiltin2) BuiltinFunc { if _, empty := err.(BuiltinEmpty); empty { return nil } - return handleFunctionalBuiltinEr(name, bctx.Location, err) + return handleBuiltinErr(name, bctx.Location, err) } } @@ -150,11 +125,11 @@ func functionalWrapper3(name string, fn FunctionalBuiltin3) BuiltinFunc { if _, empty := err.(BuiltinEmpty); empty { return nil } - return handleFunctionalBuiltinEr(name, bctx.Location, err) + return handleBuiltinErr(name, bctx.Location, err) } } -func handleFunctionalBuiltinEr(name string, loc *ast.Location, err error) error { +func handleBuiltinErr(name string, loc *ast.Location, err error) error { switch err := err.(type) { case BuiltinEmpty: return nil diff --git a/github.com/open-policy-agent/opa/topdown/builtins/builtins.go b/github.com/open-policy-agent/opa/topdown/builtins/builtins.go index 63b12f79..8619d3f5 100644 --- a/github.com/open-policy-agent/opa/topdown/builtins/builtins.go +++ b/github.com/open-policy-agent/opa/topdown/builtins/builtins.go @@ -81,7 +81,7 @@ func NewOperandEnumErr(pos int, expected ...string) error { func IntOperand(x ast.Value, pos int) (int, error) { n, ok := x.(ast.Number) if !ok { - return 0, NewOperandTypeErr(pos, x, ast.NumberTypeName) + return 0, NewOperandTypeErr(pos, x, "number") } i, ok := n.Int() @@ -97,17 +97,17 @@ func IntOperand(x ast.Value, pos int) (int, error) { func NumberOperand(x ast.Value, pos int) (ast.Number, error) { n, ok := x.(ast.Number) if !ok { - return ast.Number(""), NewOperandTypeErr(pos, x, ast.NumberTypeName) + return ast.Number(""), NewOperandTypeErr(pos, x, "number") } return n, nil } // SetOperand converts x to a set. If the cast fails, a descriptive error is // returned. -func SetOperand(x ast.Value, pos int) (*ast.Set, error) { - s, ok := x.(*ast.Set) +func SetOperand(x ast.Value, pos int) (ast.Set, error) { + s, ok := x.(ast.Set) if !ok { - return nil, NewOperandTypeErr(pos, x, ast.SetTypeName) + return nil, NewOperandTypeErr(pos, x, "set") } return s, nil } @@ -117,11 +117,21 @@ func SetOperand(x ast.Value, pos int) (*ast.Set, error) { func StringOperand(x ast.Value, pos int) (ast.String, error) { s, ok := x.(ast.String) if !ok { - return ast.String(""), NewOperandTypeErr(pos, x, ast.StringTypeName) + return ast.String(""), NewOperandTypeErr(pos, x, "string") } return s, nil } +// ObjectOperand converts x to an object. If the cast fails, a descriptive +// error is returned. +func ObjectOperand(x ast.Value, pos int) (ast.Object, error) { + o, ok := x.(ast.Object) + if !ok { + return nil, NewOperandTypeErr(pos, x, "object") + } + return o, nil +} + // NumberToFloat converts n to a big float. func NumberToFloat(n ast.Number) *big.Float { r, ok := new(big.Float).SetString(string(n)) diff --git a/github.com/open-policy-agent/opa/topdown/casts.go b/github.com/open-policy-agent/opa/topdown/casts.go index 1f2e272f..7019b870 100644 --- a/github.com/open-policy-agent/opa/topdown/casts.go +++ b/github.com/open-policy-agent/opa/topdown/casts.go @@ -30,7 +30,7 @@ func builtinToNumber(a ast.Value) (ast.Value, error) { } return ast.Number(json.Number(a)), nil } - return nil, builtins.NewOperandTypeErr(1, a, ast.NullTypeName, ast.BooleanTypeName, ast.NumberTypeName, ast.StringTypeName) + return nil, builtins.NewOperandTypeErr(1, a, "null", "boolean", "number", "string") } func init() { diff --git a/github.com/open-policy-agent/opa/topdown/ineq.go b/github.com/open-policy-agent/opa/topdown/comparison.go similarity index 87% rename from github.com/open-policy-agent/opa/topdown/ineq.go rename to github.com/open-policy-agent/opa/topdown/comparison.go index 884510e6..96be984a 100644 --- a/github.com/open-policy-agent/opa/topdown/ineq.go +++ b/github.com/open-policy-agent/opa/topdown/comparison.go @@ -28,12 +28,13 @@ func compareNotEq(a, b ast.Value) bool { return ast.Compare(a, b) != 0 } +func compareEq(a, b ast.Value) bool { + return ast.Compare(a, b) == 0 +} + func builtinCompare(cmp compareFunc) FunctionalBuiltin2 { return func(a, b ast.Value) (ast.Value, error) { - if !cmp(a, b) { - return nil, BuiltinEmpty{} - } - return ast.Boolean(true), nil + return ast.Boolean(cmp(a, b)), nil } } @@ -43,4 +44,5 @@ func init() { RegisterFunctionalBuiltin2(ast.LessThan.Name, builtinCompare(compareLessThan)) RegisterFunctionalBuiltin2(ast.LessThanEq.Name, builtinCompare(compareLessThanEq)) RegisterFunctionalBuiltin2(ast.NotEqual.Name, builtinCompare(compareNotEq)) + RegisterFunctionalBuiltin2(ast.Equal.Name, builtinCompare(compareEq)) } diff --git a/github.com/open-policy-agent/opa/topdown/errors.go b/github.com/open-policy-agent/opa/topdown/errors.go index 6fce72ba..5cfd4ea2 100644 --- a/github.com/open-policy-agent/opa/topdown/errors.go +++ b/github.com/open-policy-agent/opa/topdown/errors.go @@ -86,6 +86,14 @@ func objectDocKeyConflictErr(loc *ast.Location) error { } } +func documentConflictErr(loc *ast.Location) error { + return &Error{ + Code: ConflictErr, + Location: loc, + Message: "base and virtual document keys must be disjoint", + } +} + func unsupportedBuiltinErr(loc *ast.Location) error { return &Error{ Code: InternalErr, diff --git a/github.com/open-policy-agent/opa/topdown/eval.go b/github.com/open-policy-agent/opa/topdown/eval.go index 7fecc42d..c2bd2f7c 100644 --- a/github.com/open-policy-agent/opa/topdown/eval.go +++ b/github.com/open-policy-agent/opa/topdown/eval.go @@ -4,10 +4,9 @@ import ( "context" "fmt" - "github.com/open-policy-agent/opa/topdown/builtins" - "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/storage" + "github.com/open-policy-agent/opa/topdown/builtins" ) type evalIterator func(*eval) error @@ -15,21 +14,25 @@ type evalIterator func(*eval) error type unifyIterator func() error type eval struct { - ctx context.Context - queryID uint64 - parent *eval - cancel Cancel - query ast.Body - bindings *bindings - store storage.Store - txn storage.Transaction - compiler *ast.Compiler - input *ast.Term - tracer Tracer - builtinCache builtins.Cache - virtualCache *virtualCache - saveSet *saveSet - saveStack *saveStack + ctx context.Context + queryID uint64 + parent *eval + cancel Cancel + query ast.Body + bindings *bindings + store storage.Store + txn storage.Transaction + compiler *ast.Compiler + input *ast.Term + tracer Tracer + instr *Instrumentation + builtinCache builtins.Cache + virtualCache *virtualCache + saveSet *saveSet + saveStack *saveStack + saveSupport *saveSupport + saveNamespace *ast.Term + genvarprefix string } func (e *eval) Run(iter evalIterator) error { @@ -52,13 +55,17 @@ func (e *eval) closure(query ast.Body) *eval { func (e *eval) child(query ast.Body) *eval { cpy := *e - cpy.bindings = newBindings() - cpy.query = query cpy.queryID++ + cpy.query = query + cpy.bindings = newBindings(cpy.queryID, e.instr) cpy.parent = e return &cpy } +func (e *eval) partial() bool { + return e.saveSet != nil +} + func (e *eval) traceEnter(x interface{}) { e.traceEvent(EnterOp, x) } @@ -79,6 +86,10 @@ func (e *eval) traceRedo(x interface{}) { e.traceEvent(RedoOp, x) } +func (e *eval) traceSave(x interface{}) { + e.traceEvent(SaveOp, x) +} + func (e *eval) traceEvent(op Op, x interface{}) { if e.tracer == nil || !e.tracer.Enabled() { @@ -86,7 +97,7 @@ func (e *eval) traceEvent(op Op, x interface{}) { } locals := ast.NewValueMap() - e.bindings.Iter(func(k, v *ast.Term) error { + e.bindings.Iter(nil, func(k, v *ast.Term) error { locals.Put(k.Value, v.Value) return nil }) @@ -110,7 +121,6 @@ func (e *eval) traceEvent(op Op, x interface{}) { func (e *eval) traceEnabled() bool { return e.tracer != nil && e.tracer.Enabled() } - func (e *eval) eval(iter evalIterator) error { return e.evalExpr(0, iter) } @@ -132,6 +142,11 @@ func (e *eval) evalExpr(index int, iter evalIterator) error { e.traceEval(expr) if len(expr.With) > 0 { + if e.partial() { + return e.saveExpr(expr, e.bindings, func() error { + return e.evalExpr(index+1, iter) + }) + } return e.evalWith(index, iter) } @@ -143,6 +158,11 @@ func (e *eval) evalStep(index int, iter evalIterator) error { expr := e.query[index] if expr.Negated { + if e.partial() { + return e.saveExpr(expr, e.bindings, func() error { + return e.evalExpr(index+1, iter) + }) + } return e.evalNot(index, iter) } @@ -158,6 +178,10 @@ func (e *eval) evalStep(index int, iter evalIterator) error { e.traceRedo(expr) return err }) + } else if e.saveSet.ContainsAny(terms[1:]) { + return e.saveCall(terms[0], terms[1:len(terms)-1], terms[len(terms)-1], func() error { + return e.evalExpr(index+1, iter) + }) } else { err = e.evalCall(index, terms[0], terms[1:], func() error { defined = true @@ -167,20 +191,22 @@ func (e *eval) evalStep(index int, iter evalIterator) error { }) } case *ast.Term: - rterm := ast.VarTerm(ast.WildcardPrefix + "term" + fmt.Sprintf("%d_%d", e.queryID, index)) + rterm := e.generateVar(fmt.Sprintf("term_%d_%d", e.queryID, index)) err = e.unify(terms, rterm, func() error { - if !e.saveSet.Contains(rterm) { - if !e.bindings.Plug(rterm).Equal(ast.BooleanTerm(false)) { - defined = true - err := e.evalExpr(index+1, iter) - e.traceRedo(expr) - return err - } - return nil + if e.saveSet.Contains(rterm) { + operator := ast.NewTerm(ast.NotEqual.Ref()) + args := []*ast.Term{rterm, ast.BooleanTerm(false)} + return e.saveVoidCall(operator, args, func() error { + return e.evalExpr(index+1, iter) + }) } - return e.saveCall(ast.NewTerm(ast.NotEqual.Ref()), []*ast.Term{rterm, ast.BooleanTerm(false)}, ast.BooleanTerm(true), func() error { - return e.evalExpr(index+1, iter) - }) + if !e.bindings.Plug(rterm).Equal(ast.BooleanTerm(false)) { + defined = true + err := e.evalExpr(index+1, iter) + e.traceRedo(expr) + return err + } + return nil }) } @@ -330,7 +356,7 @@ func (e *eval) biunify(a, b *ast.Term, b1, b2 *bindings, iter unifyIterator) err case ast.Object: return e.biunifyObjects(vA, vB, b1, b2, iter) } - case *ast.Set: + case ast.Set: return e.biunifyValues(a, b, b1, b2, iter) } return nil @@ -353,23 +379,34 @@ func (e *eval) biunifyArraysRec(a, b ast.Array, b1, b2 *bindings, iter unifyIter } func (e *eval) biunifyObjects(a, b ast.Object, b1, b2 *bindings, iter unifyIterator) error { - if len(a) != len(b) { + if a.Len() != b.Len() { return nil } - return e.biunifyObjectsRec(a, b, b1, b2, iter, 0) + + // Objects must not contain unbound variables as keys at this point as we + // cannot unify them. Similar to sets, plug both sides before comparing the + // keys and unifying the values. + if nonGroundKeys(a) { + a = plugKeys(a, b1) + } + + if nonGroundKeys(b) { + b = plugKeys(b, b2) + } + + return e.biunifyObjectsRec(a, b, b1, b2, iter, a.Keys(), 0) } -func (e *eval) biunifyObjectsRec(a, b ast.Object, b1, b2 *bindings, iter unifyIterator, idx int) error { - if idx == len(a) { +func (e *eval) biunifyObjectsRec(a, b ast.Object, b1, b2 *bindings, iter unifyIterator, keys []*ast.Term, idx int) error { + if idx == len(keys) { return iter() } - item := a[idx] - other := b.Get(item[0]) - if other == nil { + v2 := b.Get(keys[idx]) + if v2 == nil { return nil } - return e.biunify(item[1], other, b1, b2, func() error { - return e.biunifyObjectsRec(a, b, b1, b2, iter, idx+1) + return e.biunify(a.Get(keys[idx]), v2, b1, b2, func() error { + return e.biunifyObjectsRec(a, b, b1, b2, iter, keys, idx+1) }) } @@ -377,28 +414,23 @@ func (e *eval) biunifyValues(a, b *ast.Term, b1, b2 *bindings, iter unifyIterato saveA := e.saveSet.Contains(a) saveB := e.saveSet.Contains(b) - - if saveA && saveB { - return e.saveUnify(a, b, b1, b2, iter) - } - _, refA := a.Value.(ast.Ref) _, refB := b.Value.(ast.Ref) + // Try to evaluate refs and comprehensions. If partial evaluation is + // enabled, then skip evaluation (and save the expression) if the term is + // in the save set. Currently, comprehensions are not evaluated during + // partial eval. This could be improved in the future. if refA && !saveA { return e.biunifyRef(a, b, b1, b2, iter) - } else if refA && saveA { - return e.saveUnify(a, b, b1, b2, iter) } else if refB && !saveB { return e.biunifyRef(b, a, b2, b1, iter) - } else if refB && saveB { - return e.saveUnify(a, b, b1, b2, iter) } compA := ast.IsComprehension(a.Value) compB := ast.IsComprehension(b.Value) - if saveA || saveB || ((compA || compB) && e.saveSet != nil) { + if saveA || saveB || ((compA || compB) && e.partial()) { return e.saveUnify(a, b, b1, b2, iter) } @@ -408,6 +440,7 @@ func (e *eval) biunifyValues(a, b *ast.Term, b1, b2 *bindings, iter unifyIterato return e.biunifyComprehension(b.Value, a, b2, b1, iter) } + // Perform standard unification. _, varA := a.Value.(ast.Var) _, varB := b.Value.(ast.Var) @@ -431,6 +464,15 @@ func (e *eval) biunifyValues(a, b *ast.Term, b1, b2 *bindings, iter unifyIterato return err } + // Sets must not contain unbound variables at this point as we cannot unify + // them. So simply plug both sides (to substitute any bound variables with + // values) and then check for equality. + switch a.Value.(type) { + case ast.Set: + a = b1.Plug(a) + b = b2.Plug(b) + } + if a.Equal(b) { return iter() } @@ -514,7 +556,7 @@ func (e *eval) biunifyComprehensionArray(x *ast.ArrayComprehension, b *ast.Term, } func (e *eval) biunifyComprehensionSet(x *ast.SetComprehension, b *ast.Term, b1, b2 *bindings, iter unifyIterator) error { - result := &ast.Set{} + result := ast.NewSet() child := e.closure(x.Body) err := child.Run(func(child *eval) error { result.Add(child.bindings.Plug(x.Term)) @@ -527,7 +569,7 @@ func (e *eval) biunifyComprehensionSet(x *ast.SetComprehension, b *ast.Term, b1, } func (e *eval) biunifyComprehensionObject(x *ast.ObjectComprehension, b *ast.Term, b1, b2 *bindings, iter unifyIterator) error { - result := ast.Object{} + result := ast.NewObject() child := e.closure(x.Body) err := child.Run(func(child *eval) error { key := child.bindings.Plug(x.Key) @@ -536,7 +578,7 @@ func (e *eval) biunifyComprehensionObject(x *ast.ObjectComprehension, b *ast.Ter if exist != nil && !exist.Equal(value) { return objectDocKeyConflictErr(x.Key.Location) } - result = append(result, ast.Item(key, value)) + result.Insert(key, value) return nil }) if err != nil { @@ -545,35 +587,66 @@ func (e *eval) biunifyComprehensionObject(x *ast.ObjectComprehension, b *ast.Ter return e.biunify(ast.NewTerm(result), b, b1, b2, iter) } +func (e *eval) saveExpr(expr *ast.Expr, b *bindings, iter unifyIterator) error { + e.saveStack.Push(expr, b, nil) + defer e.saveStack.Pop() + e.traceSave(expr) + return iter() +} + func (e *eval) saveUnify(a, b *ast.Term, b1, b2 *bindings, iter unifyIterator) error { expr := ast.Equality.Expr(a, b) elem := newSaveSetElem(e.getUnifyOutputs(expr)) e.saveSet.Push(elem) defer e.saveSet.Pop() - e.saveStack.Push(expr, b1) + e.saveStack.Push(expr, b1, b2) defer e.saveStack.Pop() + e.traceSave(expr) return iter() } -func (e *eval) saveCall(operator *ast.Term, args []*ast.Term, result *ast.Term, iter unifyIterator) error { +func (e *eval) saveVoidCall(operator *ast.Term, args []*ast.Term, iter unifyIterator) error { terms := make([]*ast.Term, len(args)+1) terms[0] = operator for i := 1; i < len(terms); i++ { terms[i] = args[i-1] } expr := ast.NewExpr(terms) + e.saveStack.Push(expr, e.bindings, nil) + defer e.saveStack.Pop() + e.traceSave(expr) + return iter() +} + +func (e *eval) saveCall(operator *ast.Term, args []*ast.Term, result *ast.Term, iter unifyIterator) error { + terms := make([]*ast.Term, len(args)+2) + terms[0] = operator + for i := 1; i < len(terms)-1; i++ { + terms[i] = args[i-1] + } + terms[len(terms)-1] = result + expr := ast.NewExpr(terms) elem := newSaveSetElem([]*ast.Term{result}) e.saveSet.Push(elem) defer e.saveSet.Pop() - e.saveStack.Push(expr, e.bindings) + e.saveStack.Push(expr, e.bindings, nil) defer e.saveStack.Pop() + e.traceSave(expr) return iter() } func (e *eval) getRules(ref ast.Ref) (*ast.IndexResult, error) { - if e.saveSet != nil { + + e.instr.startTimer(evalOpRuleIndex) + defer e.instr.stopTimer(evalOpRuleIndex) + + // If partial evaluation is being performed, the rule index cannot be used + // because the input may not be known and want to partially evaluate all + // rules. + if e.partial() { return e.getAllRules(ref), nil } + return e.getRulesIndexed(ref) } @@ -587,7 +660,7 @@ func (e *eval) getAllRules(ref ast.Ref) *ast.IndexResult { ir.Default = rule } else { ir.Rules = append(ir.Rules, rule) - for els := rule.Else; els != nil; els = rule.Else { + for els := rule.Else; els != nil; els = els.Else { ir.Else[rule] = append(ir.Else[rule], els) } } @@ -605,6 +678,9 @@ func (e *eval) getRulesIndexed(ref ast.Ref) (*ast.IndexResult, error) { func (e *eval) Resolve(ref ast.Ref) (ast.Value, error) { + e.instr.startTimer(evalOpResolve) + defer e.instr.stopTimer(evalOpResolve) + if ref[0].Equal(ast.InputRootDocument) { if e.input != nil { v, err := e.input.Value.Find(ref[1:]) @@ -668,6 +744,10 @@ func (e *eval) getUnifyOutputs(expr *ast.Expr) []*ast.Term { return outputs } +func (e *eval) generateVar(suffix string) *ast.Term { + return ast.VarTerm(fmt.Sprintf("%v_%v", e.genvarprefix, suffix)) +} + type evalBuiltin struct { e *eval bi *ast.Builtin @@ -678,20 +758,29 @@ type evalBuiltin struct { func (e evalBuiltin) eval(iter unifyIterator) error { - nargs := len(e.bi.Decl.Args()) - nterms := len(e.terms) - - args := make([]*ast.Term, nargs) + operands := make([]*ast.Term, len(e.terms)) - for i := 0; i < nargs; i++ { - args[i] = e.e.bindings.Plug(e.terms[i]) + for i := 0; i < len(e.terms); i++ { + operands[i] = e.e.bindings.Plug(e.terms[i]) } - return e.f(e.bctx, args, func(output *ast.Term) error { - if nargs == nterms { - return iter() + numDeclArgs := len(e.bi.Decl.Args()) + + e.e.instr.startTimer(evalOpBuiltinCall) + defer e.e.instr.stopTimer(evalOpBuiltinCall) + + return e.f(e.bctx, operands, func(output *ast.Term) error { + + e.e.instr.stopTimer(evalOpBuiltinCall) + defer e.e.instr.startTimer(evalOpBuiltinCall) + + if len(operands) == numDeclArgs { + if output.Value.Compare(ast.Boolean(false)) != 0 { + return iter() + } + return nil } - return e.e.unify(e.terms[nterms-1], output, iter) + return e.e.unify(e.terms[len(e.terms)-1], output, iter) }) } @@ -742,30 +831,43 @@ func (e evalFunc) evalOneRule(iter unifyIterator, rule *ast.Rule, prev *ast.Term child := e.e.child(rule.Body) - b := make(ast.Array, len(e.terms)) + args := make(ast.Array, len(e.terms)) + for i := range rule.Head.Args { - b[i] = rule.Head.Args[i] + args[i] = rule.Head.Args[i] } - if len(b) == len(rule.Head.Args)+1 { - b[len(b)-1] = rule.Head.Value + if len(args) == len(rule.Head.Args)+1 { + args[len(args)-1] = rule.Head.Value } var result *ast.Term child.traceEnter(rule) - err := child.biunifyArrays(e.terms, b, e.e.bindings, child.bindings, func() error { + err := child.biunifyArrays(e.terms, args, e.e.bindings, child.bindings, func() error { return child.eval(func(child *eval) error { child.traceExit(rule) result = child.bindings.Plug(rule.Head.Value) - if prev != nil { - if ast.Compare(prev, result) != 0 { - return functionConflictErr(rule.Location) + if len(e.terms) == len(rule.Head.Args) { + if result.Value.Compare(ast.Boolean(false)) == 0 { + return nil + } + } + + // Partial evaluation should explore all rules and may not produce + // a ground result so we do not perform conflict detection or + // deduplication. See "ignore conflicts: functions" test case for + // an example. + if !e.e.partial() { + if prev != nil { + if ast.Compare(prev, result) != 0 { + return functionConflictErr(rule.Location) + } + child.traceRedo(rule) + return nil } - child.traceRedo(rule) - return nil } prev = result @@ -810,6 +912,13 @@ func (e evalTree) eval(iter unifyIterator) error { func (e evalTree) finish(iter unifyIterator) error { + // During partial evaluation it may not be possible to compute the value + // for this reference if it refers to a virtual document so save the entire + // expression. See "save: full extent" test case for an example. + if e.e.partial() && e.node != nil { + return e.e.saveUnify(ast.NewTerm(e.plugged), e.rterm, e.bindings, e.rbindings, iter) + } + v, err := e.extent() if err != nil || v == nil { return err @@ -868,13 +977,13 @@ func (e evalTree) enumerate(iter unifyIterator) error { } } case ast.Object: - for _, pair := range doc { - err := e.e.biunify(pair[0], e.ref[e.pos], e.bindings, e.bindings, func() error { - return e.next(iter, pair[0]) + err := doc.Iter(func(k, _ *ast.Term) error { + return e.e.biunify(k, e.ref[e.pos], e.bindings, e.bindings, func() error { + return e.next(iter, k) }) - if err != nil { - return err - } + }) + if err != nil { + return err } } } @@ -911,9 +1020,15 @@ func (e evalTree) extent() (*ast.Term, error) { } return ast.NewTerm(base), nil } - if base != nil { - merged, _ := base.(ast.Object).Merge(virtual) + merged, ok := base.(ast.Object).Merge(virtual) + if !ok { + // TODO(tsandall): the location used in this error could be + // improved to reference the containing expression. We should + // update the eval struct to keep track of the currently evaluation + // expression. + return nil, documentConflictErr(e.ref[0].Location) + } return ast.NewTerm(merged), nil } @@ -926,7 +1041,7 @@ func (e evalTree) leaves(plugged ast.Ref, node *ast.TreeNode) (ast.Object, error return nil, nil } - result := ast.Object{} + result := ast.NewObject() for _, child := range node.Children { if child.Hide { @@ -939,7 +1054,7 @@ func (e evalTree) leaves(plugged ast.Ref, node *ast.TreeNode) (ast.Object, error var err error if len(child.Values) > 0 { - rterm := ast.VarTerm(ast.WildcardPrefix + "leaf") + rterm := e.e.generateVar("leaf") err = e.e.unify(ast.NewTerm(plugged), rterm, func() error { save = e.e.bindings.Plug(rterm).Value return nil @@ -953,7 +1068,8 @@ func (e evalTree) leaves(plugged ast.Ref, node *ast.TreeNode) (ast.Object, error } if save != nil { - result, _ = result.Merge(ast.Object{ast.Item(plugged[len(plugged)-1], ast.NewTerm(save))}) + v := ast.NewObject([2]*ast.Term{plugged[len(plugged)-1], ast.NewTerm(save)}) + result, _ = result.Merge(v) } plugged = plugged[:len(plugged)-1] @@ -979,6 +1095,12 @@ func (e evalVirtual) eval(iter unifyIterator) error { return err } + // Partial evaluation of ordered rules is not supported currently. Save the + // expression and continue. This could be revisited in the future. + if e.e.partial() && len(ir.Else) > 0 { + return e.e.saveUnify(ast.NewTerm(e.ref), e.rterm, e.bindings, e.rbindings, iter) + } + switch ir.Kind { case ast.PartialSetDoc: eval := evalVirtualPartial{ @@ -1036,6 +1158,12 @@ type evalVirtualPartial struct { func (e evalVirtualPartial) eval(iter unifyIterator) error { if len(e.ref) == e.pos+1 { + // During partial evaluation, it may not be possible to produce a value + // for this reference so save the entire expression. See "save: full + // extent: partial object" test case for an example. + if e.e.partial() { + return e.e.saveUnify(ast.NewTerm(e.ref), e.rterm, e.bindings, e.rbindings, iter) + } return e.evalAllRules(iter, e.ir.Rules) } @@ -1050,9 +1178,11 @@ func (e evalVirtualPartial) eval(iter unifyIterator) error { cached := e.e.virtualCache.Get(path) if cached != nil { + e.e.instr.counterIncr(evalOpVirtualCacheHit) return e.evalTerm(iter, cached, e.bindings) } + e.e.instr.counterIncr(evalOpVirtualCacheMiss) cacheKey = path } } @@ -1157,7 +1287,7 @@ func (e evalVirtualPartial) evalTerm(iter unifyIterator, term *ast.Term, termbin func (e evalVirtualPartial) reduce(head *ast.Head, b *bindings, result *ast.Term) (*ast.Term, error) { switch v := result.Value.(type) { - case *ast.Set: + case ast.Set: v.Add(b.Plug(head.Key)) case ast.Object: key := b.Plug(head.Key) @@ -1166,7 +1296,7 @@ func (e evalVirtualPartial) reduce(head *ast.Head, b *bindings, result *ast.Term if exist != nil && !exist.Equal(value) { return nil, objectDocKeyConflictErr(head.Location) } - v = append(v, ast.Item(key, value)) + v.Insert(key, value) result.Value = v } @@ -1194,22 +1324,36 @@ func (e evalVirtualComplete) eval(iter unifyIterator) error { return nil } - cached := e.e.virtualCache.Get(e.plugged[:e.pos+1]) + if !e.e.partial() { + return e.evalValue(iter) + } + + if e.ir.Default == nil { + return e.partialEval(iter) + } + return e.partialEvalDefault(iter) +} + +func (e evalVirtualComplete) evalValue(iter unifyIterator) error { + cached := e.e.virtualCache.Get(e.plugged[:e.pos+1]) if cached != nil { + e.e.instr.counterIncr(evalOpVirtualCacheHit) return e.evalTerm(iter, cached, e.bindings) } + e.e.instr.counterIncr(evalOpVirtualCacheMiss) + var prev *ast.Term for i := range e.ir.Rules { - next, err := e.evalRule(iter, e.ir.Rules[i], prev) + next, err := e.evalValueRule(iter, e.ir.Rules[i], prev) if err != nil { return err } if next == nil { for _, rule := range e.ir.Else[e.ir.Rules[i]] { - next, err = e.evalRule(iter, rule, prev) + next, err = e.evalValueRule(iter, rule, prev) if err != nil { return err } @@ -1224,19 +1368,18 @@ func (e evalVirtualComplete) eval(iter unifyIterator) error { } if e.ir.Default != nil && prev == nil { - _, err := e.evalRule(iter, e.ir.Default, prev) + _, err := e.evalValueRule(iter, e.ir.Default, prev) return err } return nil } -func (e evalVirtualComplete) evalRule(iter unifyIterator, rule *ast.Rule, prev *ast.Term) (*ast.Term, error) { +func (e evalVirtualComplete) evalValueRule(iter unifyIterator, rule *ast.Rule, prev *ast.Term) (*ast.Term, error) { child := e.e.child(rule.Body) - var result *ast.Term - child.traceEnter(rule) + var result *ast.Term err := child.eval(func(child *eval) error { child.traceExit(rule) @@ -1250,10 +1393,10 @@ func (e evalVirtualComplete) evalRule(iter unifyIterator, rule *ast.Rule, prev * return nil } - e.e.virtualCache.Put(e.plugged[:e.pos+1], result) - prev = result + e.e.virtualCache.Put(e.plugged[:e.pos+1], result) term, termbindings := child.bindings.apply(rule.Head.Value) + err := e.evalTerm(iter, term, termbindings) if err != nil { return err @@ -1263,13 +1406,83 @@ func (e evalVirtualComplete) evalRule(iter unifyIterator, rule *ast.Rule, prev * return nil }) - if err != nil { - return nil, err - } else if result != nil { - return result, nil + return result, err +} + +func (e evalVirtualComplete) partialEval(iter unifyIterator) error { + + for _, rule := range e.ir.Rules { + child := e.e.child(rule.Body) + child.traceEnter(rule) + + err := child.eval(func(child *eval) error { + child.traceExit(rule) + term, termbindings := child.bindings.apply(rule.Head.Value) + + err := e.evalTerm(iter, term, termbindings) + if err != nil { + return err + } + + child.traceRedo(rule) + return nil + }) + + if err != nil { + return err + } } - return nil, nil + return nil +} + +func (e evalVirtualComplete) partialEvalDefault(iter unifyIterator) error { + + path := e.plugged[:e.pos+1].Insert(e.e.saveNamespace, 1) + + if !e.e.saveSupport.Exists(path) { + + for i := range e.ir.Rules { + err := e.partialEvalDefaultRule(iter, e.ir.Rules[i], path) + if err != nil { + return err + } + } + + err := e.partialEvalDefaultRule(iter, e.ir.Default, path) + if err != nil { + return err + } + } + + rewritten := ast.NewTerm(e.ref.Insert(e.e.saveNamespace, 1)) + return e.e.saveUnify(rewritten, e.rterm, e.bindings, e.rbindings, iter) +} + +func (e evalVirtualComplete) partialEvalDefaultRule(iter unifyIterator, rule *ast.Rule, path ast.Ref) error { + + child := e.e.child(rule.Body) + child.traceEnter(rule) + + e.e.saveStack.PushQuery(nil) + defer e.e.saveStack.PopQuery() + + return child.eval(func(child *eval) error { + child.traceExit(rule) + + current := e.e.saveStack.PopQuery() + defer e.e.saveStack.PushQuery(current) + plugged := current.Plug(child.bindings) + + e.e.saveSupport.Insert(path, &ast.Rule{ + Head: ast.NewHead(rule.Head.Name, nil, child.bindings.PlugNamespaced(rule.Head.Value, child.bindings)), + Body: plugged, + Default: rule.Default, + }) + + child.traceRedo(rule) + return nil + }) } func (e evalVirtualComplete) evalTerm(iter unifyIterator, term *ast.Term, termbindings *bindings) error { @@ -1343,23 +1556,17 @@ func (e evalTerm) enumerate(iter unifyIterator) error { } } case ast.Object: - for _, pair := range v { - err := e.e.biunify(pair[0], e.ref[e.pos], e.termbindings, e.bindings, func() error { + return v.Iter(func(k, _ *ast.Term) error { + return e.e.biunify(k, e.ref[e.pos], e.termbindings, e.bindings, func() error { return e.next(iter, e.bindings.Plug(e.ref[e.pos])) }) - if err != nil { - return err - } - } - case *ast.Set: - for _, elem := range *v { - err := e.e.biunify(elem, e.ref[e.pos], e.termbindings, e.bindings, func() error { + }) + case ast.Set: + return v.Iter(func(elem *ast.Term) error { + return e.e.biunify(elem, e.ref[e.pos], e.termbindings, e.bindings, func() error { return e.next(iter, e.bindings.Plug(e.ref[e.pos])) }) - if err != nil { - return err - } - } + }) } return nil @@ -1367,16 +1574,23 @@ func (e evalTerm) enumerate(iter unifyIterator) error { func (e evalTerm) get(plugged *ast.Term) (*ast.Term, *bindings) { switch v := e.term.Value.(type) { - case *ast.Set: + case ast.Set: if v.IsGround() { if v.Contains(plugged) { return e.termbindings.apply(plugged) } } else { - for _, elem := range *v { + var t *ast.Term + var b *bindings + stop := v.Until(func(elem *ast.Term) bool { if e.termbindings.Plug(elem).Equal(plugged) { - return e.termbindings.apply(plugged) + t, b = e.termbindings.apply(plugged) + return true } + return false + }) + if stop { + return t, b } } case ast.Object: @@ -1386,10 +1600,17 @@ func (e evalTerm) get(plugged *ast.Term) (*ast.Term, *bindings) { return e.termbindings.apply(term) } } else { - for i := range v { - if e.termbindings.Plug(v[i][0]).Equal(plugged) { - return e.termbindings.apply(v[i][1]) + var t *ast.Term + var b *bindings + stop := v.Until(func(k, v *ast.Term) bool { + if e.termbindings.Plug(k).Equal(plugged) { + t, b = e.termbindings.apply(v) + return true } + return false + }) + if stop { + return t, b } } case ast.Array: @@ -1400,3 +1621,16 @@ func (e evalTerm) get(plugged *ast.Term) (*ast.Term, *bindings) { } return nil, nil } + +func nonGroundKeys(a ast.Object) bool { + return a.Until(func(k, _ *ast.Term) bool { + return !k.IsGround() + }) +} + +func plugKeys(a ast.Object, b *bindings) ast.Object { + plugged, _ := a.Map(func(k, v *ast.Term) (*ast.Term, *ast.Term, error) { + return b.Plug(k), v, nil + }) + return plugged +} diff --git a/github.com/open-policy-agent/opa/topdown/http.go b/github.com/open-policy-agent/opa/topdown/http.go new file mode 100644 index 00000000..3cd1f0ed --- /dev/null +++ b/github.com/open-policy-agent/opa/topdown/http.go @@ -0,0 +1,174 @@ +// Copyright 2018 The OPA Authors. All rights reserved. +// Use of this source code is governed by an Apache2 +// license that can be found in the LICENSE file. + +package topdown + +import ( + "bytes" + "encoding/json" + + "net/http" + "os" + "strings" + "time" + + "github.com/open-policy-agent/opa/ast" + "github.com/open-policy-agent/opa/topdown/builtins" +) + +const defaultHTTPRequestTimeout = time.Second * 5 + +var allowedKeys = ast.NewSet(ast.StringTerm("method"), ast.StringTerm("url"), ast.StringTerm("body")) +var requiredKeys = ast.NewSet(ast.StringTerm("method"), ast.StringTerm("url")) + +var client *http.Client + +func builtinHTTPSend(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error { + + req, err := validateHTTPRequestOperand(args[0], 1) + if err != nil { + return handleBuiltinErr(ast.HTTPSend.Name, bctx.Location, err) + } + + resp, err := executeHTTPRequest(bctx, req) + if err != nil { + return handleBuiltinErr(ast.HTTPSend.Name, bctx.Location, err) + } + + return iter(ast.NewTerm(resp)) +} + +func init() { + createHTTPClient() + RegisterBuiltinFunc(ast.HTTPSend.Name, builtinHTTPSend) +} + +func createHTTPClient() { + timeout := defaultHTTPRequestTimeout + timeoutDuration := os.Getenv("HTTP_SEND_TIMEOUT") + if timeoutDuration != "" { + timeout, _ = time.ParseDuration(timeoutDuration) + } + client = &http.Client{ + Timeout: timeout, + } +} + +func validateHTTPRequestOperand(term *ast.Term, pos int) (ast.Object, error) { + + obj, err := builtins.ObjectOperand(term.Value, pos) + if err != nil { + return nil, err + } + + requestKeys := ast.NewSet(obj.Keys()...) + + invalidKeys := requestKeys.Diff(allowedKeys) + if invalidKeys.Len() != 0 { + return nil, builtins.NewOperandErr(pos, "invalid request parameters(s): %v", invalidKeys) + } + + missingKeys := requiredKeys.Diff(requestKeys) + if missingKeys.Len() != 0 { + return nil, builtins.NewOperandErr(pos, "missing required request parameters(s): %v", missingKeys) + } + + return obj, nil + +} + +func executeHTTPRequest(bctx BuiltinContext, obj ast.Object) (ast.Value, error) { + var url string + var method string + var body *bytes.Buffer + for _, val := range obj.Keys() { + key, err := ast.JSON(val.Value) + if err != nil { + return nil, err + } + key = key.(string) + + if key == "method" { + method = obj.Get(val).String() + method = strings.Trim(method, "\"") + } else if key == "url" { + url = obj.Get(val).String() + url = strings.Trim(url, "\"") + } else { + bodyVal := obj.Get(val).Value + bodyValInterface, err := ast.JSON(bodyVal) + if err != nil { + return nil, err + } + + bodyValBytes, err := json.Marshal(bodyValInterface) + if err != nil { + return nil, err + } + body = bytes.NewBuffer(bodyValBytes) + } + } + + if body == nil { + body = bytes.NewBufferString("") + } + + // check if cache already has a response for this query + cachedResponse := checkCache(method, url, bctx) + if cachedResponse != nil { + return cachedResponse, nil + } + + // create the http request + req, err := http.NewRequest(strings.ToUpper(method), url, body) + if err != nil { + return nil, err + } + + // execute the http request + resp, err := client.Do(req) + if err != nil { + return nil, err + } + + defer resp.Body.Close() + + // format the http result + var resultBody interface{} + json.NewDecoder(resp.Body).Decode(&resultBody) + + result := make(map[string]interface{}) + result["status"] = resp.Status + result["status_code"] = resp.StatusCode + result["body"] = resultBody + + resultObj, err := ast.InterfaceToValue(result) + if err != nil { + return nil, err + } + + // add result to cache + key := getCtxKey(method, url) + bctx.Cache.Put(key, resultObj) + + return resultObj, nil +} + +// getCtxKey returns the cache key. +// Key format: _ +func getCtxKey(method string, url string) string { + keyTerms := []string{strings.ToUpper(method), url} + return strings.Join(keyTerms, "_") +} + +// checkCache checks for the given key's value in the cache +func checkCache(method string, url string, bctx BuiltinContext) ast.Value { + key := getCtxKey(method, url) + + val, ok := bctx.Cache.Get(key) + if ok { + return val.(ast.Value) + } + return nil +} diff --git a/github.com/open-policy-agent/opa/topdown/input.go b/github.com/open-policy-agent/opa/topdown/input.go index 62afe491..962a3cb9 100644 --- a/github.com/open-policy-agent/opa/topdown/input.go +++ b/github.com/open-policy-agent/opa/topdown/input.go @@ -66,10 +66,9 @@ func makeInput(pairs [][2]*ast.Term) (ast.Value, error) { func makeTree(k ast.Ref, v *ast.Term) ast.Object { var obj ast.Object for i := len(k) - 1; i >= 1; i-- { - obj = ast.Object{ast.Item(k[i], v)} + obj = ast.NewObject(ast.Item(k[i], v)) v = &ast.Term{Value: obj} - obj = ast.Object{} } - obj = ast.Object{ast.Item(k[0], v)} + obj = ast.NewObject(ast.Item(k[0], v)) return obj } diff --git a/github.com/open-policy-agent/opa/topdown/instrumentation.go b/github.com/open-policy-agent/opa/topdown/instrumentation.go new file mode 100644 index 00000000..b660e2fd --- /dev/null +++ b/github.com/open-policy-agent/opa/topdown/instrumentation.go @@ -0,0 +1,53 @@ +// Copyright 2018 The OPA Authors. All rights reserved. +// Use of this source code is governed by an Apache2 +// license that can be found in the LICENSE file. + +package topdown + +import "github.com/open-policy-agent/opa/metrics" + +const ( + evalOpPlug = "eval_op_plug" + evalOpResolve = "eval_op_resolve" + evalOpRuleIndex = "eval_op_rule_index" + evalOpBuiltinCall = "eval_op_builtin_call" + evalOpVirtualCacheHit = "eval_op_virtual_cache_hit" + evalOpVirtualCacheMiss = "eval_op_virtual_cache_miss" +) + +// Instrumentation implements helper functions to instrument query evaluation +// to diagnose performance issues. Instrumentation may be expensive in some +// cases, so it is disabled by default. +type Instrumentation struct { + m metrics.Metrics +} + +// NewInstrumentation returns a new Instrumentation object. Performance +// diagnostics recorded on this Instrumentation object will stored in m. +func NewInstrumentation(m metrics.Metrics) *Instrumentation { + return &Instrumentation{ + m: m, + } +} + +func (instr *Instrumentation) startTimer(name string) { + if instr == nil { + return + } + instr.m.Timer(name).Start() +} + +func (instr *Instrumentation) stopTimer(name string) { + if instr == nil { + return + } + delta := instr.m.Timer(name).Stop() + instr.m.Histogram(name).Update(delta) +} + +func (instr *Instrumentation) counterIncr(name string) { + if instr == nil { + return + } + instr.m.Counter(name).Incr() +} diff --git a/github.com/open-policy-agent/opa/topdown/partial.go b/github.com/open-policy-agent/opa/topdown/partial.go deleted file mode 100644 index 282ee13e..00000000 --- a/github.com/open-policy-agent/opa/topdown/partial.go +++ /dev/null @@ -1,136 +0,0 @@ -package topdown - -import "github.com/open-policy-agent/opa/ast" - -type saveSet struct { - s []*saveSetElem -} - -func newSaveSet(terms []*ast.Term) *saveSet { - return &saveSet{[]*saveSetElem{newSaveSetElem(terms)}} -} - -func (n *saveSet) Empty() bool { - if n != nil { - for i := range n.s { - if len(n.s[i].children) != 0 { - return false - } - } - } - return true -} - -func (n *saveSet) Contains(x *ast.Term) bool { - if n != nil { - for i := len(n.s) - 1; i >= 0; i-- { - if n.s[i].Contains(x) { - return true - } - } - } - return false -} - -func (n *saveSet) ContainsAny(xs []*ast.Term) bool { - for i := range xs { - if n.Contains(xs[i]) { - return true - } - } - return false -} - -func (n *saveSet) Push(x *saveSetElem) { - n.s = append(n.s, x) -} - -func (n *saveSet) Pop() { - n.s = n.s[:len(n.s)-1] -} - -type saveSetElem struct { - children map[ast.Value]*saveSetElem -} - -func newSaveSetElem(terms []*ast.Term) *saveSetElem { - elem := &saveSetElem{ - children: map[ast.Value]*saveSetElem{}, - } - for i := range terms { - elem.Insert(terms[i]) - } - return elem -} - -func (n *saveSetElem) Empty() bool { - return n == nil || len(n.children) == 0 -} - -func (n *saveSetElem) Contains(x *ast.Term) bool { - switch x := x.Value.(type) { - case ast.Ref: - curr := n - for i := 0; i < len(x); i++ { - if curr = curr.child(x[i].Value); curr == nil { - return false - } else if curr.Empty() { - return true - } - } - return true - case ast.Var, ast.String: - return n.child(x) != nil - default: - return false - } -} -func (n *saveSetElem) Insert(x *ast.Term) *saveSetElem { - if n == nil { - return nil - } - switch v := x.Value.(type) { - case ast.Ref: - curr := n - for i := 0; i < len(v); i++ { - curr = curr.Insert(v[i]) - } - return curr - case ast.Var, ast.String: - child := n.children[v] - if child == nil { - child = newSaveSetElem(nil) - n.children[v] = child - } - return child - } - return nil -} - -func (n *saveSetElem) child(v ast.Value) *saveSetElem { - if n == nil { - return nil - } - return n.children[v] -} - -type saveStack struct { - Stack []saveStackElem -} - -func newSaveStack() *saveStack { - return &saveStack{} -} - -type saveStackElem struct { - Expr *ast.Expr - Bindings *bindings -} - -func (s *saveStack) Push(expr *ast.Expr, b *bindings) { - s.Stack = append(s.Stack, saveStackElem{expr, b}) -} - -func (s *saveStack) Pop() { - s.Stack = s.Stack[:len(s.Stack)-1] -} diff --git a/github.com/open-policy-agent/opa/topdown/query.go b/github.com/open-policy-agent/opa/topdown/query.go index 0ce88b87..47e1be18 100644 --- a/github.com/open-policy-agent/opa/topdown/query.go +++ b/github.com/open-policy-agent/opa/topdown/query.go @@ -2,6 +2,7 @@ package topdown import ( "context" + "sort" "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/metrics" @@ -18,20 +19,26 @@ type QueryResult map[ast.Var]*ast.Term // Query provides a configurable interface for performing query evaluation. type Query struct { - cancel Cancel - query ast.Body - compiler *ast.Compiler - store storage.Store - txn storage.Transaction - input *ast.Term - tracer Tracer - partial []*ast.Term - metrics metrics.Metrics + cancel Cancel + query ast.Body + compiler *ast.Compiler + store storage.Store + txn storage.Transaction + input *ast.Term + tracer Tracer + unknowns []*ast.Term + partialNamespace string + metrics metrics.Metrics + instr *Instrumentation + genvarprefix string } // NewQuery returns a new Query object that can be run. func NewQuery(query ast.Body) *Query { - return &Query{query: query} + return &Query{ + query: query, + genvarprefix: ast.WildcardPrefix, + } } // WithCompiler sets the compiler to use for the query. @@ -75,59 +82,89 @@ func (q *Query) WithTracer(tracer Tracer) *Query { // WithMetrics sets the metrics collection to add evaluation metrics to. This // is optional. -func (q *Query) WithMetrics(metrics metrics.Metrics) *Query { - q.metrics = metrics +func (q *Query) WithMetrics(m metrics.Metrics) *Query { + q.metrics = m return q } -// WithPartial sets the initial set of vars or refs to treat as unavailable -// during query evaluation. This is typically required for partial evaluation. -func (q *Query) WithPartial(terms []*ast.Term) *Query { - q.partial = terms +// WithInstrumentation sets the instrumentation configuration to enable on the +// evaluation process. By default, instrumentation is turned off. +func (q *Query) WithInstrumentation(instr *Instrumentation) *Query { + q.instr = instr return q } -// PartialRun is a wrapper around PartialIter that accumulates results and returns -// them in one shot. -func (q *Query) PartialRun(ctx context.Context) ([]ast.Body, error) { - partials := []ast.Body{} - return partials, q.PartialIter(ctx, func(partial ast.Body) error { - partials = append(partials, partial) - return nil - }) +// WithUnknowns sets the initial set of variables or references to treat as +// unknown during query evaluation. This is required for partial evaluation. +func (q *Query) WithUnknowns(terms []*ast.Term) *Query { + q.unknowns = terms + return q +} + +// WithPartialNamespace sets the namespace to use for supporting rules +// generated as part of the partial evaluation process. The ns value must be a +// valid package path component. +func (q *Query) WithPartialNamespace(ns string) *Query { + q.partialNamespace = ns + return q } -// PartialIter executes the query invokes the iter function with partially -// evaluated queries produced by evaluating the query with a partial set. -func (q *Query) PartialIter(ctx context.Context, iter func(ast.Body) error) error { +// PartialRun executes partial evaluation on the query with respect to unknown +// values. Partial evaluation attempts to evaluate as much of the query as +// possible without requiring values for the unknowns set on the query. The +// result of partial evaluation is a new set of queries that can be evaluated +// once the unknown value is known. In addition to new queries, partial +// evaluation may produce additional support modules that should be used in +// conjunction with the partially evaluated queries. +func (q *Query) PartialRun(ctx context.Context) (partials []ast.Body, support []*ast.Module, err error) { + if q.partialNamespace == "" { + q.partialNamespace = "partial" // lazily initialize partial namespace + } e := &eval{ - ctx: ctx, - cancel: q.cancel, - query: q.query, - bindings: newBindings(), - compiler: q.compiler, - store: q.store, - txn: q.txn, - input: q.input, - tracer: q.tracer, - builtinCache: builtins.Cache{}, - virtualCache: newVirtualCache(), - saveSet: newSaveSet(q.partial), - saveStack: newSaveStack(), + ctx: ctx, + cancel: q.cancel, + query: q.query, + bindings: newBindings(0, q.instr), + compiler: q.compiler, + store: q.store, + txn: q.txn, + input: q.input, + tracer: q.tracer, + instr: q.instr, + builtinCache: builtins.Cache{}, + virtualCache: newVirtualCache(), + saveSet: newSaveSet(q.unknowns), + saveStack: newSaveStack(), + saveSupport: newSaveSupport(), + saveNamespace: ast.StringTerm(q.partialNamespace), + genvarprefix: q.genvarprefix, } - q.startTimer() - defer q.stopTimer() - return e.Run(func(e *eval) error { + q.startTimer(metrics.RegoPartialEval) + defer q.stopTimer(metrics.RegoPartialEval) + err = e.Run(func(e *eval) error { + // Build output from saved expressions. body := ast.NewBody() - for _, elem := range e.saveStack.Stack { - body.Append(plugExpr(elem.Bindings, elem.Expr)) + for _, elem := range e.saveStack.Stack[len(e.saveStack.Stack)-1] { + body.Append(elem.Plug(e.bindings)) } - e.bindings.Iter(func(a, b *ast.Term) error { - body.Append(ast.Equality.Expr(a, b)) + // Include bindings as exprs so that when caller evals the result, they + // can obtain values for the vars in their query. + bindingExprs := []*ast.Expr{} + e.bindings.Iter(e.bindings, func(a, b *ast.Term) error { + bindingExprs = append(bindingExprs, ast.Equality.Expr(a, b)) return nil }) - return iter(body) + // Sort binding expressions so that results are deterministic. + sort.Slice(bindingExprs, func(i, j int) bool { + return bindingExprs[i].Compare(bindingExprs[j]) < 0 + }) + for i := range bindingExprs { + body.Append(bindingExprs[i]) + } + partials = append(partials, body) + return nil }) + return partials, e.saveSupport.List(), err } // Run is a wrapper around Iter that accumulates query results and returns them @@ -147,20 +184,22 @@ func (q *Query) Iter(ctx context.Context, iter func(QueryResult) error) error { ctx: ctx, cancel: q.cancel, query: q.query, - bindings: newBindings(), + bindings: newBindings(0, q.instr), compiler: q.compiler, store: q.store, txn: q.txn, input: q.input, tracer: q.tracer, + instr: q.instr, builtinCache: builtins.Cache{}, virtualCache: newVirtualCache(), + genvarprefix: q.genvarprefix, } - q.startTimer() - defer q.stopTimer() + q.startTimer(metrics.RegoQueryEval) + defer q.stopTimer(metrics.RegoQueryEval) return e.Run(func(e *eval) error { qr := QueryResult{} - e.bindings.Iter(func(k, v *ast.Term) error { + e.bindings.Iter(nil, func(k, v *ast.Term) error { qr[k.Value.(ast.Var)] = v return nil }) @@ -168,27 +207,14 @@ func (q *Query) Iter(ctx context.Context, iter func(QueryResult) error) error { }) } -func (q *Query) startTimer() { +func (q *Query) startTimer(name string) { if q.metrics != nil { - q.metrics.Timer(metrics.RegoQueryEval).Start() + q.metrics.Timer(name).Start() } } -func (q *Query) stopTimer() { +func (q *Query) stopTimer(name string) { if q.metrics != nil { - q.metrics.Timer(metrics.RegoQueryEval).Stop() - } -} - -func plugExpr(b *bindings, expr *ast.Expr) *ast.Expr { - expr = expr.Copy() - switch terms := expr.Terms.(type) { - case *ast.Term: - expr.Terms = b.Plug(terms) - case []*ast.Term: - for i := range terms { - terms[i] = b.Plug(terms[i]) - } + q.metrics.Timer(name).Stop() } - return expr } diff --git a/github.com/open-policy-agent/opa/topdown/regex.go b/github.com/open-policy-agent/opa/topdown/regex.go index f273a504..02965946 100644 --- a/github.com/open-policy-agent/opa/topdown/regex.go +++ b/github.com/open-policy-agent/opa/topdown/regex.go @@ -8,6 +8,8 @@ import ( "regexp" "sync" + "github.com/yashtewari/glob-intersection" + "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/topdown/builtins" ) @@ -28,10 +30,7 @@ func builtinRegexMatch(a, b ast.Value) (ast.Value, error) { if err != nil { return nil, err } - if re.Match([]byte(s2)) { - return ast.Boolean(true), nil - } - return nil, BuiltinEmpty{} + return ast.Boolean(re.Match([]byte(s2))), nil } func getRegexp(pat string) (*regexp.Regexp, error) { @@ -49,7 +48,24 @@ func getRegexp(pat string) (*regexp.Regexp, error) { return re, nil } +func builtinGlobsMatch(a, b ast.Value) (ast.Value, error) { + s1, err := builtins.StringOperand(a, 1) + if err != nil { + return nil, err + } + s2, err := builtins.StringOperand(b, 2) + if err != nil { + return nil, err + } + ne, err := gintersect.NonEmpty(string(s1), string(s2)) + if err != nil { + return nil, err + } + return ast.Boolean(ne), nil +} + func init() { regexpCache = map[string]*regexp.Regexp{} RegisterFunctionalBuiltin2(ast.RegexMatch.Name, builtinRegexMatch) + RegisterFunctionalBuiltin2(ast.GlobsMatch.Name, builtinGlobsMatch) } diff --git a/github.com/open-policy-agent/opa/topdown/save.go b/github.com/open-policy-agent/opa/topdown/save.go new file mode 100644 index 00000000..f77e84d4 --- /dev/null +++ b/github.com/open-policy-agent/opa/topdown/save.go @@ -0,0 +1,263 @@ +package topdown + +import ( + "github.com/open-policy-agent/opa/ast" +) + +// saveSet contains a set of terms that are treated as unknown. The set is +// implemented as a tree so that we can partially evaluate data/input that is +// only partially known. E.g., policies expressed over input.x and input.y may +// be partially evaluated assuming input.x is known and input.y is unknown. +// +// Any time a variable is unified with an element in the set (an unknown), the +// variable is added to the set so that subsequent references to the variable +// are also treated as unknown. +type saveSet struct { + s []*saveSetElem +} + +func newSaveSet(terms []*ast.Term) *saveSet { + return &saveSet{[]*saveSetElem{newSaveSetElem(terms)}} +} + +func (n *saveSet) Empty() bool { + if n != nil { + for i := range n.s { + if len(n.s[i].children) != 0 { + return false + } + } + } + return true +} + +func (n *saveSet) Contains(x *ast.Term) bool { + if n != nil { + for i := len(n.s) - 1; i >= 0; i-- { + if n.s[i].Contains(x) { + return true + } + } + } + return false +} + +func (n *saveSet) ContainsAny(xs []*ast.Term) bool { + for i := range xs { + if n.Contains(xs[i]) { + return true + } + } + return false +} + +func (n *saveSet) Push(x *saveSetElem) { + n.s = append(n.s, x) +} + +func (n *saveSet) Pop() { + n.s = n.s[:len(n.s)-1] +} + +type saveSetElem struct { + children map[ast.Value]*saveSetElem +} + +func newSaveSetElem(terms []*ast.Term) *saveSetElem { + elem := &saveSetElem{ + children: map[ast.Value]*saveSetElem{}, + } + for i := range terms { + elem.Insert(terms[i]) + } + return elem +} + +func (n *saveSetElem) Empty() bool { + return n == nil || len(n.children) == 0 +} + +func (n *saveSetElem) Contains(x *ast.Term) bool { + switch x := x.Value.(type) { + case ast.Ref: + curr := n + for i := 0; i < len(x); i++ { + if curr = curr.child(x[i].Value); curr == nil { + return false + } else if curr.Empty() { + return true + } + } + return true + case ast.Var, ast.String: + return n.child(x) != nil + default: + return false + } +} + +func (n *saveSetElem) Insert(x *ast.Term) *saveSetElem { + if n == nil { + return nil + } + switch v := x.Value.(type) { + case ast.Ref: + curr := n + for i := 0; i < len(v); i++ { + curr = curr.Insert(v[i]) + } + return curr + case ast.Var, ast.String: + child := n.children[v] + if child == nil { + child = newSaveSetElem(nil) + n.children[v] = child + } + return child + } + return nil +} + +func (n *saveSetElem) child(v ast.Value) *saveSetElem { + if n == nil { + return nil + } + return n.children[v] +} + +// saveStack contains a stack of queries that represent the result of partial +// evaluation. When partial evaluation completes, the top of the stack +// represents a complete, partially evaluated query that can be saved and +// evaluated later. +// +// The result is stored in a stack so that partial evaluation of a query can be +// paused and then resumed in cases where different queries make up the result +// of partial evaluation, such as when a rule with a default clause is +// partially evaluated. In this case, the partially evaluated rule will be +// output in the support module. +type saveStack struct { + Stack []saveStackQuery +} + +func newSaveStack() *saveStack { + return &saveStack{ + Stack: []saveStackQuery{ + saveStackQuery{}, + }, + } +} + +func (s *saveStack) PushQuery(query saveStackQuery) { + s.Stack = append(s.Stack, query) +} + +func (s *saveStack) PopQuery() saveStackQuery { + last := s.Stack[len(s.Stack)-1] + s.Stack = s.Stack[:len(s.Stack)-1] + return last +} + +func (s *saveStack) Push(expr *ast.Expr, b1 *bindings, b2 *bindings) { + idx := len(s.Stack) - 1 + s.Stack[idx] = append(s.Stack[idx], saveStackElem{expr, b1, b2}) +} + +func (s *saveStack) Pop() { + idx := len(s.Stack) - 1 + query := s.Stack[idx] + s.Stack[idx] = query[:len(query)-1] +} + +type saveStackQuery []saveStackElem + +func (s saveStackQuery) Plug(b *bindings) ast.Body { + if len(s) == 0 { + return ast.NewBody(ast.NewExpr(ast.BooleanTerm(true))) + } + result := make(ast.Body, len(s)) + for i := range s { + expr := s[i].Plug(b) + result.Set(expr, i) + } + return result +} + +type saveStackElem struct { + Expr *ast.Expr + B1 *bindings + B2 *bindings +} + +func (e saveStackElem) Plug(caller *bindings) *ast.Expr { + expr := e.Expr.Copy() + switch terms := expr.Terms.(type) { + case []*ast.Term: + if expr.IsEquality() { + terms[1] = e.B1.PlugNamespaced(terms[1], caller) + terms[2] = e.B2.PlugNamespaced(terms[2], caller) + } else { + for i := 1; i < len(terms); i++ { + terms[i] = e.B1.PlugNamespaced(terms[i], caller) + } + } + case *ast.Term: + expr.Terms = e.B1.PlugNamespaced(terms, caller) + } + return expr +} + +// saveSupport contains additional partially evaluated policies that are part +// of the output of partial evaluation. +// +// The support structure is accumulated as partial evaluation runs and then +// considered complete once partial evaluation finishes (but not before). This +// differs from partially evaluated queries which are considered complete as +// soon as each one finishes. +type saveSupport struct { + modules map[string]*ast.Module +} + +func newSaveSupport() *saveSupport { + return &saveSupport{ + modules: map[string]*ast.Module{}, + } +} + +func (s *saveSupport) List() []*ast.Module { + result := []*ast.Module{} + for _, module := range s.modules { + result = append(result, module) + } + return result +} + +func (s *saveSupport) Exists(path ast.Ref) bool { + k := path[:len(path)-1].String() + module, ok := s.modules[k] + if !ok { + return false + } + name := ast.Var(path[len(path)-1].Value.(ast.String)) + for _, rule := range module.Rules { + if rule.Head.Name.Equal(name) { + return true + } + } + return false +} + +func (s *saveSupport) Insert(path ast.Ref, rule *ast.Rule) { + pkg := path[:len(path)-1] + k := pkg.String() + module, ok := s.modules[k] + if !ok { + module = &ast.Module{ + Package: &ast.Package{ + Path: pkg, + }, + } + s.modules[k] = module + } + rule.Module = module + module.Rules = append(module.Rules, rule) +} diff --git a/github.com/open-policy-agent/opa/topdown/sets.go b/github.com/open-policy-agent/opa/topdown/sets.go index 6d6c84d4..a9c5ad86 100644 --- a/github.com/open-policy-agent/opa/topdown/sets.go +++ b/github.com/open-policy-agent/opa/topdown/sets.go @@ -4,8 +4,10 @@ package topdown -import "github.com/open-policy-agent/opa/ast" -import "github.com/open-policy-agent/opa/topdown/builtins" +import ( + "github.com/open-policy-agent/opa/ast" + "github.com/open-policy-agent/opa/topdown/builtins" +) // Deprecated in v0.4.2 in favour of minus/infix "-" operation. func builtinSetDiff(a, b ast.Value) (ast.Value, error) { @@ -23,6 +25,60 @@ func builtinSetDiff(a, b ast.Value) (ast.Value, error) { return s1.Diff(s2), nil } +// builtinSetIntersection returns the intersection of the given input sets +func builtinSetIntersection(a ast.Value) (ast.Value, error) { + + inputSet, err := builtins.SetOperand(a, 1) + if err != nil { + return nil, err + } + + // empty input set + if inputSet.Len() == 0 { + return ast.NewSet(), nil + } + + var result ast.Set + + err = inputSet.Iter(func(x *ast.Term) error { + n, err := builtins.SetOperand(x.Value, 1) + if err != nil { + return err + } + + if result == nil { + result = n + } else { + result = result.Intersect(n) + } + return nil + }) + return result, err +} + +// builtinSetUnion returns the union of the given input sets +func builtinSetUnion(a ast.Value) (ast.Value, error) { + + inputSet, err := builtins.SetOperand(a, 1) + if err != nil { + return nil, err + } + + result := ast.NewSet() + + err = inputSet.Iter(func(x *ast.Term) error { + n, err := builtins.SetOperand(x.Value, 1) + if err != nil { + return err + } + result = result.Union(n) + return nil + }) + return result, err +} + func init() { RegisterFunctionalBuiltin2(ast.SetDiff.Name, builtinSetDiff) + RegisterFunctionalBuiltin1(ast.Intersection.Name, builtinSetIntersection) + RegisterFunctionalBuiltin1(ast.Union.Name, builtinSetUnion) } diff --git a/github.com/open-policy-agent/opa/topdown/strings.go b/github.com/open-policy-agent/opa/topdown/strings.go index f4a7923a..ef2902c4 100644 --- a/github.com/open-policy-agent/opa/topdown/strings.go +++ b/github.com/open-policy-agent/opa/topdown/strings.go @@ -58,26 +58,24 @@ func builtinConcat(a, b ast.Value) (ast.Value, error) { for i := range b { s, ok := b[i].Value.(ast.String) if !ok { - return nil, builtins.NewOperandElementErr(2, b, b[i].Value, ast.StringTypeName) + return nil, builtins.NewOperandElementErr(2, b, b[i].Value, "string") } strs = append(strs, string(s)) } - case *ast.Set: - var err error - stopped := b.Iter(func(x *ast.Term) bool { + case ast.Set: + err := b.Iter(func(x *ast.Term) error { s, ok := x.Value.(ast.String) if !ok { - err = builtins.NewOperandElementErr(2, b, x.Value, ast.StringTypeName) - return true + return builtins.NewOperandElementErr(2, b, x.Value, "string") } strs = append(strs, string(s)) - return false + return nil }) - if stopped { + if err != nil { return nil, err } default: - return nil, builtins.NewOperandTypeErr(2, b, ast.SetTypeName, ast.ArrayTypeName) + return nil, builtins.NewOperandTypeErr(2, b, "set", "array") } return ast.String(strings.Join(strs, string(join))), nil @@ -136,11 +134,7 @@ func builtinContains(a, b ast.Value) (ast.Value, error) { return nil, err } - if !strings.Contains(string(s), string(substr)) { - return nil, BuiltinEmpty{} - } - - return ast.Boolean(true), nil + return ast.Boolean(strings.Contains(string(s), string(substr))), nil } func builtinStartsWith(a, b ast.Value) (ast.Value, error) { @@ -154,11 +148,7 @@ func builtinStartsWith(a, b ast.Value) (ast.Value, error) { return nil, err } - if !strings.HasPrefix(string(s), string(prefix)) { - return nil, BuiltinEmpty{} - } - - return ast.Boolean(true), nil + return ast.Boolean(strings.HasPrefix(string(s), string(prefix))), nil } func builtinEndsWith(a, b ast.Value) (ast.Value, error) { @@ -172,11 +162,7 @@ func builtinEndsWith(a, b ast.Value) (ast.Value, error) { return nil, err } - if !strings.HasSuffix(string(s), string(suffix)) { - return nil, BuiltinEmpty{} - } - - return ast.Boolean(true), nil + return ast.Boolean(strings.HasSuffix(string(s), string(suffix))), nil } func builtinLower(a ast.Value) (ast.Value, error) { @@ -252,7 +238,7 @@ func builtinSprintf(a, b ast.Value) (ast.Value, error) { astArr, ok := b.(ast.Array) if !ok { - return nil, builtins.NewOperandTypeErr(2, b, ast.ArrayTypeName) + return nil, builtins.NewOperandTypeErr(2, b, "array") } strArr := []interface{}{} diff --git a/github.com/open-policy-agent/opa/topdown/time.go b/github.com/open-policy-agent/opa/topdown/time.go index 84996464..594c7de6 100644 --- a/github.com/open-policy-agent/opa/topdown/time.go +++ b/github.com/open-policy-agent/opa/topdown/time.go @@ -6,6 +6,8 @@ package topdown import ( "encoding/json" + "fmt" + "math/big" "strconv" "time" @@ -80,6 +82,44 @@ func builtinParseDurationNanos(a ast.Value) (ast.Value, error) { return ast.Number(int64ToJSONNumber(int64(value))), nil } +func builtinDate(a ast.Value) (ast.Value, error) { + + value, err := builtins.NumberOperand(a, 1) + if err != nil { + return nil, err + } + + f := builtins.NumberToFloat(value) + i64, acc := f.Int64() + if acc != big.Exact { + return nil, fmt.Errorf("timestamp too big") + } + + t := time.Unix(0, i64).UTC() + year, month, day := t.Date() + result := ast.Array{ast.IntNumberTerm(year), ast.IntNumberTerm(int(month)), ast.IntNumberTerm(day)} + return result, nil +} + +func builtinClock(a ast.Value) (ast.Value, error) { + + value, err := builtins.NumberOperand(a, 1) + if err != nil { + return nil, err + } + + f := builtins.NumberToFloat(value) + i64, acc := f.Int64() + if acc != big.Exact { + return nil, fmt.Errorf("timestamp too big") + } + + t := time.Unix(0, i64).UTC() + hour, minute, second := t.Clock() + result := ast.Array{ast.IntNumberTerm(hour), ast.IntNumberTerm(minute), ast.IntNumberTerm(second)} + return result, nil +} + func int64ToJSONNumber(i int64) json.Number { return json.Number(strconv.FormatInt(i, 10)) } @@ -89,4 +129,6 @@ func init() { RegisterFunctionalBuiltin1(ast.ParseRFC3339Nanos.Name, builtinTimeParseRFC3339Nanos) RegisterFunctionalBuiltin2(ast.ParseNanos.Name, builtinTimeParseNanos) RegisterFunctionalBuiltin1(ast.ParseDurationNanos.Name, builtinParseDurationNanos) + RegisterFunctionalBuiltin1(ast.Date.Name, builtinDate) + RegisterFunctionalBuiltin1(ast.Clock.Name, builtinClock) } diff --git a/github.com/open-policy-agent/opa/topdown/trace.go b/github.com/open-policy-agent/opa/topdown/trace.go index ef11baac..0f368a8d 100644 --- a/github.com/open-policy-agent/opa/topdown/trace.go +++ b/github.com/open-policy-agent/opa/topdown/trace.go @@ -28,6 +28,10 @@ const ( // RedoOp is emitted when an expression, rule, or query is being re-evaluated. RedoOp Op = "Redo" + // SaveOp is emitted when an expression is saved instead of evaluated + // during partial evaluation. + SaveOp Op = "Save" + // FailOp is emitted when an expression evaluates to false. FailOp Op = "Fail" ) diff --git a/github.com/open-policy-agent/opa/topdown/type.go b/github.com/open-policy-agent/opa/topdown/type.go new file mode 100644 index 00000000..a4c31fc8 --- /dev/null +++ b/github.com/open-policy-agent/opa/topdown/type.go @@ -0,0 +1,82 @@ +// Copyright 2018 The OPA Authors. All rights reserved. +// Use of this source code is governed by an Apache2 +// license that can be found in the LICENSE file. + +package topdown + +import ( + "github.com/open-policy-agent/opa/ast" +) + +func builtinIsNumber(a ast.Value) (ast.Value, error) { + switch a.(type) { + case ast.Number: + return ast.Boolean(true), nil + default: + return nil, BuiltinEmpty{} + } +} + +func builtinIsString(a ast.Value) (ast.Value, error) { + switch a.(type) { + case ast.String: + return ast.Boolean(true), nil + default: + return nil, BuiltinEmpty{} + } +} + +func builtinIsBoolean(a ast.Value) (ast.Value, error) { + switch a.(type) { + case ast.Boolean: + return ast.Boolean(true), nil + default: + return nil, BuiltinEmpty{} + } +} + +func builtinIsArray(a ast.Value) (ast.Value, error) { + switch a.(type) { + case ast.Array: + return ast.Boolean(true), nil + default: + return nil, BuiltinEmpty{} + } +} + +func builtinIsSet(a ast.Value) (ast.Value, error) { + switch a.(type) { + case ast.Set: + return ast.Boolean(true), nil + default: + return nil, BuiltinEmpty{} + } +} + +func builtinIsObject(a ast.Value) (ast.Value, error) { + switch a.(type) { + case ast.Object: + return ast.Boolean(true), nil + default: + return nil, BuiltinEmpty{} + } +} + +func builtinIsNull(a ast.Value) (ast.Value, error) { + switch a.(type) { + case ast.Null: + return ast.Boolean(true), nil + default: + return nil, BuiltinEmpty{} + } +} + +func init() { + RegisterFunctionalBuiltin1(ast.IsNumber.Name, builtinIsNumber) + RegisterFunctionalBuiltin1(ast.IsString.Name, builtinIsString) + RegisterFunctionalBuiltin1(ast.IsBoolean.Name, builtinIsBoolean) + RegisterFunctionalBuiltin1(ast.IsArray.Name, builtinIsArray) + RegisterFunctionalBuiltin1(ast.IsSet.Name, builtinIsSet) + RegisterFunctionalBuiltin1(ast.IsObject.Name, builtinIsObject) + RegisterFunctionalBuiltin1(ast.IsNull.Name, builtinIsNull) +} diff --git a/github.com/open-policy-agent/opa/topdown/type_name.go b/github.com/open-policy-agent/opa/topdown/type_name.go new file mode 100644 index 00000000..5a77f5d3 --- /dev/null +++ b/github.com/open-policy-agent/opa/topdown/type_name.go @@ -0,0 +1,36 @@ +// Copyright 2018 The OPA Authors. All rights reserved. +// Use of this source code is governed by an Apache2 +// license that can be found in the LICENSE file. + +package topdown + +import ( + "fmt" + + "github.com/open-policy-agent/opa/ast" +) + +func builtinTypeName(a ast.Value) (ast.Value, error) { + switch a.(type) { + case ast.Null: + return ast.String("null"), nil + case ast.Boolean: + return ast.String("boolean"), nil + case ast.Number: + return ast.String("number"), nil + case ast.String: + return ast.String("string"), nil + case ast.Array: + return ast.String("array"), nil + case ast.Object: + return ast.String("object"), nil + case ast.Set: + return ast.String("set"), nil + } + + return nil, fmt.Errorf("illegal value") +} + +func init() { + RegisterFunctionalBuiltin1(ast.TypeNameBuiltin.Name, builtinTypeName) +} diff --git a/github.com/open-policy-agent/opa/topdown/walk.go b/github.com/open-policy-agent/opa/topdown/walk.go index a863c7b1..e40de8a1 100644 --- a/github.com/open-policy-agent/opa/topdown/walk.go +++ b/github.com/open-policy-agent/opa/topdown/walk.go @@ -4,58 +4,81 @@ package topdown -import "github.com/open-policy-agent/opa/ast" +import ( + "github.com/open-policy-agent/opa/ast" +) func evalWalk(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error { input := args[0] + filter := getOutputPath(args) var path ast.Array - return walk(input, path, iter) + return walk(filter, path, input, iter) } -func walk(input *ast.Term, path ast.Array, iter func(*ast.Term) error) error { +func walk(filter, path ast.Array, input *ast.Term, iter func(*ast.Term) error) error { - output := ast.ArrayTerm(ast.NewTerm(path), input) + if len(filter) == 0 { + if err := iter(ast.ArrayTerm(ast.NewTerm(path), input)); err != nil { + return err + } + } - if err := iter(output); err != nil { - return err + if len(filter) > 0 { + key := filter[0] + filter = filter[1:] + if key.IsGround() { + if term := input.Get(key); term != nil { + return walk(filter, append(path, key), term, iter) + } + return nil + } } switch v := input.Value.(type) { case ast.Array: for i := range v { path = append(path, ast.IntNumberTerm(i)) - if err := walk(v[i], path, iter); err != nil { + if err := walk(filter, path, v[i], iter); err != nil { return err } path = path[:len(path)-1] } case ast.Object: - for _, pair := range v { - path = append(path, pair[0]) - if err := walk(pair[1], path, iter); err != nil { + return v.Iter(func(k, v *ast.Term) error { + path = append(path, k) + if err := walk(filter, path, v, iter); err != nil { return err } path = path[:len(path)-1] - } - case *ast.Set: - var err error - v.Iter(func(elem *ast.Term) bool { - if err != nil { - return true - } + return nil + }) + case ast.Set: + return v.Iter(func(elem *ast.Term) error { path = append(path, elem) - if err = walk(elem, path, iter); err != nil { - return true + if err := walk(filter, path, elem, iter); err != nil { + return err } path = path[:len(path)-1] - return false + return nil }) - return err } return nil } +func getOutputPath(args []*ast.Term) ast.Array { + if len(args) == 2 { + if arr, ok := args[1].Value.(ast.Array); ok { + if len(arr) == 2 { + if path, ok := arr[0].Value.(ast.Array); ok { + return path + } + } + } + } + return nil +} + func init() { RegisterBuiltinFunc(ast.WalkBuiltin.Name, evalWalk) } diff --git a/github.com/open-policy-agent/opa/types/types.go b/github.com/open-policy-agent/opa/types/types.go index 0429f4cb..1847fedd 100644 --- a/github.com/open-policy-agent/opa/types/types.go +++ b/github.com/open-policy-agent/opa/types/types.go @@ -60,22 +60,11 @@ func (t Null) String() string { } // Boolean represents the boolean type. -type Boolean struct { - v *bool -} +type Boolean struct{} // B represents an instance of the boolean type. var B = NewBoolean() -var t = true -var f = false - -// T represents an instance of the value true. -var T = Boolean{v: &t} - -// F represents an instance of the value false. -var F = Boolean{v: &f} - // NewBoolean returns a new Boolean type. func NewBoolean() Boolean { return Boolean{} @@ -86,20 +75,11 @@ func (t Boolean) MarshalJSON() ([]byte, error) { repr := map[string]interface{}{ "type": t.typeMarker(), } - if t.v != nil { - repr["value"] = *t.v - } return json.Marshal(repr) } func (t Boolean) String() string { - if t.v == nil { - return "boolean" - } else if *t.v { - return "true" - } else { - return "false" - } + return t.typeMarker() } // String represents the string type. @@ -537,26 +517,7 @@ func Compare(a, b Type) int { return -1 } switch a.(type) { - case nil: - return 0 - case Boolean: - bA := a.(Boolean) - bB := b.(Boolean) - if bA.v == nil && bB.v == nil { - return 0 - } else if bA.v != nil && bB.v != nil { - if *bA.v == *bB.v { - return 0 - } else if *bA.v { - return 1 - } else { - return -1 - } - } else if bA.v != nil { - return 1 - } - return -1 - case Null, Number, String: + case nil, Null, Boolean, Number, String: return 0 case *Array: arrA := a.(*Array) diff --git a/github.com/pquerna/cachecontrol/cacheobject/directive.go b/github.com/pquerna/cachecontrol/cacheobject/directive.go index 1e2a6c2e..afa640e7 100644 --- a/github.com/pquerna/cachecontrol/cacheobject/directive.go +++ b/github.com/pquerna/cachecontrol/cacheobject/directive.go @@ -41,6 +41,10 @@ var ( ErrMustRevalidateNoArgs = errors.New("Unexpected argument to `must-revalidate`") ErrPublicNoArgs = errors.New("Unexpected argument to `public`") ErrProxyRevalidateNoArgs = errors.New("Unexpected argument to `proxy-revalidate`") + // Experimental + ErrImmutableNoArgs = errors.New("Unexpected argument to `immutable`") + ErrStaleIfErrorDeltaSeconds = errors.New("Failed to parse delta-seconds in `stale-if-error`") + ErrStaleWhileRevalidateDeltaSeconds = errors.New("Failed to parse delta-seconds in `stale-while-revalidate`") ) func whitespace(b byte) bool { @@ -403,6 +407,21 @@ type ResponseCacheDirectives struct { // proxy-revalidate response directive. SMaxAge DeltaSeconds + //// + // Experimental features + // - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Extension_Cache-Control_directives + // - https://www.fastly.com/blog/stale-while-revalidate-stale-if-error-available-today + //// + + // immutable(cast-to-bool): experimental feature + Immutable bool + + // stale-if-error(delta seconds): experimental feature + StaleIfError DeltaSeconds + + // stale-while-revalidate(delta seconds): experimental feature + StaleWhileRevalidate DeltaSeconds + // Extensions: http://tools.ietf.org/html/rfc7234#section-5.2.3 // // The Cache-Control header field can be extended through the use of one @@ -416,6 +435,9 @@ func ParseResponseCacheControl(value string) (*ResponseCacheDirectives, error) { cd := &ResponseCacheDirectives{ MaxAge: -1, SMaxAge: -1, + // Exerimantal stale timeouts + StaleIfError: -1, + StaleWhileRevalidate: -1, } err := parse(value, cd) @@ -446,6 +468,13 @@ func (cd *ResponseCacheDirectives) addToken(token string) error { err = ErrMaxAgeDeltaSeconds case "s-maxage": err = ErrSMaxAgeDeltaSeconds + // Experimental + case "immutable": + cd.Immutable = true + case "stale-if-error": + err = ErrMaxAgeDeltaSeconds + case "stale-while-revalidate": + err = ErrMaxAgeDeltaSeconds default: cd.Extensions = append(cd.Extensions, token) } @@ -500,6 +529,13 @@ func (cd *ResponseCacheDirectives) addPair(token string, v string) error { cd.MaxAge, err = parseDeltaSeconds(v) case "s-maxage": cd.SMaxAge, err = parseDeltaSeconds(v) + // Experimental + case "immutable": + err = ErrImmutableNoArgs + case "stale-if-error": + cd.StaleIfError, err = parseDeltaSeconds(v) + case "stale-while-revalidate": + cd.StaleWhileRevalidate, err = parseDeltaSeconds(v) default: // TODO(pquerna): this sucks, making user re-parse, and its technically not 'quoted' like the original, // but this is still easier, just a SplitN on "=" diff --git a/github.com/prometheus/procfs/nfs/nfs.go b/github.com/prometheus/procfs/nfs/nfs.go index e2185b78..651bf681 100644 --- a/github.com/prometheus/procfs/nfs/nfs.go +++ b/github.com/prometheus/procfs/nfs/nfs.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package nfsd implements parsing of /proc/net/rpc/nfsd. +// Package nfs implements parsing of /proc/net/rpc/nfsd. // Fields are documented in https://www.svennd.be/nfsd-stats-explained-procnetrpcnfsd/ package nfs @@ -136,8 +136,8 @@ type ClientV4Stats struct { Setattr uint64 FsInfo uint64 Renew uint64 - SetClientId uint64 - SetClientIdConfirm uint64 + SetClientID uint64 + SetClientIDConfirm uint64 Lock uint64 Lockt uint64 Locku uint64 @@ -156,13 +156,13 @@ type ClientV4Stats struct { ReadDir uint64 ServerCaps uint64 DelegReturn uint64 - GetAcl uint64 - SetAcl uint64 + GetACL uint64 + SetACL uint64 FsLocations uint64 ReleaseLockowner uint64 Secinfo uint64 FsidPresent uint64 - ExchangeId uint64 + ExchangeID uint64 CreateSession uint64 DestroySession uint64 Sequence uint64 @@ -173,11 +173,11 @@ type ClientV4Stats struct { LayoutCommit uint64 LayoutReturn uint64 SecinfoNoName uint64 - TestStateId uint64 - FreeStateId uint64 + TestStateID uint64 + FreeStateID uint64 GetDeviceList uint64 BindConnToSession uint64 - DestroyClientId uint64 + DestroyClientID uint64 Seek uint64 Allocate uint64 DeAllocate uint64 @@ -238,7 +238,7 @@ type V4Ops struct { RelLockOwner uint64 } -// RPCStats models all stats from /proc/net/rpc/nfs. +// ClientRPCStats models all stats from /proc/net/rpc/nfs. type ClientRPCStats struct { Network Network ClientRPC ClientRPC diff --git a/github.com/prometheus/procfs/nfs/parse.go b/github.com/prometheus/procfs/nfs/parse.go index 8f568f01..95a83cc5 100644 --- a/github.com/prometheus/procfs/nfs/parse.go +++ b/github.com/prometheus/procfs/nfs/parse.go @@ -204,8 +204,8 @@ func parseClientV4Stats(v []uint64) (ClientV4Stats, error) { Setattr: v[10], FsInfo: v[11], Renew: v[12], - SetClientId: v[13], - SetClientIdConfirm: v[14], + SetClientID: v[13], + SetClientIDConfirm: v[14], Lock: v[15], Lockt: v[16], Locku: v[17], @@ -224,13 +224,13 @@ func parseClientV4Stats(v []uint64) (ClientV4Stats, error) { ReadDir: v[30], ServerCaps: v[31], DelegReturn: v[32], - GetAcl: v[33], - SetAcl: v[34], + GetACL: v[33], + SetACL: v[34], FsLocations: v[35], ReleaseLockowner: v[36], Secinfo: v[37], FsidPresent: v[38], - ExchangeId: v[39], + ExchangeID: v[39], CreateSession: v[40], DestroySession: v[41], Sequence: v[42], @@ -241,11 +241,11 @@ func parseClientV4Stats(v []uint64) (ClientV4Stats, error) { LayoutCommit: v[47], LayoutReturn: v[48], SecinfoNoName: v[49], - TestStateId: v[50], - FreeStateId: v[51], + TestStateID: v[50], + FreeStateID: v[51], GetDeviceList: v[52], BindConnToSession: v[53], - DestroyClientId: v[54], + DestroyClientID: v[54], Seek: v[55], Allocate: v[56], DeAllocate: v[57], diff --git a/github.com/rcrowley/go-metrics/LICENSE b/github.com/rcrowley/go-metrics/LICENSE new file mode 100644 index 00000000..363fa9ee --- /dev/null +++ b/github.com/rcrowley/go-metrics/LICENSE @@ -0,0 +1,29 @@ +Copyright 2012 Richard Crowley. 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 RICHARD CROWLEY ``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 RICHARD CROWLEY 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. + +The views and conclusions contained in the software and documentation +are those of the authors and should not be interpreted as representing +official policies, either expressed or implied, of Richard Crowley. diff --git a/github.com/rcrowley/go-metrics/counter.go b/github.com/rcrowley/go-metrics/counter.go new file mode 100644 index 00000000..bb7b039c --- /dev/null +++ b/github.com/rcrowley/go-metrics/counter.go @@ -0,0 +1,112 @@ +package metrics + +import "sync/atomic" + +// Counters hold an int64 value that can be incremented and decremented. +type Counter interface { + Clear() + Count() int64 + Dec(int64) + Inc(int64) + Snapshot() Counter +} + +// GetOrRegisterCounter returns an existing Counter or constructs and registers +// a new StandardCounter. +func GetOrRegisterCounter(name string, r Registry) Counter { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewCounter).(Counter) +} + +// NewCounter constructs a new StandardCounter. +func NewCounter() Counter { + if UseNilMetrics { + return NilCounter{} + } + return &StandardCounter{0} +} + +// NewRegisteredCounter constructs and registers a new StandardCounter. +func NewRegisteredCounter(name string, r Registry) Counter { + c := NewCounter() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// CounterSnapshot is a read-only copy of another Counter. +type CounterSnapshot int64 + +// Clear panics. +func (CounterSnapshot) Clear() { + panic("Clear called on a CounterSnapshot") +} + +// Count returns the count at the time the snapshot was taken. +func (c CounterSnapshot) Count() int64 { return int64(c) } + +// Dec panics. +func (CounterSnapshot) Dec(int64) { + panic("Dec called on a CounterSnapshot") +} + +// Inc panics. +func (CounterSnapshot) Inc(int64) { + panic("Inc called on a CounterSnapshot") +} + +// Snapshot returns the snapshot. +func (c CounterSnapshot) Snapshot() Counter { return c } + +// NilCounter is a no-op Counter. +type NilCounter struct{} + +// Clear is a no-op. +func (NilCounter) Clear() {} + +// Count is a no-op. +func (NilCounter) Count() int64 { return 0 } + +// Dec is a no-op. +func (NilCounter) Dec(i int64) {} + +// Inc is a no-op. +func (NilCounter) Inc(i int64) {} + +// Snapshot is a no-op. +func (NilCounter) Snapshot() Counter { return NilCounter{} } + +// StandardCounter is the standard implementation of a Counter and uses the +// sync/atomic package to manage a single int64 value. +type StandardCounter struct { + count int64 +} + +// Clear sets the counter to zero. +func (c *StandardCounter) Clear() { + atomic.StoreInt64(&c.count, 0) +} + +// Count returns the current count. +func (c *StandardCounter) Count() int64 { + return atomic.LoadInt64(&c.count) +} + +// Dec decrements the counter by the given amount. +func (c *StandardCounter) Dec(i int64) { + atomic.AddInt64(&c.count, -i) +} + +// Inc increments the counter by the given amount. +func (c *StandardCounter) Inc(i int64) { + atomic.AddInt64(&c.count, i) +} + +// Snapshot returns a read-only copy of the counter. +func (c *StandardCounter) Snapshot() Counter { + return CounterSnapshot(c.Count()) +} diff --git a/github.com/rcrowley/go-metrics/debug.go b/github.com/rcrowley/go-metrics/debug.go new file mode 100644 index 00000000..043ccefa --- /dev/null +++ b/github.com/rcrowley/go-metrics/debug.go @@ -0,0 +1,76 @@ +package metrics + +import ( + "runtime/debug" + "time" +) + +var ( + debugMetrics struct { + GCStats struct { + LastGC Gauge + NumGC Gauge + Pause Histogram + //PauseQuantiles Histogram + PauseTotal Gauge + } + ReadGCStats Timer + } + gcStats debug.GCStats +) + +// Capture new values for the Go garbage collector statistics exported in +// debug.GCStats. This is designed to be called as a goroutine. +func CaptureDebugGCStats(r Registry, d time.Duration) { + for _ = range time.Tick(d) { + CaptureDebugGCStatsOnce(r) + } +} + +// Capture new values for the Go garbage collector statistics exported in +// debug.GCStats. This is designed to be called in a background goroutine. +// Giving a registry which has not been given to RegisterDebugGCStats will +// panic. +// +// Be careful (but much less so) with this because debug.ReadGCStats calls +// the C function runtime·lock(runtime·mheap) which, while not a stop-the-world +// operation, isn't something you want to be doing all the time. +func CaptureDebugGCStatsOnce(r Registry) { + lastGC := gcStats.LastGC + t := time.Now() + debug.ReadGCStats(&gcStats) + debugMetrics.ReadGCStats.UpdateSince(t) + + debugMetrics.GCStats.LastGC.Update(int64(gcStats.LastGC.UnixNano())) + debugMetrics.GCStats.NumGC.Update(int64(gcStats.NumGC)) + if lastGC != gcStats.LastGC && 0 < len(gcStats.Pause) { + debugMetrics.GCStats.Pause.Update(int64(gcStats.Pause[0])) + } + //debugMetrics.GCStats.PauseQuantiles.Update(gcStats.PauseQuantiles) + debugMetrics.GCStats.PauseTotal.Update(int64(gcStats.PauseTotal)) +} + +// Register metrics for the Go garbage collector statistics exported in +// debug.GCStats. The metrics are named by their fully-qualified Go symbols, +// i.e. debug.GCStats.PauseTotal. +func RegisterDebugGCStats(r Registry) { + debugMetrics.GCStats.LastGC = NewGauge() + debugMetrics.GCStats.NumGC = NewGauge() + debugMetrics.GCStats.Pause = NewHistogram(NewExpDecaySample(1028, 0.015)) + //debugMetrics.GCStats.PauseQuantiles = NewHistogram(NewExpDecaySample(1028, 0.015)) + debugMetrics.GCStats.PauseTotal = NewGauge() + debugMetrics.ReadGCStats = NewTimer() + + r.Register("debug.GCStats.LastGC", debugMetrics.GCStats.LastGC) + r.Register("debug.GCStats.NumGC", debugMetrics.GCStats.NumGC) + r.Register("debug.GCStats.Pause", debugMetrics.GCStats.Pause) + //r.Register("debug.GCStats.PauseQuantiles", debugMetrics.GCStats.PauseQuantiles) + r.Register("debug.GCStats.PauseTotal", debugMetrics.GCStats.PauseTotal) + r.Register("debug.ReadGCStats", debugMetrics.ReadGCStats) +} + +// Allocate an initial slice for gcStats.Pause to avoid allocations during +// normal operation. +func init() { + gcStats.Pause = make([]time.Duration, 11) +} diff --git a/github.com/rcrowley/go-metrics/ewma.go b/github.com/rcrowley/go-metrics/ewma.go new file mode 100644 index 00000000..694a1d03 --- /dev/null +++ b/github.com/rcrowley/go-metrics/ewma.go @@ -0,0 +1,118 @@ +package metrics + +import ( + "math" + "sync" + "sync/atomic" +) + +// EWMAs continuously calculate an exponentially-weighted moving average +// based on an outside source of clock ticks. +type EWMA interface { + Rate() float64 + Snapshot() EWMA + Tick() + Update(int64) +} + +// NewEWMA constructs a new EWMA with the given alpha. +func NewEWMA(alpha float64) EWMA { + if UseNilMetrics { + return NilEWMA{} + } + return &StandardEWMA{alpha: alpha} +} + +// NewEWMA1 constructs a new EWMA for a one-minute moving average. +func NewEWMA1() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/1)) +} + +// NewEWMA5 constructs a new EWMA for a five-minute moving average. +func NewEWMA5() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/5)) +} + +// NewEWMA15 constructs a new EWMA for a fifteen-minute moving average. +func NewEWMA15() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/15)) +} + +// EWMASnapshot is a read-only copy of another EWMA. +type EWMASnapshot float64 + +// Rate returns the rate of events per second at the time the snapshot was +// taken. +func (a EWMASnapshot) Rate() float64 { return float64(a) } + +// Snapshot returns the snapshot. +func (a EWMASnapshot) Snapshot() EWMA { return a } + +// Tick panics. +func (EWMASnapshot) Tick() { + panic("Tick called on an EWMASnapshot") +} + +// Update panics. +func (EWMASnapshot) Update(int64) { + panic("Update called on an EWMASnapshot") +} + +// NilEWMA is a no-op EWMA. +type NilEWMA struct{} + +// Rate is a no-op. +func (NilEWMA) Rate() float64 { return 0.0 } + +// Snapshot is a no-op. +func (NilEWMA) Snapshot() EWMA { return NilEWMA{} } + +// Tick is a no-op. +func (NilEWMA) Tick() {} + +// Update is a no-op. +func (NilEWMA) Update(n int64) {} + +// StandardEWMA is the standard implementation of an EWMA and tracks the number +// of uncounted events and processes them on each tick. It uses the +// sync/atomic package to manage uncounted events. +type StandardEWMA struct { + uncounted int64 // /!\ this should be the first member to ensure 64-bit alignment + alpha float64 + rate float64 + init bool + mutex sync.Mutex +} + +// Rate returns the moving average rate of events per second. +func (a *StandardEWMA) Rate() float64 { + a.mutex.Lock() + defer a.mutex.Unlock() + return a.rate * float64(1e9) +} + +// Snapshot returns a read-only copy of the EWMA. +func (a *StandardEWMA) Snapshot() EWMA { + return EWMASnapshot(a.Rate()) +} + +// Tick ticks the clock to update the moving average. It assumes it is called +// every five seconds. +func (a *StandardEWMA) Tick() { + count := atomic.LoadInt64(&a.uncounted) + atomic.AddInt64(&a.uncounted, -count) + instantRate := float64(count) / float64(5e9) + a.mutex.Lock() + defer a.mutex.Unlock() + if a.init { + a.rate += a.alpha * (instantRate - a.rate) + } else { + a.init = true + a.rate = instantRate + } +} + +// Update adds n uncounted events. +func (a *StandardEWMA) Update(n int64) { + atomic.AddInt64(&a.uncounted, n) +} diff --git a/github.com/rcrowley/go-metrics/gauge.go b/github.com/rcrowley/go-metrics/gauge.go new file mode 100644 index 00000000..cb57a938 --- /dev/null +++ b/github.com/rcrowley/go-metrics/gauge.go @@ -0,0 +1,120 @@ +package metrics + +import "sync/atomic" + +// Gauges hold an int64 value that can be set arbitrarily. +type Gauge interface { + Snapshot() Gauge + Update(int64) + Value() int64 +} + +// GetOrRegisterGauge returns an existing Gauge or constructs and registers a +// new StandardGauge. +func GetOrRegisterGauge(name string, r Registry) Gauge { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewGauge).(Gauge) +} + +// NewGauge constructs a new StandardGauge. +func NewGauge() Gauge { + if UseNilMetrics { + return NilGauge{} + } + return &StandardGauge{0} +} + +// NewRegisteredGauge constructs and registers a new StandardGauge. +func NewRegisteredGauge(name string, r Registry) Gauge { + c := NewGauge() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// NewFunctionalGauge constructs a new FunctionalGauge. +func NewFunctionalGauge(f func() int64) Gauge { + if UseNilMetrics { + return NilGauge{} + } + return &FunctionalGauge{value: f} +} + +// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. +func NewRegisteredFunctionalGauge(name string, r Registry, f func() int64) Gauge { + c := NewFunctionalGauge(f) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// GaugeSnapshot is a read-only copy of another Gauge. +type GaugeSnapshot int64 + +// Snapshot returns the snapshot. +func (g GaugeSnapshot) Snapshot() Gauge { return g } + +// Update panics. +func (GaugeSnapshot) Update(int64) { + panic("Update called on a GaugeSnapshot") +} + +// Value returns the value at the time the snapshot was taken. +func (g GaugeSnapshot) Value() int64 { return int64(g) } + +// NilGauge is a no-op Gauge. +type NilGauge struct{} + +// Snapshot is a no-op. +func (NilGauge) Snapshot() Gauge { return NilGauge{} } + +// Update is a no-op. +func (NilGauge) Update(v int64) {} + +// Value is a no-op. +func (NilGauge) Value() int64 { return 0 } + +// StandardGauge is the standard implementation of a Gauge and uses the +// sync/atomic package to manage a single int64 value. +type StandardGauge struct { + value int64 +} + +// Snapshot returns a read-only copy of the gauge. +func (g *StandardGauge) Snapshot() Gauge { + return GaugeSnapshot(g.Value()) +} + +// Update updates the gauge's value. +func (g *StandardGauge) Update(v int64) { + atomic.StoreInt64(&g.value, v) +} + +// Value returns the gauge's current value. +func (g *StandardGauge) Value() int64 { + return atomic.LoadInt64(&g.value) +} + +// FunctionalGauge returns value from given function +type FunctionalGauge struct { + value func() int64 +} + +// Value returns the gauge's current value. +func (g FunctionalGauge) Value() int64 { + return g.value() +} + +// Snapshot returns the snapshot. +func (g FunctionalGauge) Snapshot() Gauge { return GaugeSnapshot(g.Value()) } + +// Update panics. +func (FunctionalGauge) Update(int64) { + panic("Update called on a FunctionalGauge") +} diff --git a/github.com/rcrowley/go-metrics/gauge_float64.go b/github.com/rcrowley/go-metrics/gauge_float64.go new file mode 100644 index 00000000..6f93920b --- /dev/null +++ b/github.com/rcrowley/go-metrics/gauge_float64.go @@ -0,0 +1,127 @@ +package metrics + +import "sync" + +// GaugeFloat64s hold a float64 value that can be set arbitrarily. +type GaugeFloat64 interface { + Snapshot() GaugeFloat64 + Update(float64) + Value() float64 +} + +// GetOrRegisterGaugeFloat64 returns an existing GaugeFloat64 or constructs and registers a +// new StandardGaugeFloat64. +func GetOrRegisterGaugeFloat64(name string, r Registry) GaugeFloat64 { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewGaugeFloat64()).(GaugeFloat64) +} + +// NewGaugeFloat64 constructs a new StandardGaugeFloat64. +func NewGaugeFloat64() GaugeFloat64 { + if UseNilMetrics { + return NilGaugeFloat64{} + } + return &StandardGaugeFloat64{ + value: 0.0, + } +} + +// NewRegisteredGaugeFloat64 constructs and registers a new StandardGaugeFloat64. +func NewRegisteredGaugeFloat64(name string, r Registry) GaugeFloat64 { + c := NewGaugeFloat64() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// NewFunctionalGauge constructs a new FunctionalGauge. +func NewFunctionalGaugeFloat64(f func() float64) GaugeFloat64 { + if UseNilMetrics { + return NilGaugeFloat64{} + } + return &FunctionalGaugeFloat64{value: f} +} + +// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. +func NewRegisteredFunctionalGaugeFloat64(name string, r Registry, f func() float64) GaugeFloat64 { + c := NewFunctionalGaugeFloat64(f) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// GaugeFloat64Snapshot is a read-only copy of another GaugeFloat64. +type GaugeFloat64Snapshot float64 + +// Snapshot returns the snapshot. +func (g GaugeFloat64Snapshot) Snapshot() GaugeFloat64 { return g } + +// Update panics. +func (GaugeFloat64Snapshot) Update(float64) { + panic("Update called on a GaugeFloat64Snapshot") +} + +// Value returns the value at the time the snapshot was taken. +func (g GaugeFloat64Snapshot) Value() float64 { return float64(g) } + +// NilGauge is a no-op Gauge. +type NilGaugeFloat64 struct{} + +// Snapshot is a no-op. +func (NilGaugeFloat64) Snapshot() GaugeFloat64 { return NilGaugeFloat64{} } + +// Update is a no-op. +func (NilGaugeFloat64) Update(v float64) {} + +// Value is a no-op. +func (NilGaugeFloat64) Value() float64 { return 0.0 } + +// StandardGaugeFloat64 is the standard implementation of a GaugeFloat64 and uses +// sync.Mutex to manage a single float64 value. +type StandardGaugeFloat64 struct { + mutex sync.Mutex + value float64 +} + +// Snapshot returns a read-only copy of the gauge. +func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64 { + return GaugeFloat64Snapshot(g.Value()) +} + +// Update updates the gauge's value. +func (g *StandardGaugeFloat64) Update(v float64) { + g.mutex.Lock() + defer g.mutex.Unlock() + g.value = v +} + +// Value returns the gauge's current value. +func (g *StandardGaugeFloat64) Value() float64 { + g.mutex.Lock() + defer g.mutex.Unlock() + return g.value +} + +// FunctionalGaugeFloat64 returns value from given function +type FunctionalGaugeFloat64 struct { + value func() float64 +} + +// Value returns the gauge's current value. +func (g FunctionalGaugeFloat64) Value() float64 { + return g.value() +} + +// Snapshot returns the snapshot. +func (g FunctionalGaugeFloat64) Snapshot() GaugeFloat64 { return GaugeFloat64Snapshot(g.Value()) } + +// Update panics. +func (FunctionalGaugeFloat64) Update(float64) { + panic("Update called on a FunctionalGaugeFloat64") +} diff --git a/github.com/rcrowley/go-metrics/graphite.go b/github.com/rcrowley/go-metrics/graphite.go new file mode 100644 index 00000000..abd0a7d2 --- /dev/null +++ b/github.com/rcrowley/go-metrics/graphite.go @@ -0,0 +1,113 @@ +package metrics + +import ( + "bufio" + "fmt" + "log" + "net" + "strconv" + "strings" + "time" +) + +// GraphiteConfig provides a container with configuration parameters for +// the Graphite exporter +type GraphiteConfig struct { + Addr *net.TCPAddr // Network address to connect to + Registry Registry // Registry to be exported + FlushInterval time.Duration // Flush interval + DurationUnit time.Duration // Time conversion unit for durations + Prefix string // Prefix to be prepended to metric names + Percentiles []float64 // Percentiles to export from timers and histograms +} + +// Graphite is a blocking exporter function which reports metrics in r +// to a graphite server located at addr, flushing them every d duration +// and prepending metric names with prefix. +func Graphite(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) { + GraphiteWithConfig(GraphiteConfig{ + Addr: addr, + Registry: r, + FlushInterval: d, + DurationUnit: time.Nanosecond, + Prefix: prefix, + Percentiles: []float64{0.5, 0.75, 0.95, 0.99, 0.999}, + }) +} + +// GraphiteWithConfig is a blocking exporter function just like Graphite, +// but it takes a GraphiteConfig instead. +func GraphiteWithConfig(c GraphiteConfig) { + log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015") + for _ = range time.Tick(c.FlushInterval) { + if err := graphite(&c); nil != err { + log.Println(err) + } + } +} + +// GraphiteOnce performs a single submission to Graphite, returning a +// non-nil error on failed connections. This can be used in a loop +// similar to GraphiteWithConfig for custom error handling. +func GraphiteOnce(c GraphiteConfig) error { + log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015") + return graphite(&c) +} + +func graphite(c *GraphiteConfig) error { + now := time.Now().Unix() + du := float64(c.DurationUnit) + conn, err := net.DialTCP("tcp", nil, c.Addr) + if nil != err { + return err + } + defer conn.Close() + w := bufio.NewWriter(conn) + c.Registry.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Count(), now) + case Gauge: + fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now) + case GaugeFloat64: + fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles(c.Percentiles) + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, h.Count(), now) + fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, h.Min(), now) + fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, h.Max(), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, h.Mean(), now) + fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, h.StdDev(), now) + for psIdx, psKey := range c.Percentiles { + key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) + fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) + } + case Meter: + m := metric.Snapshot() + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, m.Count(), now) + fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, m.Rate1(), now) + fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, m.Rate5(), now) + fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, m.Rate15(), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, m.RateMean(), now) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles(c.Percentiles) + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, t.Count(), now) + fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, t.Min()/int64(du), now) + fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, t.Max()/int64(du), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, t.Mean()/du, now) + fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, t.StdDev()/du, now) + for psIdx, psKey := range c.Percentiles { + key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) + fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) + } + fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, t.Rate1(), now) + fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, t.Rate5(), now) + fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, t.Rate15(), now) + fmt.Fprintf(w, "%s.%s.mean-rate %.2f %d\n", c.Prefix, name, t.RateMean(), now) + } + w.Flush() + }) + return nil +} diff --git a/github.com/rcrowley/go-metrics/healthcheck.go b/github.com/rcrowley/go-metrics/healthcheck.go new file mode 100644 index 00000000..445131ca --- /dev/null +++ b/github.com/rcrowley/go-metrics/healthcheck.go @@ -0,0 +1,61 @@ +package metrics + +// Healthchecks hold an error value describing an arbitrary up/down status. +type Healthcheck interface { + Check() + Error() error + Healthy() + Unhealthy(error) +} + +// NewHealthcheck constructs a new Healthcheck which will use the given +// function to update its status. +func NewHealthcheck(f func(Healthcheck)) Healthcheck { + if UseNilMetrics { + return NilHealthcheck{} + } + return &StandardHealthcheck{nil, f} +} + +// NilHealthcheck is a no-op. +type NilHealthcheck struct{} + +// Check is a no-op. +func (NilHealthcheck) Check() {} + +// Error is a no-op. +func (NilHealthcheck) Error() error { return nil } + +// Healthy is a no-op. +func (NilHealthcheck) Healthy() {} + +// Unhealthy is a no-op. +func (NilHealthcheck) Unhealthy(error) {} + +// StandardHealthcheck is the standard implementation of a Healthcheck and +// stores the status and a function to call to update the status. +type StandardHealthcheck struct { + err error + f func(Healthcheck) +} + +// Check runs the healthcheck function to update the healthcheck's status. +func (h *StandardHealthcheck) Check() { + h.f(h) +} + +// Error returns the healthcheck's status, which will be nil if it is healthy. +func (h *StandardHealthcheck) Error() error { + return h.err +} + +// Healthy marks the healthcheck as healthy. +func (h *StandardHealthcheck) Healthy() { + h.err = nil +} + +// Unhealthy marks the healthcheck as unhealthy. The error is stored and +// may be retrieved by the Error method. +func (h *StandardHealthcheck) Unhealthy(err error) { + h.err = err +} diff --git a/github.com/rcrowley/go-metrics/histogram.go b/github.com/rcrowley/go-metrics/histogram.go new file mode 100644 index 00000000..dbc837fe --- /dev/null +++ b/github.com/rcrowley/go-metrics/histogram.go @@ -0,0 +1,202 @@ +package metrics + +// Histograms calculate distribution statistics from a series of int64 values. +type Histogram interface { + Clear() + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + Sample() Sample + Snapshot() Histogram + StdDev() float64 + Sum() int64 + Update(int64) + Variance() float64 +} + +// GetOrRegisterHistogram returns an existing Histogram or constructs and +// registers a new StandardHistogram. +func GetOrRegisterHistogram(name string, r Registry, s Sample) Histogram { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, func() Histogram { return NewHistogram(s) }).(Histogram) +} + +// NewHistogram constructs a new StandardHistogram from a Sample. +func NewHistogram(s Sample) Histogram { + if UseNilMetrics { + return NilHistogram{} + } + return &StandardHistogram{sample: s} +} + +// NewRegisteredHistogram constructs and registers a new StandardHistogram from +// a Sample. +func NewRegisteredHistogram(name string, r Registry, s Sample) Histogram { + c := NewHistogram(s) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// HistogramSnapshot is a read-only copy of another Histogram. +type HistogramSnapshot struct { + sample *SampleSnapshot +} + +// Clear panics. +func (*HistogramSnapshot) Clear() { + panic("Clear called on a HistogramSnapshot") +} + +// Count returns the number of samples recorded at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Count() int64 { return h.sample.Count() } + +// Max returns the maximum value in the sample at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Max() int64 { return h.sample.Max() } + +// Mean returns the mean of the values in the sample at the time the snapshot +// was taken. +func (h *HistogramSnapshot) Mean() float64 { return h.sample.Mean() } + +// Min returns the minimum value in the sample at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Min() int64 { return h.sample.Min() } + +// Percentile returns an arbitrary percentile of values in the sample at the +// time the snapshot was taken. +func (h *HistogramSnapshot) Percentile(p float64) float64 { + return h.sample.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the sample +// at the time the snapshot was taken. +func (h *HistogramSnapshot) Percentiles(ps []float64) []float64 { + return h.sample.Percentiles(ps) +} + +// Sample returns the Sample underlying the histogram. +func (h *HistogramSnapshot) Sample() Sample { return h.sample } + +// Snapshot returns the snapshot. +func (h *HistogramSnapshot) Snapshot() Histogram { return h } + +// StdDev returns the standard deviation of the values in the sample at the +// time the snapshot was taken. +func (h *HistogramSnapshot) StdDev() float64 { return h.sample.StdDev() } + +// Sum returns the sum in the sample at the time the snapshot was taken. +func (h *HistogramSnapshot) Sum() int64 { return h.sample.Sum() } + +// Update panics. +func (*HistogramSnapshot) Update(int64) { + panic("Update called on a HistogramSnapshot") +} + +// Variance returns the variance of inputs at the time the snapshot was taken. +func (h *HistogramSnapshot) Variance() float64 { return h.sample.Variance() } + +// NilHistogram is a no-op Histogram. +type NilHistogram struct{} + +// Clear is a no-op. +func (NilHistogram) Clear() {} + +// Count is a no-op. +func (NilHistogram) Count() int64 { return 0 } + +// Max is a no-op. +func (NilHistogram) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilHistogram) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilHistogram) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilHistogram) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilHistogram) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Sample is a no-op. +func (NilHistogram) Sample() Sample { return NilSample{} } + +// Snapshot is a no-op. +func (NilHistogram) Snapshot() Histogram { return NilHistogram{} } + +// StdDev is a no-op. +func (NilHistogram) StdDev() float64 { return 0.0 } + +// Sum is a no-op. +func (NilHistogram) Sum() int64 { return 0 } + +// Update is a no-op. +func (NilHistogram) Update(v int64) {} + +// Variance is a no-op. +func (NilHistogram) Variance() float64 { return 0.0 } + +// StandardHistogram is the standard implementation of a Histogram and uses a +// Sample to bound its memory use. +type StandardHistogram struct { + sample Sample +} + +// Clear clears the histogram and its sample. +func (h *StandardHistogram) Clear() { h.sample.Clear() } + +// Count returns the number of samples recorded since the histogram was last +// cleared. +func (h *StandardHistogram) Count() int64 { return h.sample.Count() } + +// Max returns the maximum value in the sample. +func (h *StandardHistogram) Max() int64 { return h.sample.Max() } + +// Mean returns the mean of the values in the sample. +func (h *StandardHistogram) Mean() float64 { return h.sample.Mean() } + +// Min returns the minimum value in the sample. +func (h *StandardHistogram) Min() int64 { return h.sample.Min() } + +// Percentile returns an arbitrary percentile of the values in the sample. +func (h *StandardHistogram) Percentile(p float64) float64 { + return h.sample.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of the values in the +// sample. +func (h *StandardHistogram) Percentiles(ps []float64) []float64 { + return h.sample.Percentiles(ps) +} + +// Sample returns the Sample underlying the histogram. +func (h *StandardHistogram) Sample() Sample { return h.sample } + +// Snapshot returns a read-only copy of the histogram. +func (h *StandardHistogram) Snapshot() Histogram { + return &HistogramSnapshot{sample: h.sample.Snapshot().(*SampleSnapshot)} +} + +// StdDev returns the standard deviation of the values in the sample. +func (h *StandardHistogram) StdDev() float64 { return h.sample.StdDev() } + +// Sum returns the sum in the sample. +func (h *StandardHistogram) Sum() int64 { return h.sample.Sum() } + +// Update samples a new value. +func (h *StandardHistogram) Update(v int64) { h.sample.Update(v) } + +// Variance returns the variance of the values in the sample. +func (h *StandardHistogram) Variance() float64 { return h.sample.Variance() } diff --git a/github.com/rcrowley/go-metrics/json.go b/github.com/rcrowley/go-metrics/json.go new file mode 100644 index 00000000..174b9477 --- /dev/null +++ b/github.com/rcrowley/go-metrics/json.go @@ -0,0 +1,31 @@ +package metrics + +import ( + "encoding/json" + "io" + "time" +) + +// MarshalJSON returns a byte slice containing a JSON representation of all +// the metrics in the Registry. +func (r *StandardRegistry) MarshalJSON() ([]byte, error) { + return json.Marshal(r.GetAll()) +} + +// WriteJSON writes metrics from the given registry periodically to the +// specified io.Writer as JSON. +func WriteJSON(r Registry, d time.Duration, w io.Writer) { + for _ = range time.Tick(d) { + WriteJSONOnce(r, w) + } +} + +// WriteJSONOnce writes metrics from the given registry to the specified +// io.Writer as JSON. +func WriteJSONOnce(r Registry, w io.Writer) { + json.NewEncoder(w).Encode(r) +} + +func (p *PrefixedRegistry) MarshalJSON() ([]byte, error) { + return json.Marshal(p.GetAll()) +} diff --git a/github.com/rcrowley/go-metrics/log.go b/github.com/rcrowley/go-metrics/log.go new file mode 100644 index 00000000..f8074c04 --- /dev/null +++ b/github.com/rcrowley/go-metrics/log.go @@ -0,0 +1,80 @@ +package metrics + +import ( + "time" +) + +type Logger interface { + Printf(format string, v ...interface{}) +} + +func Log(r Registry, freq time.Duration, l Logger) { + LogScaled(r, freq, time.Nanosecond, l) +} + +// Output each metric in the given registry periodically using the given +// logger. Print timings in `scale` units (eg time.Millisecond) rather than nanos. +func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) { + du := float64(scale) + duSuffix := scale.String()[1:] + + for _ = range time.Tick(freq) { + r.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + l.Printf("counter %s\n", name) + l.Printf(" count: %9d\n", metric.Count()) + case Gauge: + l.Printf("gauge %s\n", name) + l.Printf(" value: %9d\n", metric.Value()) + case GaugeFloat64: + l.Printf("gauge %s\n", name) + l.Printf(" value: %f\n", metric.Value()) + case Healthcheck: + metric.Check() + l.Printf("healthcheck %s\n", name) + l.Printf(" error: %v\n", metric.Error()) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + l.Printf("histogram %s\n", name) + l.Printf(" count: %9d\n", h.Count()) + l.Printf(" min: %9d\n", h.Min()) + l.Printf(" max: %9d\n", h.Max()) + l.Printf(" mean: %12.2f\n", h.Mean()) + l.Printf(" stddev: %12.2f\n", h.StdDev()) + l.Printf(" median: %12.2f\n", ps[0]) + l.Printf(" 75%%: %12.2f\n", ps[1]) + l.Printf(" 95%%: %12.2f\n", ps[2]) + l.Printf(" 99%%: %12.2f\n", ps[3]) + l.Printf(" 99.9%%: %12.2f\n", ps[4]) + case Meter: + m := metric.Snapshot() + l.Printf("meter %s\n", name) + l.Printf(" count: %9d\n", m.Count()) + l.Printf(" 1-min rate: %12.2f\n", m.Rate1()) + l.Printf(" 5-min rate: %12.2f\n", m.Rate5()) + l.Printf(" 15-min rate: %12.2f\n", m.Rate15()) + l.Printf(" mean rate: %12.2f\n", m.RateMean()) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + l.Printf("timer %s\n", name) + l.Printf(" count: %9d\n", t.Count()) + l.Printf(" min: %12.2f%s\n", float64(t.Min())/du, duSuffix) + l.Printf(" max: %12.2f%s\n", float64(t.Max())/du, duSuffix) + l.Printf(" mean: %12.2f%s\n", t.Mean()/du, duSuffix) + l.Printf(" stddev: %12.2f%s\n", t.StdDev()/du, duSuffix) + l.Printf(" median: %12.2f%s\n", ps[0]/du, duSuffix) + l.Printf(" 75%%: %12.2f%s\n", ps[1]/du, duSuffix) + l.Printf(" 95%%: %12.2f%s\n", ps[2]/du, duSuffix) + l.Printf(" 99%%: %12.2f%s\n", ps[3]/du, duSuffix) + l.Printf(" 99.9%%: %12.2f%s\n", ps[4]/du, duSuffix) + l.Printf(" 1-min rate: %12.2f\n", t.Rate1()) + l.Printf(" 5-min rate: %12.2f\n", t.Rate5()) + l.Printf(" 15-min rate: %12.2f\n", t.Rate15()) + l.Printf(" mean rate: %12.2f\n", t.RateMean()) + } + }) + } +} diff --git a/github.com/rcrowley/go-metrics/meter.go b/github.com/rcrowley/go-metrics/meter.go new file mode 100644 index 00000000..53ff329b --- /dev/null +++ b/github.com/rcrowley/go-metrics/meter.go @@ -0,0 +1,264 @@ +package metrics + +import ( + "sync" + "time" +) + +// Meters count events to produce exponentially-weighted moving average rates +// at one-, five-, and fifteen-minutes and a mean rate. +type Meter interface { + Count() int64 + Mark(int64) + Rate1() float64 + Rate5() float64 + Rate15() float64 + RateMean() float64 + Snapshot() Meter + Stop() +} + +// GetOrRegisterMeter returns an existing Meter or constructs and registers a +// new StandardMeter. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. +func GetOrRegisterMeter(name string, r Registry) Meter { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewMeter).(Meter) +} + +// NewMeter constructs a new StandardMeter and launches a goroutine. +// Be sure to call Stop() once the meter is of no use to allow for garbage collection. +func NewMeter() Meter { + if UseNilMetrics { + return NilMeter{} + } + m := newStandardMeter() + arbiter.Lock() + defer arbiter.Unlock() + arbiter.meters[m] = struct{}{} + if !arbiter.started { + arbiter.started = true + go arbiter.tick() + } + return m +} + +// NewMeter constructs and registers a new StandardMeter and launches a +// goroutine. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. +func NewRegisteredMeter(name string, r Registry) Meter { + c := NewMeter() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// MeterSnapshot is a read-only copy of another Meter. +type MeterSnapshot struct { + count int64 + rate1, rate5, rate15, rateMean float64 +} + +// Count returns the count of events at the time the snapshot was taken. +func (m *MeterSnapshot) Count() int64 { return m.count } + +// Mark panics. +func (*MeterSnapshot) Mark(n int64) { + panic("Mark called on a MeterSnapshot") +} + +// Rate1 returns the one-minute moving average rate of events per second at the +// time the snapshot was taken. +func (m *MeterSnapshot) Rate1() float64 { return m.rate1 } + +// Rate5 returns the five-minute moving average rate of events per second at +// the time the snapshot was taken. +func (m *MeterSnapshot) Rate5() float64 { return m.rate5 } + +// Rate15 returns the fifteen-minute moving average rate of events per second +// at the time the snapshot was taken. +func (m *MeterSnapshot) Rate15() float64 { return m.rate15 } + +// RateMean returns the meter's mean rate of events per second at the time the +// snapshot was taken. +func (m *MeterSnapshot) RateMean() float64 { return m.rateMean } + +// Snapshot returns the snapshot. +func (m *MeterSnapshot) Snapshot() Meter { return m } + +// Stop is a no-op. +func (m *MeterSnapshot) Stop() {} + +// NilMeter is a no-op Meter. +type NilMeter struct{} + +// Count is a no-op. +func (NilMeter) Count() int64 { return 0 } + +// Mark is a no-op. +func (NilMeter) Mark(n int64) {} + +// Rate1 is a no-op. +func (NilMeter) Rate1() float64 { return 0.0 } + +// Rate5 is a no-op. +func (NilMeter) Rate5() float64 { return 0.0 } + +// Rate15is a no-op. +func (NilMeter) Rate15() float64 { return 0.0 } + +// RateMean is a no-op. +func (NilMeter) RateMean() float64 { return 0.0 } + +// Snapshot is a no-op. +func (NilMeter) Snapshot() Meter { return NilMeter{} } + +// Stop is a no-op. +func (NilMeter) Stop() {} + +// StandardMeter is the standard implementation of a Meter. +type StandardMeter struct { + lock sync.RWMutex + snapshot *MeterSnapshot + a1, a5, a15 EWMA + startTime time.Time + stopped bool +} + +func newStandardMeter() *StandardMeter { + return &StandardMeter{ + snapshot: &MeterSnapshot{}, + a1: NewEWMA1(), + a5: NewEWMA5(), + a15: NewEWMA15(), + startTime: time.Now(), + } +} + +// Stop stops the meter, Mark() will be a no-op if you use it after being stopped. +func (m *StandardMeter) Stop() { + m.lock.Lock() + stopped := m.stopped + m.stopped = true + m.lock.Unlock() + if !stopped { + arbiter.Lock() + delete(arbiter.meters, m) + arbiter.Unlock() + } +} + +// Count returns the number of events recorded. +func (m *StandardMeter) Count() int64 { + m.lock.RLock() + count := m.snapshot.count + m.lock.RUnlock() + return count +} + +// Mark records the occurance of n events. +func (m *StandardMeter) Mark(n int64) { + m.lock.Lock() + defer m.lock.Unlock() + if m.stopped { + return + } + m.snapshot.count += n + m.a1.Update(n) + m.a5.Update(n) + m.a15.Update(n) + m.updateSnapshot() +} + +// Rate1 returns the one-minute moving average rate of events per second. +func (m *StandardMeter) Rate1() float64 { + m.lock.RLock() + rate1 := m.snapshot.rate1 + m.lock.RUnlock() + return rate1 +} + +// Rate5 returns the five-minute moving average rate of events per second. +func (m *StandardMeter) Rate5() float64 { + m.lock.RLock() + rate5 := m.snapshot.rate5 + m.lock.RUnlock() + return rate5 +} + +// Rate15 returns the fifteen-minute moving average rate of events per second. +func (m *StandardMeter) Rate15() float64 { + m.lock.RLock() + rate15 := m.snapshot.rate15 + m.lock.RUnlock() + return rate15 +} + +// RateMean returns the meter's mean rate of events per second. +func (m *StandardMeter) RateMean() float64 { + m.lock.RLock() + rateMean := m.snapshot.rateMean + m.lock.RUnlock() + return rateMean +} + +// Snapshot returns a read-only copy of the meter. +func (m *StandardMeter) Snapshot() Meter { + m.lock.RLock() + snapshot := *m.snapshot + m.lock.RUnlock() + return &snapshot +} + +func (m *StandardMeter) updateSnapshot() { + // should run with write lock held on m.lock + snapshot := m.snapshot + snapshot.rate1 = m.a1.Rate() + snapshot.rate5 = m.a5.Rate() + snapshot.rate15 = m.a15.Rate() + snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds() +} + +func (m *StandardMeter) tick() { + m.lock.Lock() + defer m.lock.Unlock() + m.a1.Tick() + m.a5.Tick() + m.a15.Tick() + m.updateSnapshot() +} + +// meterArbiter ticks meters every 5s from a single goroutine. +// meters are references in a set for future stopping. +type meterArbiter struct { + sync.RWMutex + started bool + meters map[*StandardMeter]struct{} + ticker *time.Ticker +} + +var arbiter = meterArbiter{ticker: time.NewTicker(5e9), meters: make(map[*StandardMeter]struct{})} + +// Ticks meters on the scheduled interval +func (ma *meterArbiter) tick() { + for { + select { + case <-ma.ticker.C: + ma.tickMeters() + } + } +} + +func (ma *meterArbiter) tickMeters() { + ma.RLock() + defer ma.RUnlock() + for meter := range ma.meters { + meter.tick() + } +} diff --git a/github.com/rcrowley/go-metrics/metrics.go b/github.com/rcrowley/go-metrics/metrics.go new file mode 100644 index 00000000..b97a49ed --- /dev/null +++ b/github.com/rcrowley/go-metrics/metrics.go @@ -0,0 +1,13 @@ +// Go port of Coda Hale's Metrics library +// +// +// +// Coda Hale's original work: +package metrics + +// UseNilMetrics is checked by the constructor functions for all of the +// standard metrics. If it is true, the metric returned is a stub. +// +// This global kill-switch helps quantify the observer effect and makes +// for less cluttered pprof profiles. +var UseNilMetrics bool = false diff --git a/github.com/rcrowley/go-metrics/opentsdb.go b/github.com/rcrowley/go-metrics/opentsdb.go new file mode 100644 index 00000000..266b6c93 --- /dev/null +++ b/github.com/rcrowley/go-metrics/opentsdb.go @@ -0,0 +1,119 @@ +package metrics + +import ( + "bufio" + "fmt" + "log" + "net" + "os" + "strings" + "time" +) + +var shortHostName string = "" + +// OpenTSDBConfig provides a container with configuration parameters for +// the OpenTSDB exporter +type OpenTSDBConfig struct { + Addr *net.TCPAddr // Network address to connect to + Registry Registry // Registry to be exported + FlushInterval time.Duration // Flush interval + DurationUnit time.Duration // Time conversion unit for durations + Prefix string // Prefix to be prepended to metric names +} + +// OpenTSDB is a blocking exporter function which reports metrics in r +// to a TSDB server located at addr, flushing them every d duration +// and prepending metric names with prefix. +func OpenTSDB(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) { + OpenTSDBWithConfig(OpenTSDBConfig{ + Addr: addr, + Registry: r, + FlushInterval: d, + DurationUnit: time.Nanosecond, + Prefix: prefix, + }) +} + +// OpenTSDBWithConfig is a blocking exporter function just like OpenTSDB, +// but it takes a OpenTSDBConfig instead. +func OpenTSDBWithConfig(c OpenTSDBConfig) { + for _ = range time.Tick(c.FlushInterval) { + if err := openTSDB(&c); nil != err { + log.Println(err) + } + } +} + +func getShortHostname() string { + if shortHostName == "" { + host, _ := os.Hostname() + if index := strings.Index(host, "."); index > 0 { + shortHostName = host[:index] + } else { + shortHostName = host + } + } + return shortHostName +} + +func openTSDB(c *OpenTSDBConfig) error { + shortHostname := getShortHostname() + now := time.Now().Unix() + du := float64(c.DurationUnit) + conn, err := net.DialTCP("tcp", nil, c.Addr) + if nil != err { + return err + } + defer conn.Close() + w := bufio.NewWriter(conn) + c.Registry.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, metric.Count(), shortHostname) + case Gauge: + fmt.Fprintf(w, "put %s.%s.value %d %d host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname) + case GaugeFloat64: + fmt.Fprintf(w, "put %s.%s.value %d %f host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, h.Count(), shortHostname) + fmt.Fprintf(w, "put %s.%s.min %d %d host=%s\n", c.Prefix, name, now, h.Min(), shortHostname) + fmt.Fprintf(w, "put %s.%s.max %d %d host=%s\n", c.Prefix, name, now, h.Max(), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, h.Mean(), shortHostname) + fmt.Fprintf(w, "put %s.%s.std-dev %d %.2f host=%s\n", c.Prefix, name, now, h.StdDev(), shortHostname) + fmt.Fprintf(w, "put %s.%s.50-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[0], shortHostname) + fmt.Fprintf(w, "put %s.%s.75-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[1], shortHostname) + fmt.Fprintf(w, "put %s.%s.95-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[2], shortHostname) + fmt.Fprintf(w, "put %s.%s.99-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[3], shortHostname) + fmt.Fprintf(w, "put %s.%s.999-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[4], shortHostname) + case Meter: + m := metric.Snapshot() + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, m.Count(), shortHostname) + fmt.Fprintf(w, "put %s.%s.one-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate1(), shortHostname) + fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate5(), shortHostname) + fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate15(), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, m.RateMean(), shortHostname) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, t.Count(), shortHostname) + fmt.Fprintf(w, "put %s.%s.min %d %d host=%s\n", c.Prefix, name, now, t.Min()/int64(du), shortHostname) + fmt.Fprintf(w, "put %s.%s.max %d %d host=%s\n", c.Prefix, name, now, t.Max()/int64(du), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, t.Mean()/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.std-dev %d %.2f host=%s\n", c.Prefix, name, now, t.StdDev()/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.50-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[0]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.75-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[1]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.95-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[2]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.99-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[3]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.999-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[4]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.one-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate1(), shortHostname) + fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate5(), shortHostname) + fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate15(), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean-rate %d %.2f host=%s\n", c.Prefix, name, now, t.RateMean(), shortHostname) + } + w.Flush() + }) + return nil +} diff --git a/github.com/rcrowley/go-metrics/registry.go b/github.com/rcrowley/go-metrics/registry.go new file mode 100644 index 00000000..6c0007b1 --- /dev/null +++ b/github.com/rcrowley/go-metrics/registry.go @@ -0,0 +1,354 @@ +package metrics + +import ( + "fmt" + "reflect" + "strings" + "sync" +) + +// DuplicateMetric is the error returned by Registry.Register when a metric +// already exists. If you mean to Register that metric you must first +// Unregister the existing metric. +type DuplicateMetric string + +func (err DuplicateMetric) Error() string { + return fmt.Sprintf("duplicate metric: %s", string(err)) +} + +// A Registry holds references to a set of metrics by name and can iterate +// over them, calling callback functions provided by the user. +// +// This is an interface so as to encourage other structs to implement +// the Registry API as appropriate. +type Registry interface { + + // Call the given function for each registered metric. + Each(func(string, interface{})) + + // Get the metric by the given name or nil if none is registered. + Get(string) interface{} + + // GetAll metrics in the Registry. + GetAll() map[string]map[string]interface{} + + // Gets an existing metric or registers the given one. + // The interface can be the metric to register if not found in registry, + // or a function returning the metric for lazy instantiation. + GetOrRegister(string, interface{}) interface{} + + // Register the given metric under the given name. + Register(string, interface{}) error + + // Run all registered healthchecks. + RunHealthchecks() + + // Unregister the metric with the given name. + Unregister(string) + + // Unregister all metrics. (Mostly for testing.) + UnregisterAll() +} + +// The standard implementation of a Registry is a mutex-protected map +// of names to metrics. +type StandardRegistry struct { + metrics map[string]interface{} + mutex sync.Mutex +} + +// Create a new registry. +func NewRegistry() Registry { + return &StandardRegistry{metrics: make(map[string]interface{})} +} + +// Call the given function for each registered metric. +func (r *StandardRegistry) Each(f func(string, interface{})) { + for name, i := range r.registered() { + f(name, i) + } +} + +// Get the metric by the given name or nil if none is registered. +func (r *StandardRegistry) Get(name string) interface{} { + r.mutex.Lock() + defer r.mutex.Unlock() + return r.metrics[name] +} + +// Gets an existing metric or creates and registers a new one. Threadsafe +// alternative to calling Get and Register on failure. +// The interface can be the metric to register if not found in registry, +// or a function returning the metric for lazy instantiation. +func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} { + r.mutex.Lock() + defer r.mutex.Unlock() + if metric, ok := r.metrics[name]; ok { + return metric + } + if v := reflect.ValueOf(i); v.Kind() == reflect.Func { + i = v.Call(nil)[0].Interface() + } + r.register(name, i) + return i +} + +// Register the given metric under the given name. Returns a DuplicateMetric +// if a metric by the given name is already registered. +func (r *StandardRegistry) Register(name string, i interface{}) error { + r.mutex.Lock() + defer r.mutex.Unlock() + return r.register(name, i) +} + +// Run all registered healthchecks. +func (r *StandardRegistry) RunHealthchecks() { + r.mutex.Lock() + defer r.mutex.Unlock() + for _, i := range r.metrics { + if h, ok := i.(Healthcheck); ok { + h.Check() + } + } +} + +// GetAll metrics in the Registry +func (r *StandardRegistry) GetAll() map[string]map[string]interface{} { + data := make(map[string]map[string]interface{}) + r.Each(func(name string, i interface{}) { + values := make(map[string]interface{}) + switch metric := i.(type) { + case Counter: + values["count"] = metric.Count() + case Gauge: + values["value"] = metric.Value() + case GaugeFloat64: + values["value"] = metric.Value() + case Healthcheck: + values["error"] = nil + metric.Check() + if err := metric.Error(); nil != err { + values["error"] = metric.Error().Error() + } + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + values["count"] = h.Count() + values["min"] = h.Min() + values["max"] = h.Max() + values["mean"] = h.Mean() + values["stddev"] = h.StdDev() + values["median"] = ps[0] + values["75%"] = ps[1] + values["95%"] = ps[2] + values["99%"] = ps[3] + values["99.9%"] = ps[4] + case Meter: + m := metric.Snapshot() + values["count"] = m.Count() + values["1m.rate"] = m.Rate1() + values["5m.rate"] = m.Rate5() + values["15m.rate"] = m.Rate15() + values["mean.rate"] = m.RateMean() + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + values["count"] = t.Count() + values["min"] = t.Min() + values["max"] = t.Max() + values["mean"] = t.Mean() + values["stddev"] = t.StdDev() + values["median"] = ps[0] + values["75%"] = ps[1] + values["95%"] = ps[2] + values["99%"] = ps[3] + values["99.9%"] = ps[4] + values["1m.rate"] = t.Rate1() + values["5m.rate"] = t.Rate5() + values["15m.rate"] = t.Rate15() + values["mean.rate"] = t.RateMean() + } + data[name] = values + }) + return data +} + +// Unregister the metric with the given name. +func (r *StandardRegistry) Unregister(name string) { + r.mutex.Lock() + defer r.mutex.Unlock() + r.stop(name) + delete(r.metrics, name) +} + +// Unregister all metrics. (Mostly for testing.) +func (r *StandardRegistry) UnregisterAll() { + r.mutex.Lock() + defer r.mutex.Unlock() + for name, _ := range r.metrics { + r.stop(name) + delete(r.metrics, name) + } +} + +func (r *StandardRegistry) register(name string, i interface{}) error { + if _, ok := r.metrics[name]; ok { + return DuplicateMetric(name) + } + switch i.(type) { + case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer: + r.metrics[name] = i + } + return nil +} + +func (r *StandardRegistry) registered() map[string]interface{} { + r.mutex.Lock() + defer r.mutex.Unlock() + metrics := make(map[string]interface{}, len(r.metrics)) + for name, i := range r.metrics { + metrics[name] = i + } + return metrics +} + +func (r *StandardRegistry) stop(name string) { + if i, ok := r.metrics[name]; ok { + if s, ok := i.(Stoppable); ok { + s.Stop() + } + } +} + +// Stoppable defines the metrics which has to be stopped. +type Stoppable interface { + Stop() +} + +type PrefixedRegistry struct { + underlying Registry + prefix string +} + +func NewPrefixedRegistry(prefix string) Registry { + return &PrefixedRegistry{ + underlying: NewRegistry(), + prefix: prefix, + } +} + +func NewPrefixedChildRegistry(parent Registry, prefix string) Registry { + return &PrefixedRegistry{ + underlying: parent, + prefix: prefix, + } +} + +// Call the given function for each registered metric. +func (r *PrefixedRegistry) Each(fn func(string, interface{})) { + wrappedFn := func(prefix string) func(string, interface{}) { + return func(name string, iface interface{}) { + if strings.HasPrefix(name, prefix) { + fn(name, iface) + } else { + return + } + } + } + + baseRegistry, prefix := findPrefix(r, "") + baseRegistry.Each(wrappedFn(prefix)) +} + +func findPrefix(registry Registry, prefix string) (Registry, string) { + switch r := registry.(type) { + case *PrefixedRegistry: + return findPrefix(r.underlying, r.prefix+prefix) + case *StandardRegistry: + return r, prefix + } + return nil, "" +} + +// Get the metric by the given name or nil if none is registered. +func (r *PrefixedRegistry) Get(name string) interface{} { + realName := r.prefix + name + return r.underlying.Get(realName) +} + +// Gets an existing metric or registers the given one. +// The interface can be the metric to register if not found in registry, +// or a function returning the metric for lazy instantiation. +func (r *PrefixedRegistry) GetOrRegister(name string, metric interface{}) interface{} { + realName := r.prefix + name + return r.underlying.GetOrRegister(realName, metric) +} + +// Register the given metric under the given name. The name will be prefixed. +func (r *PrefixedRegistry) Register(name string, metric interface{}) error { + realName := r.prefix + name + return r.underlying.Register(realName, metric) +} + +// Run all registered healthchecks. +func (r *PrefixedRegistry) RunHealthchecks() { + r.underlying.RunHealthchecks() +} + +// GetAll metrics in the Registry +func (r *PrefixedRegistry) GetAll() map[string]map[string]interface{} { + return r.underlying.GetAll() +} + +// Unregister the metric with the given name. The name will be prefixed. +func (r *PrefixedRegistry) Unregister(name string) { + realName := r.prefix + name + r.underlying.Unregister(realName) +} + +// Unregister all metrics. (Mostly for testing.) +func (r *PrefixedRegistry) UnregisterAll() { + r.underlying.UnregisterAll() +} + +var DefaultRegistry Registry = NewRegistry() + +// Call the given function for each registered metric. +func Each(f func(string, interface{})) { + DefaultRegistry.Each(f) +} + +// Get the metric by the given name or nil if none is registered. +func Get(name string) interface{} { + return DefaultRegistry.Get(name) +} + +// Gets an existing metric or creates and registers a new one. Threadsafe +// alternative to calling Get and Register on failure. +func GetOrRegister(name string, i interface{}) interface{} { + return DefaultRegistry.GetOrRegister(name, i) +} + +// Register the given metric under the given name. Returns a DuplicateMetric +// if a metric by the given name is already registered. +func Register(name string, i interface{}) error { + return DefaultRegistry.Register(name, i) +} + +// Register the given metric under the given name. Panics if a metric by the +// given name is already registered. +func MustRegister(name string, i interface{}) { + if err := Register(name, i); err != nil { + panic(err) + } +} + +// Run all registered healthchecks. +func RunHealthchecks() { + DefaultRegistry.RunHealthchecks() +} + +// Unregister the metric with the given name. +func Unregister(name string) { + DefaultRegistry.Unregister(name) +} diff --git a/github.com/rcrowley/go-metrics/runtime.go b/github.com/rcrowley/go-metrics/runtime.go new file mode 100644 index 00000000..11c6b785 --- /dev/null +++ b/github.com/rcrowley/go-metrics/runtime.go @@ -0,0 +1,212 @@ +package metrics + +import ( + "runtime" + "runtime/pprof" + "time" +) + +var ( + memStats runtime.MemStats + runtimeMetrics struct { + MemStats struct { + Alloc Gauge + BuckHashSys Gauge + DebugGC Gauge + EnableGC Gauge + Frees Gauge + HeapAlloc Gauge + HeapIdle Gauge + HeapInuse Gauge + HeapObjects Gauge + HeapReleased Gauge + HeapSys Gauge + LastGC Gauge + Lookups Gauge + Mallocs Gauge + MCacheInuse Gauge + MCacheSys Gauge + MSpanInuse Gauge + MSpanSys Gauge + NextGC Gauge + NumGC Gauge + GCCPUFraction GaugeFloat64 + PauseNs Histogram + PauseTotalNs Gauge + StackInuse Gauge + StackSys Gauge + Sys Gauge + TotalAlloc Gauge + } + NumCgoCall Gauge + NumGoroutine Gauge + NumThread Gauge + ReadMemStats Timer + } + frees uint64 + lookups uint64 + mallocs uint64 + numGC uint32 + numCgoCalls int64 + + threadCreateProfile = pprof.Lookup("threadcreate") +) + +// Capture new values for the Go runtime statistics exported in +// runtime.MemStats. This is designed to be called as a goroutine. +func CaptureRuntimeMemStats(r Registry, d time.Duration) { + for _ = range time.Tick(d) { + CaptureRuntimeMemStatsOnce(r) + } +} + +// Capture new values for the Go runtime statistics exported in +// runtime.MemStats. This is designed to be called in a background +// goroutine. Giving a registry which has not been given to +// RegisterRuntimeMemStats will panic. +// +// Be very careful with this because runtime.ReadMemStats calls the C +// functions runtime·semacquire(&runtime·worldsema) and runtime·stoptheworld() +// and that last one does what it says on the tin. +func CaptureRuntimeMemStatsOnce(r Registry) { + t := time.Now() + runtime.ReadMemStats(&memStats) // This takes 50-200us. + runtimeMetrics.ReadMemStats.UpdateSince(t) + + runtimeMetrics.MemStats.Alloc.Update(int64(memStats.Alloc)) + runtimeMetrics.MemStats.BuckHashSys.Update(int64(memStats.BuckHashSys)) + if memStats.DebugGC { + runtimeMetrics.MemStats.DebugGC.Update(1) + } else { + runtimeMetrics.MemStats.DebugGC.Update(0) + } + if memStats.EnableGC { + runtimeMetrics.MemStats.EnableGC.Update(1) + } else { + runtimeMetrics.MemStats.EnableGC.Update(0) + } + + runtimeMetrics.MemStats.Frees.Update(int64(memStats.Frees - frees)) + runtimeMetrics.MemStats.HeapAlloc.Update(int64(memStats.HeapAlloc)) + runtimeMetrics.MemStats.HeapIdle.Update(int64(memStats.HeapIdle)) + runtimeMetrics.MemStats.HeapInuse.Update(int64(memStats.HeapInuse)) + runtimeMetrics.MemStats.HeapObjects.Update(int64(memStats.HeapObjects)) + runtimeMetrics.MemStats.HeapReleased.Update(int64(memStats.HeapReleased)) + runtimeMetrics.MemStats.HeapSys.Update(int64(memStats.HeapSys)) + runtimeMetrics.MemStats.LastGC.Update(int64(memStats.LastGC)) + runtimeMetrics.MemStats.Lookups.Update(int64(memStats.Lookups - lookups)) + runtimeMetrics.MemStats.Mallocs.Update(int64(memStats.Mallocs - mallocs)) + runtimeMetrics.MemStats.MCacheInuse.Update(int64(memStats.MCacheInuse)) + runtimeMetrics.MemStats.MCacheSys.Update(int64(memStats.MCacheSys)) + runtimeMetrics.MemStats.MSpanInuse.Update(int64(memStats.MSpanInuse)) + runtimeMetrics.MemStats.MSpanSys.Update(int64(memStats.MSpanSys)) + runtimeMetrics.MemStats.NextGC.Update(int64(memStats.NextGC)) + runtimeMetrics.MemStats.NumGC.Update(int64(memStats.NumGC - numGC)) + runtimeMetrics.MemStats.GCCPUFraction.Update(gcCPUFraction(&memStats)) + + // + i := numGC % uint32(len(memStats.PauseNs)) + ii := memStats.NumGC % uint32(len(memStats.PauseNs)) + if memStats.NumGC-numGC >= uint32(len(memStats.PauseNs)) { + for i = 0; i < uint32(len(memStats.PauseNs)); i++ { + runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) + } + } else { + if i > ii { + for ; i < uint32(len(memStats.PauseNs)); i++ { + runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) + } + i = 0 + } + for ; i < ii; i++ { + runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) + } + } + frees = memStats.Frees + lookups = memStats.Lookups + mallocs = memStats.Mallocs + numGC = memStats.NumGC + + runtimeMetrics.MemStats.PauseTotalNs.Update(int64(memStats.PauseTotalNs)) + runtimeMetrics.MemStats.StackInuse.Update(int64(memStats.StackInuse)) + runtimeMetrics.MemStats.StackSys.Update(int64(memStats.StackSys)) + runtimeMetrics.MemStats.Sys.Update(int64(memStats.Sys)) + runtimeMetrics.MemStats.TotalAlloc.Update(int64(memStats.TotalAlloc)) + + currentNumCgoCalls := numCgoCall() + runtimeMetrics.NumCgoCall.Update(currentNumCgoCalls - numCgoCalls) + numCgoCalls = currentNumCgoCalls + + runtimeMetrics.NumGoroutine.Update(int64(runtime.NumGoroutine())) + + runtimeMetrics.NumThread.Update(int64(threadCreateProfile.Count())) +} + +// Register runtimeMetrics for the Go runtime statistics exported in runtime and +// specifically runtime.MemStats. The runtimeMetrics are named by their +// fully-qualified Go symbols, i.e. runtime.MemStats.Alloc. +func RegisterRuntimeMemStats(r Registry) { + runtimeMetrics.MemStats.Alloc = NewGauge() + runtimeMetrics.MemStats.BuckHashSys = NewGauge() + runtimeMetrics.MemStats.DebugGC = NewGauge() + runtimeMetrics.MemStats.EnableGC = NewGauge() + runtimeMetrics.MemStats.Frees = NewGauge() + runtimeMetrics.MemStats.HeapAlloc = NewGauge() + runtimeMetrics.MemStats.HeapIdle = NewGauge() + runtimeMetrics.MemStats.HeapInuse = NewGauge() + runtimeMetrics.MemStats.HeapObjects = NewGauge() + runtimeMetrics.MemStats.HeapReleased = NewGauge() + runtimeMetrics.MemStats.HeapSys = NewGauge() + runtimeMetrics.MemStats.LastGC = NewGauge() + runtimeMetrics.MemStats.Lookups = NewGauge() + runtimeMetrics.MemStats.Mallocs = NewGauge() + runtimeMetrics.MemStats.MCacheInuse = NewGauge() + runtimeMetrics.MemStats.MCacheSys = NewGauge() + runtimeMetrics.MemStats.MSpanInuse = NewGauge() + runtimeMetrics.MemStats.MSpanSys = NewGauge() + runtimeMetrics.MemStats.NextGC = NewGauge() + runtimeMetrics.MemStats.NumGC = NewGauge() + runtimeMetrics.MemStats.GCCPUFraction = NewGaugeFloat64() + runtimeMetrics.MemStats.PauseNs = NewHistogram(NewExpDecaySample(1028, 0.015)) + runtimeMetrics.MemStats.PauseTotalNs = NewGauge() + runtimeMetrics.MemStats.StackInuse = NewGauge() + runtimeMetrics.MemStats.StackSys = NewGauge() + runtimeMetrics.MemStats.Sys = NewGauge() + runtimeMetrics.MemStats.TotalAlloc = NewGauge() + runtimeMetrics.NumCgoCall = NewGauge() + runtimeMetrics.NumGoroutine = NewGauge() + runtimeMetrics.NumThread = NewGauge() + runtimeMetrics.ReadMemStats = NewTimer() + + r.Register("runtime.MemStats.Alloc", runtimeMetrics.MemStats.Alloc) + r.Register("runtime.MemStats.BuckHashSys", runtimeMetrics.MemStats.BuckHashSys) + r.Register("runtime.MemStats.DebugGC", runtimeMetrics.MemStats.DebugGC) + r.Register("runtime.MemStats.EnableGC", runtimeMetrics.MemStats.EnableGC) + r.Register("runtime.MemStats.Frees", runtimeMetrics.MemStats.Frees) + r.Register("runtime.MemStats.HeapAlloc", runtimeMetrics.MemStats.HeapAlloc) + r.Register("runtime.MemStats.HeapIdle", runtimeMetrics.MemStats.HeapIdle) + r.Register("runtime.MemStats.HeapInuse", runtimeMetrics.MemStats.HeapInuse) + r.Register("runtime.MemStats.HeapObjects", runtimeMetrics.MemStats.HeapObjects) + r.Register("runtime.MemStats.HeapReleased", runtimeMetrics.MemStats.HeapReleased) + r.Register("runtime.MemStats.HeapSys", runtimeMetrics.MemStats.HeapSys) + r.Register("runtime.MemStats.LastGC", runtimeMetrics.MemStats.LastGC) + r.Register("runtime.MemStats.Lookups", runtimeMetrics.MemStats.Lookups) + r.Register("runtime.MemStats.Mallocs", runtimeMetrics.MemStats.Mallocs) + r.Register("runtime.MemStats.MCacheInuse", runtimeMetrics.MemStats.MCacheInuse) + r.Register("runtime.MemStats.MCacheSys", runtimeMetrics.MemStats.MCacheSys) + r.Register("runtime.MemStats.MSpanInuse", runtimeMetrics.MemStats.MSpanInuse) + r.Register("runtime.MemStats.MSpanSys", runtimeMetrics.MemStats.MSpanSys) + r.Register("runtime.MemStats.NextGC", runtimeMetrics.MemStats.NextGC) + r.Register("runtime.MemStats.NumGC", runtimeMetrics.MemStats.NumGC) + r.Register("runtime.MemStats.GCCPUFraction", runtimeMetrics.MemStats.GCCPUFraction) + r.Register("runtime.MemStats.PauseNs", runtimeMetrics.MemStats.PauseNs) + r.Register("runtime.MemStats.PauseTotalNs", runtimeMetrics.MemStats.PauseTotalNs) + r.Register("runtime.MemStats.StackInuse", runtimeMetrics.MemStats.StackInuse) + r.Register("runtime.MemStats.StackSys", runtimeMetrics.MemStats.StackSys) + r.Register("runtime.MemStats.Sys", runtimeMetrics.MemStats.Sys) + r.Register("runtime.MemStats.TotalAlloc", runtimeMetrics.MemStats.TotalAlloc) + r.Register("runtime.NumCgoCall", runtimeMetrics.NumCgoCall) + r.Register("runtime.NumGoroutine", runtimeMetrics.NumGoroutine) + r.Register("runtime.NumThread", runtimeMetrics.NumThread) + r.Register("runtime.ReadMemStats", runtimeMetrics.ReadMemStats) +} diff --git a/github.com/rcrowley/go-metrics/runtime_cgo.go b/github.com/rcrowley/go-metrics/runtime_cgo.go new file mode 100644 index 00000000..e3391f4e --- /dev/null +++ b/github.com/rcrowley/go-metrics/runtime_cgo.go @@ -0,0 +1,10 @@ +// +build cgo +// +build !appengine + +package metrics + +import "runtime" + +func numCgoCall() int64 { + return runtime.NumCgoCall() +} diff --git a/github.com/rcrowley/go-metrics/runtime_gccpufraction.go b/github.com/rcrowley/go-metrics/runtime_gccpufraction.go new file mode 100644 index 00000000..ca12c05b --- /dev/null +++ b/github.com/rcrowley/go-metrics/runtime_gccpufraction.go @@ -0,0 +1,9 @@ +// +build go1.5 + +package metrics + +import "runtime" + +func gcCPUFraction(memStats *runtime.MemStats) float64 { + return memStats.GCCPUFraction +} diff --git a/github.com/rcrowley/go-metrics/runtime_no_cgo.go b/github.com/rcrowley/go-metrics/runtime_no_cgo.go new file mode 100644 index 00000000..616a3b47 --- /dev/null +++ b/github.com/rcrowley/go-metrics/runtime_no_cgo.go @@ -0,0 +1,7 @@ +// +build !cgo appengine + +package metrics + +func numCgoCall() int64 { + return 0 +} diff --git a/github.com/rcrowley/go-metrics/runtime_no_gccpufraction.go b/github.com/rcrowley/go-metrics/runtime_no_gccpufraction.go new file mode 100644 index 00000000..be96aa6f --- /dev/null +++ b/github.com/rcrowley/go-metrics/runtime_no_gccpufraction.go @@ -0,0 +1,9 @@ +// +build !go1.5 + +package metrics + +import "runtime" + +func gcCPUFraction(memStats *runtime.MemStats) float64 { + return 0 +} diff --git a/github.com/rcrowley/go-metrics/sample.go b/github.com/rcrowley/go-metrics/sample.go new file mode 100644 index 00000000..fecee5ef --- /dev/null +++ b/github.com/rcrowley/go-metrics/sample.go @@ -0,0 +1,616 @@ +package metrics + +import ( + "math" + "math/rand" + "sort" + "sync" + "time" +) + +const rescaleThreshold = time.Hour + +// Samples maintain a statistically-significant selection of values from +// a stream. +type Sample interface { + Clear() + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + Size() int + Snapshot() Sample + StdDev() float64 + Sum() int64 + Update(int64) + Values() []int64 + Variance() float64 +} + +// ExpDecaySample is an exponentially-decaying sample using a forward-decaying +// priority reservoir. See Cormode et al's "Forward Decay: A Practical Time +// Decay Model for Streaming Systems". +// +// +type ExpDecaySample struct { + alpha float64 + count int64 + mutex sync.Mutex + reservoirSize int + t0, t1 time.Time + values *expDecaySampleHeap +} + +// NewExpDecaySample constructs a new exponentially-decaying sample with the +// given reservoir size and alpha. +func NewExpDecaySample(reservoirSize int, alpha float64) Sample { + if UseNilMetrics { + return NilSample{} + } + s := &ExpDecaySample{ + alpha: alpha, + reservoirSize: reservoirSize, + t0: time.Now(), + values: newExpDecaySampleHeap(reservoirSize), + } + s.t1 = s.t0.Add(rescaleThreshold) + return s +} + +// Clear clears all samples. +func (s *ExpDecaySample) Clear() { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count = 0 + s.t0 = time.Now() + s.t1 = s.t0.Add(rescaleThreshold) + s.values.Clear() +} + +// Count returns the number of samples recorded, which may exceed the +// reservoir size. +func (s *ExpDecaySample) Count() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.count +} + +// Max returns the maximum value in the sample, which may not be the maximum +// value ever to be part of the sample. +func (s *ExpDecaySample) Max() int64 { + return SampleMax(s.Values()) +} + +// Mean returns the mean of the values in the sample. +func (s *ExpDecaySample) Mean() float64 { + return SampleMean(s.Values()) +} + +// Min returns the minimum value in the sample, which may not be the minimum +// value ever to be part of the sample. +func (s *ExpDecaySample) Min() int64 { + return SampleMin(s.Values()) +} + +// Percentile returns an arbitrary percentile of values in the sample. +func (s *ExpDecaySample) Percentile(p float64) float64 { + return SamplePercentile(s.Values(), p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the +// sample. +func (s *ExpDecaySample) Percentiles(ps []float64) []float64 { + return SamplePercentiles(s.Values(), ps) +} + +// Size returns the size of the sample, which is at most the reservoir size. +func (s *ExpDecaySample) Size() int { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.values.Size() +} + +// Snapshot returns a read-only copy of the sample. +func (s *ExpDecaySample) Snapshot() Sample { + s.mutex.Lock() + defer s.mutex.Unlock() + vals := s.values.Values() + values := make([]int64, len(vals)) + for i, v := range vals { + values[i] = v.v + } + return &SampleSnapshot{ + count: s.count, + values: values, + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (s *ExpDecaySample) StdDev() float64 { + return SampleStdDev(s.Values()) +} + +// Sum returns the sum of the values in the sample. +func (s *ExpDecaySample) Sum() int64 { + return SampleSum(s.Values()) +} + +// Update samples a new value. +func (s *ExpDecaySample) Update(v int64) { + s.update(time.Now(), v) +} + +// Values returns a copy of the values in the sample. +func (s *ExpDecaySample) Values() []int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + vals := s.values.Values() + values := make([]int64, len(vals)) + for i, v := range vals { + values[i] = v.v + } + return values +} + +// Variance returns the variance of the values in the sample. +func (s *ExpDecaySample) Variance() float64 { + return SampleVariance(s.Values()) +} + +// update samples a new value at a particular timestamp. This is a method all +// its own to facilitate testing. +func (s *ExpDecaySample) update(t time.Time, v int64) { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count++ + if s.values.Size() == s.reservoirSize { + s.values.Pop() + } + s.values.Push(expDecaySample{ + k: math.Exp(t.Sub(s.t0).Seconds()*s.alpha) / rand.Float64(), + v: v, + }) + if t.After(s.t1) { + values := s.values.Values() + t0 := s.t0 + s.values.Clear() + s.t0 = t + s.t1 = s.t0.Add(rescaleThreshold) + for _, v := range values { + v.k = v.k * math.Exp(-s.alpha*s.t0.Sub(t0).Seconds()) + s.values.Push(v) + } + } +} + +// NilSample is a no-op Sample. +type NilSample struct{} + +// Clear is a no-op. +func (NilSample) Clear() {} + +// Count is a no-op. +func (NilSample) Count() int64 { return 0 } + +// Max is a no-op. +func (NilSample) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilSample) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilSample) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilSample) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilSample) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Size is a no-op. +func (NilSample) Size() int { return 0 } + +// Sample is a no-op. +func (NilSample) Snapshot() Sample { return NilSample{} } + +// StdDev is a no-op. +func (NilSample) StdDev() float64 { return 0.0 } + +// Sum is a no-op. +func (NilSample) Sum() int64 { return 0 } + +// Update is a no-op. +func (NilSample) Update(v int64) {} + +// Values is a no-op. +func (NilSample) Values() []int64 { return []int64{} } + +// Variance is a no-op. +func (NilSample) Variance() float64 { return 0.0 } + +// SampleMax returns the maximum value of the slice of int64. +func SampleMax(values []int64) int64 { + if 0 == len(values) { + return 0 + } + var max int64 = math.MinInt64 + for _, v := range values { + if max < v { + max = v + } + } + return max +} + +// SampleMean returns the mean value of the slice of int64. +func SampleMean(values []int64) float64 { + if 0 == len(values) { + return 0.0 + } + return float64(SampleSum(values)) / float64(len(values)) +} + +// SampleMin returns the minimum value of the slice of int64. +func SampleMin(values []int64) int64 { + if 0 == len(values) { + return 0 + } + var min int64 = math.MaxInt64 + for _, v := range values { + if min > v { + min = v + } + } + return min +} + +// SamplePercentiles returns an arbitrary percentile of the slice of int64. +func SamplePercentile(values int64Slice, p float64) float64 { + return SamplePercentiles(values, []float64{p})[0] +} + +// SamplePercentiles returns a slice of arbitrary percentiles of the slice of +// int64. +func SamplePercentiles(values int64Slice, ps []float64) []float64 { + scores := make([]float64, len(ps)) + size := len(values) + if size > 0 { + sort.Sort(values) + for i, p := range ps { + pos := p * float64(size+1) + if pos < 1.0 { + scores[i] = float64(values[0]) + } else if pos >= float64(size) { + scores[i] = float64(values[size-1]) + } else { + lower := float64(values[int(pos)-1]) + upper := float64(values[int(pos)]) + scores[i] = lower + (pos-math.Floor(pos))*(upper-lower) + } + } + } + return scores +} + +// SampleSnapshot is a read-only copy of another Sample. +type SampleSnapshot struct { + count int64 + values []int64 +} + +func NewSampleSnapshot(count int64, values []int64) *SampleSnapshot { + return &SampleSnapshot{ + count: count, + values: values, + } +} + +// Clear panics. +func (*SampleSnapshot) Clear() { + panic("Clear called on a SampleSnapshot") +} + +// Count returns the count of inputs at the time the snapshot was taken. +func (s *SampleSnapshot) Count() int64 { return s.count } + +// Max returns the maximal value at the time the snapshot was taken. +func (s *SampleSnapshot) Max() int64 { return SampleMax(s.values) } + +// Mean returns the mean value at the time the snapshot was taken. +func (s *SampleSnapshot) Mean() float64 { return SampleMean(s.values) } + +// Min returns the minimal value at the time the snapshot was taken. +func (s *SampleSnapshot) Min() int64 { return SampleMin(s.values) } + +// Percentile returns an arbitrary percentile of values at the time the +// snapshot was taken. +func (s *SampleSnapshot) Percentile(p float64) float64 { + return SamplePercentile(s.values, p) +} + +// Percentiles returns a slice of arbitrary percentiles of values at the time +// the snapshot was taken. +func (s *SampleSnapshot) Percentiles(ps []float64) []float64 { + return SamplePercentiles(s.values, ps) +} + +// Size returns the size of the sample at the time the snapshot was taken. +func (s *SampleSnapshot) Size() int { return len(s.values) } + +// Snapshot returns the snapshot. +func (s *SampleSnapshot) Snapshot() Sample { return s } + +// StdDev returns the standard deviation of values at the time the snapshot was +// taken. +func (s *SampleSnapshot) StdDev() float64 { return SampleStdDev(s.values) } + +// Sum returns the sum of values at the time the snapshot was taken. +func (s *SampleSnapshot) Sum() int64 { return SampleSum(s.values) } + +// Update panics. +func (*SampleSnapshot) Update(int64) { + panic("Update called on a SampleSnapshot") +} + +// Values returns a copy of the values in the sample. +func (s *SampleSnapshot) Values() []int64 { + values := make([]int64, len(s.values)) + copy(values, s.values) + return values +} + +// Variance returns the variance of values at the time the snapshot was taken. +func (s *SampleSnapshot) Variance() float64 { return SampleVariance(s.values) } + +// SampleStdDev returns the standard deviation of the slice of int64. +func SampleStdDev(values []int64) float64 { + return math.Sqrt(SampleVariance(values)) +} + +// SampleSum returns the sum of the slice of int64. +func SampleSum(values []int64) int64 { + var sum int64 + for _, v := range values { + sum += v + } + return sum +} + +// SampleVariance returns the variance of the slice of int64. +func SampleVariance(values []int64) float64 { + if 0 == len(values) { + return 0.0 + } + m := SampleMean(values) + var sum float64 + for _, v := range values { + d := float64(v) - m + sum += d * d + } + return sum / float64(len(values)) +} + +// A uniform sample using Vitter's Algorithm R. +// +// +type UniformSample struct { + count int64 + mutex sync.Mutex + reservoirSize int + values []int64 +} + +// NewUniformSample constructs a new uniform sample with the given reservoir +// size. +func NewUniformSample(reservoirSize int) Sample { + if UseNilMetrics { + return NilSample{} + } + return &UniformSample{ + reservoirSize: reservoirSize, + values: make([]int64, 0, reservoirSize), + } +} + +// Clear clears all samples. +func (s *UniformSample) Clear() { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count = 0 + s.values = make([]int64, 0, s.reservoirSize) +} + +// Count returns the number of samples recorded, which may exceed the +// reservoir size. +func (s *UniformSample) Count() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.count +} + +// Max returns the maximum value in the sample, which may not be the maximum +// value ever to be part of the sample. +func (s *UniformSample) Max() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMax(s.values) +} + +// Mean returns the mean of the values in the sample. +func (s *UniformSample) Mean() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMean(s.values) +} + +// Min returns the minimum value in the sample, which may not be the minimum +// value ever to be part of the sample. +func (s *UniformSample) Min() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMin(s.values) +} + +// Percentile returns an arbitrary percentile of values in the sample. +func (s *UniformSample) Percentile(p float64) float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SamplePercentile(s.values, p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the +// sample. +func (s *UniformSample) Percentiles(ps []float64) []float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SamplePercentiles(s.values, ps) +} + +// Size returns the size of the sample, which is at most the reservoir size. +func (s *UniformSample) Size() int { + s.mutex.Lock() + defer s.mutex.Unlock() + return len(s.values) +} + +// Snapshot returns a read-only copy of the sample. +func (s *UniformSample) Snapshot() Sample { + s.mutex.Lock() + defer s.mutex.Unlock() + values := make([]int64, len(s.values)) + copy(values, s.values) + return &SampleSnapshot{ + count: s.count, + values: values, + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (s *UniformSample) StdDev() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleStdDev(s.values) +} + +// Sum returns the sum of the values in the sample. +func (s *UniformSample) Sum() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleSum(s.values) +} + +// Update samples a new value. +func (s *UniformSample) Update(v int64) { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count++ + if len(s.values) < s.reservoirSize { + s.values = append(s.values, v) + } else { + r := rand.Int63n(s.count) + if r < int64(len(s.values)) { + s.values[int(r)] = v + } + } +} + +// Values returns a copy of the values in the sample. +func (s *UniformSample) Values() []int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + values := make([]int64, len(s.values)) + copy(values, s.values) + return values +} + +// Variance returns the variance of the values in the sample. +func (s *UniformSample) Variance() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleVariance(s.values) +} + +// expDecaySample represents an individual sample in a heap. +type expDecaySample struct { + k float64 + v int64 +} + +func newExpDecaySampleHeap(reservoirSize int) *expDecaySampleHeap { + return &expDecaySampleHeap{make([]expDecaySample, 0, reservoirSize)} +} + +// expDecaySampleHeap is a min-heap of expDecaySamples. +// The internal implementation is copied from the standard library's container/heap +type expDecaySampleHeap struct { + s []expDecaySample +} + +func (h *expDecaySampleHeap) Clear() { + h.s = h.s[:0] +} + +func (h *expDecaySampleHeap) Push(s expDecaySample) { + n := len(h.s) + h.s = h.s[0 : n+1] + h.s[n] = s + h.up(n) +} + +func (h *expDecaySampleHeap) Pop() expDecaySample { + n := len(h.s) - 1 + h.s[0], h.s[n] = h.s[n], h.s[0] + h.down(0, n) + + n = len(h.s) + s := h.s[n-1] + h.s = h.s[0 : n-1] + return s +} + +func (h *expDecaySampleHeap) Size() int { + return len(h.s) +} + +func (h *expDecaySampleHeap) Values() []expDecaySample { + return h.s +} + +func (h *expDecaySampleHeap) up(j int) { + for { + i := (j - 1) / 2 // parent + if i == j || !(h.s[j].k < h.s[i].k) { + break + } + h.s[i], h.s[j] = h.s[j], h.s[i] + j = i + } +} + +func (h *expDecaySampleHeap) down(i, n int) { + for { + j1 := 2*i + 1 + if j1 >= n || j1 < 0 { // j1 < 0 after int overflow + break + } + j := j1 // left child + if j2 := j1 + 1; j2 < n && !(h.s[j1].k < h.s[j2].k) { + j = j2 // = 2*i + 2 // right child + } + if !(h.s[j].k < h.s[i].k) { + break + } + h.s[i], h.s[j] = h.s[j], h.s[i] + i = j + } +} + +type int64Slice []int64 + +func (p int64Slice) Len() int { return len(p) } +func (p int64Slice) Less(i, j int) bool { return p[i] < p[j] } +func (p int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } diff --git a/github.com/rcrowley/go-metrics/syslog.go b/github.com/rcrowley/go-metrics/syslog.go new file mode 100644 index 00000000..693f1908 --- /dev/null +++ b/github.com/rcrowley/go-metrics/syslog.go @@ -0,0 +1,78 @@ +// +build !windows + +package metrics + +import ( + "fmt" + "log/syslog" + "time" +) + +// Output each metric in the given registry to syslog periodically using +// the given syslogger. +func Syslog(r Registry, d time.Duration, w *syslog.Writer) { + for _ = range time.Tick(d) { + r.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + w.Info(fmt.Sprintf("counter %s: count: %d", name, metric.Count())) + case Gauge: + w.Info(fmt.Sprintf("gauge %s: value: %d", name, metric.Value())) + case GaugeFloat64: + w.Info(fmt.Sprintf("gauge %s: value: %f", name, metric.Value())) + case Healthcheck: + metric.Check() + w.Info(fmt.Sprintf("healthcheck %s: error: %v", name, metric.Error())) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + w.Info(fmt.Sprintf( + "histogram %s: count: %d min: %d max: %d mean: %.2f stddev: %.2f median: %.2f 75%%: %.2f 95%%: %.2f 99%%: %.2f 99.9%%: %.2f", + name, + h.Count(), + h.Min(), + h.Max(), + h.Mean(), + h.StdDev(), + ps[0], + ps[1], + ps[2], + ps[3], + ps[4], + )) + case Meter: + m := metric.Snapshot() + w.Info(fmt.Sprintf( + "meter %s: count: %d 1-min: %.2f 5-min: %.2f 15-min: %.2f mean: %.2f", + name, + m.Count(), + m.Rate1(), + m.Rate5(), + m.Rate15(), + m.RateMean(), + )) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + w.Info(fmt.Sprintf( + "timer %s: count: %d min: %d max: %d mean: %.2f stddev: %.2f median: %.2f 75%%: %.2f 95%%: %.2f 99%%: %.2f 99.9%%: %.2f 1-min: %.2f 5-min: %.2f 15-min: %.2f mean-rate: %.2f", + name, + t.Count(), + t.Min(), + t.Max(), + t.Mean(), + t.StdDev(), + ps[0], + ps[1], + ps[2], + ps[3], + ps[4], + t.Rate1(), + t.Rate5(), + t.Rate15(), + t.RateMean(), + )) + } + }) + } +} diff --git a/github.com/rcrowley/go-metrics/timer.go b/github.com/rcrowley/go-metrics/timer.go new file mode 100644 index 00000000..d6ec4c62 --- /dev/null +++ b/github.com/rcrowley/go-metrics/timer.go @@ -0,0 +1,329 @@ +package metrics + +import ( + "sync" + "time" +) + +// Timers capture the duration and rate of events. +type Timer interface { + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + Rate1() float64 + Rate5() float64 + Rate15() float64 + RateMean() float64 + Snapshot() Timer + StdDev() float64 + Stop() + Sum() int64 + Time(func()) + Update(time.Duration) + UpdateSince(time.Time) + Variance() float64 +} + +// GetOrRegisterTimer returns an existing Timer or constructs and registers a +// new StandardTimer. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. +func GetOrRegisterTimer(name string, r Registry) Timer { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewTimer).(Timer) +} + +// NewCustomTimer constructs a new StandardTimer from a Histogram and a Meter. +// Be sure to call Stop() once the timer is of no use to allow for garbage collection. +func NewCustomTimer(h Histogram, m Meter) Timer { + if UseNilMetrics { + return NilTimer{} + } + return &StandardTimer{ + histogram: h, + meter: m, + } +} + +// NewRegisteredTimer constructs and registers a new StandardTimer. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. +func NewRegisteredTimer(name string, r Registry) Timer { + c := NewTimer() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// NewTimer constructs a new StandardTimer using an exponentially-decaying +// sample with the same reservoir size and alpha as UNIX load averages. +// Be sure to call Stop() once the timer is of no use to allow for garbage collection. +func NewTimer() Timer { + if UseNilMetrics { + return NilTimer{} + } + return &StandardTimer{ + histogram: NewHistogram(NewExpDecaySample(1028, 0.015)), + meter: NewMeter(), + } +} + +// NilTimer is a no-op Timer. +type NilTimer struct { + h Histogram + m Meter +} + +// Count is a no-op. +func (NilTimer) Count() int64 { return 0 } + +// Max is a no-op. +func (NilTimer) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilTimer) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilTimer) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilTimer) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilTimer) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Rate1 is a no-op. +func (NilTimer) Rate1() float64 { return 0.0 } + +// Rate5 is a no-op. +func (NilTimer) Rate5() float64 { return 0.0 } + +// Rate15 is a no-op. +func (NilTimer) Rate15() float64 { return 0.0 } + +// RateMean is a no-op. +func (NilTimer) RateMean() float64 { return 0.0 } + +// Snapshot is a no-op. +func (NilTimer) Snapshot() Timer { return NilTimer{} } + +// StdDev is a no-op. +func (NilTimer) StdDev() float64 { return 0.0 } + +// Stop is a no-op. +func (NilTimer) Stop() {} + +// Sum is a no-op. +func (NilTimer) Sum() int64 { return 0 } + +// Time is a no-op. +func (NilTimer) Time(func()) {} + +// Update is a no-op. +func (NilTimer) Update(time.Duration) {} + +// UpdateSince is a no-op. +func (NilTimer) UpdateSince(time.Time) {} + +// Variance is a no-op. +func (NilTimer) Variance() float64 { return 0.0 } + +// StandardTimer is the standard implementation of a Timer and uses a Histogram +// and Meter. +type StandardTimer struct { + histogram Histogram + meter Meter + mutex sync.Mutex +} + +// Count returns the number of events recorded. +func (t *StandardTimer) Count() int64 { + return t.histogram.Count() +} + +// Max returns the maximum value in the sample. +func (t *StandardTimer) Max() int64 { + return t.histogram.Max() +} + +// Mean returns the mean of the values in the sample. +func (t *StandardTimer) Mean() float64 { + return t.histogram.Mean() +} + +// Min returns the minimum value in the sample. +func (t *StandardTimer) Min() int64 { + return t.histogram.Min() +} + +// Percentile returns an arbitrary percentile of the values in the sample. +func (t *StandardTimer) Percentile(p float64) float64 { + return t.histogram.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of the values in the +// sample. +func (t *StandardTimer) Percentiles(ps []float64) []float64 { + return t.histogram.Percentiles(ps) +} + +// Rate1 returns the one-minute moving average rate of events per second. +func (t *StandardTimer) Rate1() float64 { + return t.meter.Rate1() +} + +// Rate5 returns the five-minute moving average rate of events per second. +func (t *StandardTimer) Rate5() float64 { + return t.meter.Rate5() +} + +// Rate15 returns the fifteen-minute moving average rate of events per second. +func (t *StandardTimer) Rate15() float64 { + return t.meter.Rate15() +} + +// RateMean returns the meter's mean rate of events per second. +func (t *StandardTimer) RateMean() float64 { + return t.meter.RateMean() +} + +// Snapshot returns a read-only copy of the timer. +func (t *StandardTimer) Snapshot() Timer { + t.mutex.Lock() + defer t.mutex.Unlock() + return &TimerSnapshot{ + histogram: t.histogram.Snapshot().(*HistogramSnapshot), + meter: t.meter.Snapshot().(*MeterSnapshot), + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (t *StandardTimer) StdDev() float64 { + return t.histogram.StdDev() +} + +// Stop stops the meter. +func (t *StandardTimer) Stop() { + t.meter.Stop() +} + +// Sum returns the sum in the sample. +func (t *StandardTimer) Sum() int64 { + return t.histogram.Sum() +} + +// Record the duration of the execution of the given function. +func (t *StandardTimer) Time(f func()) { + ts := time.Now() + f() + t.Update(time.Since(ts)) +} + +// Record the duration of an event. +func (t *StandardTimer) Update(d time.Duration) { + t.mutex.Lock() + defer t.mutex.Unlock() + t.histogram.Update(int64(d)) + t.meter.Mark(1) +} + +// Record the duration of an event that started at a time and ends now. +func (t *StandardTimer) UpdateSince(ts time.Time) { + t.mutex.Lock() + defer t.mutex.Unlock() + t.histogram.Update(int64(time.Since(ts))) + t.meter.Mark(1) +} + +// Variance returns the variance of the values in the sample. +func (t *StandardTimer) Variance() float64 { + return t.histogram.Variance() +} + +// TimerSnapshot is a read-only copy of another Timer. +type TimerSnapshot struct { + histogram *HistogramSnapshot + meter *MeterSnapshot +} + +// Count returns the number of events recorded at the time the snapshot was +// taken. +func (t *TimerSnapshot) Count() int64 { return t.histogram.Count() } + +// Max returns the maximum value at the time the snapshot was taken. +func (t *TimerSnapshot) Max() int64 { return t.histogram.Max() } + +// Mean returns the mean value at the time the snapshot was taken. +func (t *TimerSnapshot) Mean() float64 { return t.histogram.Mean() } + +// Min returns the minimum value at the time the snapshot was taken. +func (t *TimerSnapshot) Min() int64 { return t.histogram.Min() } + +// Percentile returns an arbitrary percentile of sampled values at the time the +// snapshot was taken. +func (t *TimerSnapshot) Percentile(p float64) float64 { + return t.histogram.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of sampled values at +// the time the snapshot was taken. +func (t *TimerSnapshot) Percentiles(ps []float64) []float64 { + return t.histogram.Percentiles(ps) +} + +// Rate1 returns the one-minute moving average rate of events per second at the +// time the snapshot was taken. +func (t *TimerSnapshot) Rate1() float64 { return t.meter.Rate1() } + +// Rate5 returns the five-minute moving average rate of events per second at +// the time the snapshot was taken. +func (t *TimerSnapshot) Rate5() float64 { return t.meter.Rate5() } + +// Rate15 returns the fifteen-minute moving average rate of events per second +// at the time the snapshot was taken. +func (t *TimerSnapshot) Rate15() float64 { return t.meter.Rate15() } + +// RateMean returns the meter's mean rate of events per second at the time the +// snapshot was taken. +func (t *TimerSnapshot) RateMean() float64 { return t.meter.RateMean() } + +// Snapshot returns the snapshot. +func (t *TimerSnapshot) Snapshot() Timer { return t } + +// StdDev returns the standard deviation of the values at the time the snapshot +// was taken. +func (t *TimerSnapshot) StdDev() float64 { return t.histogram.StdDev() } + +// Stop is a no-op. +func (t *TimerSnapshot) Stop() {} + +// Sum returns the sum at the time the snapshot was taken. +func (t *TimerSnapshot) Sum() int64 { return t.histogram.Sum() } + +// Time panics. +func (*TimerSnapshot) Time(func()) { + panic("Time called on a TimerSnapshot") +} + +// Update panics. +func (*TimerSnapshot) Update(time.Duration) { + panic("Update called on a TimerSnapshot") +} + +// UpdateSince panics. +func (*TimerSnapshot) UpdateSince(time.Time) { + panic("UpdateSince called on a TimerSnapshot") +} + +// Variance returns the variance of the values at the time the snapshot was +// taken. +func (t *TimerSnapshot) Variance() float64 { return t.histogram.Variance() } diff --git a/github.com/rcrowley/go-metrics/writer.go b/github.com/rcrowley/go-metrics/writer.go new file mode 100644 index 00000000..091e971d --- /dev/null +++ b/github.com/rcrowley/go-metrics/writer.go @@ -0,0 +1,100 @@ +package metrics + +import ( + "fmt" + "io" + "sort" + "time" +) + +// Write sorts writes each metric in the given registry periodically to the +// given io.Writer. +func Write(r Registry, d time.Duration, w io.Writer) { + for _ = range time.Tick(d) { + WriteOnce(r, w) + } +} + +// WriteOnce sorts and writes metrics in the given registry to the given +// io.Writer. +func WriteOnce(r Registry, w io.Writer) { + var namedMetrics namedMetricSlice + r.Each(func(name string, i interface{}) { + namedMetrics = append(namedMetrics, namedMetric{name, i}) + }) + + sort.Sort(namedMetrics) + for _, namedMetric := range namedMetrics { + switch metric := namedMetric.m.(type) { + case Counter: + fmt.Fprintf(w, "counter %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", metric.Count()) + case Gauge: + fmt.Fprintf(w, "gauge %s\n", namedMetric.name) + fmt.Fprintf(w, " value: %9d\n", metric.Value()) + case GaugeFloat64: + fmt.Fprintf(w, "gauge %s\n", namedMetric.name) + fmt.Fprintf(w, " value: %f\n", metric.Value()) + case Healthcheck: + metric.Check() + fmt.Fprintf(w, "healthcheck %s\n", namedMetric.name) + fmt.Fprintf(w, " error: %v\n", metric.Error()) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "histogram %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", h.Count()) + fmt.Fprintf(w, " min: %9d\n", h.Min()) + fmt.Fprintf(w, " max: %9d\n", h.Max()) + fmt.Fprintf(w, " mean: %12.2f\n", h.Mean()) + fmt.Fprintf(w, " stddev: %12.2f\n", h.StdDev()) + fmt.Fprintf(w, " median: %12.2f\n", ps[0]) + fmt.Fprintf(w, " 75%%: %12.2f\n", ps[1]) + fmt.Fprintf(w, " 95%%: %12.2f\n", ps[2]) + fmt.Fprintf(w, " 99%%: %12.2f\n", ps[3]) + fmt.Fprintf(w, " 99.9%%: %12.2f\n", ps[4]) + case Meter: + m := metric.Snapshot() + fmt.Fprintf(w, "meter %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", m.Count()) + fmt.Fprintf(w, " 1-min rate: %12.2f\n", m.Rate1()) + fmt.Fprintf(w, " 5-min rate: %12.2f\n", m.Rate5()) + fmt.Fprintf(w, " 15-min rate: %12.2f\n", m.Rate15()) + fmt.Fprintf(w, " mean rate: %12.2f\n", m.RateMean()) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "timer %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", t.Count()) + fmt.Fprintf(w, " min: %9d\n", t.Min()) + fmt.Fprintf(w, " max: %9d\n", t.Max()) + fmt.Fprintf(w, " mean: %12.2f\n", t.Mean()) + fmt.Fprintf(w, " stddev: %12.2f\n", t.StdDev()) + fmt.Fprintf(w, " median: %12.2f\n", ps[0]) + fmt.Fprintf(w, " 75%%: %12.2f\n", ps[1]) + fmt.Fprintf(w, " 95%%: %12.2f\n", ps[2]) + fmt.Fprintf(w, " 99%%: %12.2f\n", ps[3]) + fmt.Fprintf(w, " 99.9%%: %12.2f\n", ps[4]) + fmt.Fprintf(w, " 1-min rate: %12.2f\n", t.Rate1()) + fmt.Fprintf(w, " 5-min rate: %12.2f\n", t.Rate5()) + fmt.Fprintf(w, " 15-min rate: %12.2f\n", t.Rate15()) + fmt.Fprintf(w, " mean rate: %12.2f\n", t.RateMean()) + } + } +} + +type namedMetric struct { + name string + m interface{} +} + +// namedMetricSlice is a slice of namedMetrics that implements sort.Interface. +type namedMetricSlice []namedMetric + +func (nms namedMetricSlice) Len() int { return len(nms) } + +func (nms namedMetricSlice) Swap(i, j int) { nms[i], nms[j] = nms[j], nms[i] } + +func (nms namedMetricSlice) Less(i, j int) bool { + return nms[i].name < nms[j].name +} diff --git a/github.com/sirupsen/logrus/entry.go b/github.com/sirupsen/logrus/entry.go index 1fad45e0..778f4c9f 100644 --- a/github.com/sirupsen/logrus/entry.go +++ b/github.com/sirupsen/logrus/entry.go @@ -94,38 +94,47 @@ func (entry Entry) log(level Level, msg string) { entry.Level = level entry.Message = msg - entry.Logger.mu.Lock() - err := entry.Logger.Hooks.Fire(level, &entry) - entry.Logger.mu.Unlock() - if err != nil { - entry.Logger.mu.Lock() - fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) - entry.Logger.mu.Unlock() - } + entry.fireHooks() + buffer = bufferPool.Get().(*bytes.Buffer) buffer.Reset() defer bufferPool.Put(buffer) entry.Buffer = buffer - serialized, err := entry.Logger.Formatter.Format(&entry) + + entry.write() + entry.Buffer = nil + + // To avoid Entry#log() returning a value that only would make sense for + // panic() to use in Entry#Panic(), we avoid the allocation by checking + // directly here. + if level <= PanicLevel { + panic(&entry) + } +} + +// This function is not declared with a pointer value because otherwise +// race conditions will occur when using multiple goroutines +func (entry Entry) fireHooks() { + entry.Logger.mu.Lock() + defer entry.Logger.mu.Unlock() + err := entry.Logger.Hooks.Fire(entry.Level, &entry) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) + } +} + +func (entry *Entry) write() { + serialized, err := entry.Logger.Formatter.Format(entry) + entry.Logger.mu.Lock() + defer entry.Logger.mu.Unlock() if err != nil { - entry.Logger.mu.Lock() fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) - entry.Logger.mu.Unlock() } else { - entry.Logger.mu.Lock() _, err = entry.Logger.Out.Write(serialized) if err != nil { fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) } - entry.Logger.mu.Unlock() - } - - // To avoid Entry#log() returning a value that only would make sense for - // panic() to use in Entry#Panic(), we avoid the allocation by checking - // directly here. - if level <= PanicLevel { - panic(&entry) } } diff --git a/github.com/sirupsen/logrus/terminal_bsd.go b/github.com/sirupsen/logrus/terminal_bsd.go index d7b3893f..4880d13d 100644 --- a/github.com/sirupsen/logrus/terminal_bsd.go +++ b/github.com/sirupsen/logrus/terminal_bsd.go @@ -1,5 +1,5 @@ // +build darwin freebsd openbsd netbsd dragonfly -// +build !appengine +// +build !appengine,!gopherjs package logrus diff --git a/github.com/sirupsen/logrus/terminal_check_appengine.go b/github.com/sirupsen/logrus/terminal_check_appengine.go index 2403de98..3de08e80 100644 --- a/github.com/sirupsen/logrus/terminal_check_appengine.go +++ b/github.com/sirupsen/logrus/terminal_check_appengine.go @@ -1,4 +1,4 @@ -// +build appengine +// +build appengine gopherjs package logrus diff --git a/github.com/sirupsen/logrus/terminal_check_notappengine.go b/github.com/sirupsen/logrus/terminal_check_notappengine.go index 116bcb4e..067047a1 100644 --- a/github.com/sirupsen/logrus/terminal_check_notappengine.go +++ b/github.com/sirupsen/logrus/terminal_check_notappengine.go @@ -1,4 +1,4 @@ -// +build !appengine +// +build !appengine,!gopherjs package logrus diff --git a/github.com/sirupsen/logrus/terminal_linux.go b/github.com/sirupsen/logrus/terminal_linux.go index 88d7298e..f29a0097 100644 --- a/github.com/sirupsen/logrus/terminal_linux.go +++ b/github.com/sirupsen/logrus/terminal_linux.go @@ -3,7 +3,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !appengine +// +build !appengine,!gopherjs package logrus diff --git a/github.com/spf13/cobra/args.go b/github.com/spf13/cobra/args.go index 94a6ca27..a5d8a927 100644 --- a/github.com/spf13/cobra/args.go +++ b/github.com/spf13/cobra/args.go @@ -16,14 +16,14 @@ func legacyArgs(cmd *Command, args []string) error { return nil } - // root command with subcommands, do subcommand checking + // root command with subcommands, do subcommand checking. if !cmd.HasParent() && len(args) > 0 { return fmt.Errorf("unknown command %q for %q%s", args[0], cmd.CommandPath(), cmd.findSuggestions(args[0])) } return nil } -// NoArgs returns an error if any args are included +// NoArgs returns an error if any args are included. func NoArgs(cmd *Command, args []string) error { if len(args) > 0 { return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath()) @@ -31,7 +31,7 @@ func NoArgs(cmd *Command, args []string) error { return nil } -// OnlyValidArgs returns an error if any args are not in the list of ValidArgs +// OnlyValidArgs returns an error if any args are not in the list of ValidArgs. func OnlyValidArgs(cmd *Command, args []string) error { if len(cmd.ValidArgs) > 0 { for _, v := range args { @@ -43,21 +43,12 @@ func OnlyValidArgs(cmd *Command, args []string) error { return nil } -func stringInSlice(a string, list []string) bool { - for _, b := range list { - if b == a { - return true - } - } - return false -} - -// ArbitraryArgs never returns an error +// ArbitraryArgs never returns an error. func ArbitraryArgs(cmd *Command, args []string) error { return nil } -// MinimumNArgs returns an error if there is not at least N args +// MinimumNArgs returns an error if there is not at least N args. func MinimumNArgs(n int) PositionalArgs { return func(cmd *Command, args []string) error { if len(args) < n { @@ -67,7 +58,7 @@ func MinimumNArgs(n int) PositionalArgs { } } -// MaximumNArgs returns an error if there are more than N args +// MaximumNArgs returns an error if there are more than N args. func MaximumNArgs(n int) PositionalArgs { return func(cmd *Command, args []string) error { if len(args) > n { @@ -77,7 +68,7 @@ func MaximumNArgs(n int) PositionalArgs { } } -// ExactArgs returns an error if there are not exactly n args +// ExactArgs returns an error if there are not exactly n args. func ExactArgs(n int) PositionalArgs { return func(cmd *Command, args []string) error { if len(args) != n { @@ -87,7 +78,7 @@ func ExactArgs(n int) PositionalArgs { } } -// RangeArgs returns an error if the number of args is not within the expected range +// RangeArgs returns an error if the number of args is not within the expected range. func RangeArgs(min int, max int) PositionalArgs { return func(cmd *Command, args []string) error { if len(args) < min || len(args) > max { diff --git a/github.com/spf13/cobra/bash_completions.go b/github.com/spf13/cobra/bash_completions.go index c19fe7a0..291eae7d 100644 --- a/github.com/spf13/cobra/bash_completions.go +++ b/github.com/spf13/cobra/bash_completions.go @@ -21,8 +21,8 @@ const ( func writePreamble(buf *bytes.Buffer, name string) { buf.WriteString(fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name)) - buf.WriteString(` -__debug() + buf.WriteString(fmt.Sprintf(` +__%[1]s_debug() { if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then echo "$*" >> "${BASH_COMP_DEBUG_FILE}" @@ -31,13 +31,13 @@ __debug() # Homebrew on Macs have version 1.3 of bash-completion which doesn't include # _init_completion. This is a very minimal version of that function. -__my_init_completion() +__%[1]s_init_completion() { COMPREPLY=() _get_comp_words_by_ref "$@" cur prev words cword } -__index_of_word() +__%[1]s_index_of_word() { local w word=$1 shift @@ -49,7 +49,7 @@ __index_of_word() index=-1 } -__contains_word() +__%[1]s_contains_word() { local w word=$1; shift for w in "$@"; do @@ -58,9 +58,9 @@ __contains_word() return 1 } -__handle_reply() +__%[1]s_handle_reply() { - __debug "${FUNCNAME[0]}" + __%[1]s_debug "${FUNCNAME[0]}" case $cur in -*) if [[ $(type -t compopt) = "builtin" ]]; then @@ -85,7 +85,7 @@ __handle_reply() local index flag flag="${cur%%=*}" - __index_of_word "${flag}" "${flags_with_completion[@]}" + __%[1]s_index_of_word "${flag}" "${flags_with_completion[@]}" COMPREPLY=() if [[ ${index} -ge 0 ]]; then PREFIX="" @@ -103,7 +103,7 @@ __handle_reply() # check if we are handling a flag with special work handling local index - __index_of_word "${prev}" "${flags_with_completion[@]}" + __%[1]s_index_of_word "${prev}" "${flags_with_completion[@]}" if [[ ${index} -ge 0 ]]; then ${flags_completion[${index}]} return @@ -136,24 +136,30 @@ __handle_reply() if declare -F __ltrim_colon_completions >/dev/null; then __ltrim_colon_completions "$cur" fi + + # If there is only 1 completion and it is a flag with an = it will be completed + # but we don't want a space after the = + if [[ "${#COMPREPLY[@]}" -eq "1" ]] && [[ $(type -t compopt) = "builtin" ]] && [[ "${COMPREPLY[0]}" == --*= ]]; then + compopt -o nospace + fi } # The arguments should be in the form "ext1|ext2|extn" -__handle_filename_extension_flag() +__%[1]s_handle_filename_extension_flag() { local ext="$1" _filedir "@(${ext})" } -__handle_subdirs_in_dir_flag() +__%[1]s_handle_subdirs_in_dir_flag() { local dir="$1" pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 } -__handle_flag() +__%[1]s_handle_flag() { - __debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" # if a command required a flag, and we found it, unset must_have_one_flag() local flagname=${words[c]} @@ -164,27 +170,30 @@ __handle_flag() flagname=${flagname%%=*} # strip everything after the = flagname="${flagname}=" # but put the = back fi - __debug "${FUNCNAME[0]}: looking for ${flagname}" - if __contains_word "${flagname}" "${must_have_one_flag[@]}"; then + __%[1]s_debug "${FUNCNAME[0]}: looking for ${flagname}" + if __%[1]s_contains_word "${flagname}" "${must_have_one_flag[@]}"; then must_have_one_flag=() fi # if you set a flag which only applies to this command, don't show subcommands - if __contains_word "${flagname}" "${local_nonpersistent_flags[@]}"; then + if __%[1]s_contains_word "${flagname}" "${local_nonpersistent_flags[@]}"; then commands=() fi # keep flag value with flagname as flaghash - if [ -n "${flagvalue}" ] ; then - flaghash[${flagname}]=${flagvalue} - elif [ -n "${words[ $((c+1)) ]}" ] ; then - flaghash[${flagname}]=${words[ $((c+1)) ]} - else - flaghash[${flagname}]="true" # pad "true" for bool flag + # flaghash variable is an associative array which is only supported in bash > 3. + if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then + if [ -n "${flagvalue}" ] ; then + flaghash[${flagname}]=${flagvalue} + elif [ -n "${words[ $((c+1)) ]}" ] ; then + flaghash[${flagname}]=${words[ $((c+1)) ]} + else + flaghash[${flagname}]="true" # pad "true" for bool flag + fi fi # skip the argument to a two word flag - if __contains_word "${words[c]}" "${two_word_flags[@]}"; then + if __%[1]s_contains_word "${words[c]}" "${two_word_flags[@]}"; then c=$((c+1)) # if we are looking for a flags value, don't show commands if [[ $c -eq $cword ]]; then @@ -196,13 +205,13 @@ __handle_flag() } -__handle_noun() +__%[1]s_handle_noun() { - __debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" - if __contains_word "${words[c]}" "${must_have_one_noun[@]}"; then + if __%[1]s_contains_word "${words[c]}" "${must_have_one_noun[@]}"; then must_have_one_noun=() - elif __contains_word "${words[c]}" "${noun_aliases[@]}"; then + elif __%[1]s_contains_word "${words[c]}" "${noun_aliases[@]}"; then must_have_one_noun=() fi @@ -210,45 +219,45 @@ __handle_noun() c=$((c+1)) } -__handle_command() +__%[1]s_handle_command() { - __debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" local next_command if [[ -n ${last_command} ]]; then next_command="_${last_command}_${words[c]//:/__}" else if [[ $c -eq 0 ]]; then - next_command="_$(basename "${words[c]//:/__}")" + next_command="_%[1]s_root_command" else next_command="_${words[c]//:/__}" fi fi c=$((c+1)) - __debug "${FUNCNAME[0]}: looking for ${next_command}" + __%[1]s_debug "${FUNCNAME[0]}: looking for ${next_command}" declare -F "$next_command" >/dev/null && $next_command } -__handle_word() +__%[1]s_handle_word() { if [[ $c -ge $cword ]]; then - __handle_reply + __%[1]s_handle_reply return fi - __debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" if [[ "${words[c]}" == -* ]]; then - __handle_flag - elif __contains_word "${words[c]}" "${commands[@]}"; then - __handle_command - elif [[ $c -eq 0 ]] && __contains_word "$(basename "${words[c]}")" "${commands[@]}"; then - __handle_command + __%[1]s_handle_flag + elif __%[1]s_contains_word "${words[c]}" "${commands[@]}"; then + __%[1]s_handle_command + elif [[ $c -eq 0 ]]; then + __%[1]s_handle_command else - __handle_noun + __%[1]s_handle_noun fi - __handle_word + __%[1]s_handle_word } -`) +`, name)) } func writePostscript(buf *bytes.Buffer, name string) { @@ -260,7 +269,7 @@ func writePostscript(buf *bytes.Buffer, name string) { if declare -F _init_completion >/dev/null 2>&1; then _init_completion -s || return else - __my_init_completion -n "=" || return + __%[1]s_init_completion -n "=" || return fi local c=0 @@ -269,13 +278,13 @@ func writePostscript(buf *bytes.Buffer, name string) { local local_nonpersistent_flags=() local flags_with_completion=() local flags_completion=() - local commands=("%s") + local commands=("%[1]s") local must_have_one_flag=() local must_have_one_noun=() local last_command local nouns=() - __handle_word + __%[1]s_handle_word } `, name)) @@ -300,7 +309,7 @@ func writeCommands(buf *bytes.Buffer, cmd *Command) { buf.WriteString("\n") } -func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]string) { +func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]string, cmd *Command) { for key, value := range annotations { switch key { case BashCompFilenameExt: @@ -308,7 +317,7 @@ func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]s var ext string if len(value) > 0 { - ext = "__handle_filename_extension_flag " + strings.Join(value, "|") + ext = fmt.Sprintf("__%s_handle_filename_extension_flag ", cmd.Root().Name()) + strings.Join(value, "|") } else { ext = "_filedir" } @@ -326,7 +335,7 @@ func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]s var ext string if len(value) == 1 { - ext = "__handle_subdirs_in_dir_flag " + value[0] + ext = fmt.Sprintf("__%s_handle_subdirs_in_dir_flag ", cmd.Root().Name()) + value[0] } else { ext = "_filedir -d" } @@ -335,7 +344,7 @@ func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]s } } -func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag) { +func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag, cmd *Command) { name := flag.Shorthand format := " " if len(flag.NoOptDefVal) == 0 { @@ -343,10 +352,10 @@ func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag) { } format += "flags+=(\"-%s\")\n" buf.WriteString(fmt.Sprintf(format, name)) - writeFlagHandler(buf, "-"+name, flag.Annotations) + writeFlagHandler(buf, "-"+name, flag.Annotations, cmd) } -func writeFlag(buf *bytes.Buffer, flag *pflag.Flag) { +func writeFlag(buf *bytes.Buffer, flag *pflag.Flag, cmd *Command) { name := flag.Name format := " flags+=(\"--%s" if len(flag.NoOptDefVal) == 0 { @@ -354,7 +363,7 @@ func writeFlag(buf *bytes.Buffer, flag *pflag.Flag) { } format += "\")\n" buf.WriteString(fmt.Sprintf(format, name)) - writeFlagHandler(buf, "--"+name, flag.Annotations) + writeFlagHandler(buf, "--"+name, flag.Annotations, cmd) } func writeLocalNonPersistentFlag(buf *bytes.Buffer, flag *pflag.Flag) { @@ -380,9 +389,9 @@ func writeFlags(buf *bytes.Buffer, cmd *Command) { if nonCompletableFlag(flag) { return } - writeFlag(buf, flag) + writeFlag(buf, flag, cmd) if len(flag.Shorthand) > 0 { - writeShortFlag(buf, flag) + writeShortFlag(buf, flag, cmd) } if localNonPersistentFlags.Lookup(flag.Name) != nil { writeLocalNonPersistentFlag(buf, flag) @@ -392,9 +401,9 @@ func writeFlags(buf *bytes.Buffer, cmd *Command) { if nonCompletableFlag(flag) { return } - writeFlag(buf, flag) + writeFlag(buf, flag, cmd) if len(flag.Shorthand) > 0 { - writeShortFlag(buf, flag) + writeShortFlag(buf, flag, cmd) } }) @@ -452,7 +461,13 @@ func gen(buf *bytes.Buffer, cmd *Command) { commandName := cmd.CommandPath() commandName = strings.Replace(commandName, " ", "_", -1) commandName = strings.Replace(commandName, ":", "__", -1) - buf.WriteString(fmt.Sprintf("_%s()\n{\n", commandName)) + + if cmd.Root() == cmd { + buf.WriteString(fmt.Sprintf("_%s_root_command()\n{\n", commandName)) + } else { + buf.WriteString(fmt.Sprintf("_%s()\n{\n", commandName)) + } + buf.WriteString(fmt.Sprintf(" last_command=%q\n", commandName)) writeCommands(buf, cmd) writeFlags(buf, cmd) @@ -491,17 +506,20 @@ func (c *Command) GenBashCompletionFile(filename string) error { return c.GenBashCompletion(outFile) } -// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists. +// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag if it exists, +// and causes your command to report an error if invoked without the flag. func (c *Command) MarkFlagRequired(name string) error { return MarkFlagRequired(c.Flags(), name) } -// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag, if it exists. +// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag if it exists, +// and causes your command to report an error if invoked without the flag. func (c *Command) MarkPersistentFlagRequired(name string) error { return MarkFlagRequired(c.PersistentFlags(), name) } -// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag in the flag set, if it exists. +// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag if it exists, +// and causes your command to report an error if invoked without the flag. func MarkFlagRequired(flags *pflag.FlagSet, name string) error { return flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{"true"}) } diff --git a/github.com/spf13/cobra/cobra.go b/github.com/spf13/cobra/cobra.go index 8928cefc..7010fd15 100644 --- a/github.com/spf13/cobra/cobra.go +++ b/github.com/spf13/cobra/cobra.go @@ -70,7 +70,8 @@ func AddTemplateFuncs(tmplFuncs template.FuncMap) { } } -// OnInitialize takes a series of func() arguments and appends them to a slice of func(). +// OnInitialize sets the passed functions to be run when each command's +// Execute method is called. func OnInitialize(y ...func()) { initializers = append(initializers, y...) } @@ -188,3 +189,12 @@ func ld(s, t string, ignoreCase bool) int { } return d[len(s)][len(t)] } + +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} diff --git a/github.com/spf13/cobra/command.go b/github.com/spf13/cobra/command.go index 58e6ceb0..15b81127 100644 --- a/github.com/spf13/cobra/command.go +++ b/github.com/spf13/cobra/command.go @@ -75,6 +75,11 @@ type Command struct { // group commands. Annotations map[string]string + // Version defines the version for this command. If this value is non-empty and the command does not + // define a "version" flag, a "version" boolean flag will be added to the command and, if specified, + // will print content of the "Version" variable. + Version string + // The *Run functions are executed in the following order: // * PersistentPreRun() // * PreRun() @@ -118,6 +123,10 @@ type Command struct { // will be printed by generating docs for this command. DisableAutoGenTag bool + // DisableFlagsInUseLine will disable the addition of [flags] to the usage + // line of a command when printing help or generating docs + DisableFlagsInUseLine bool + // DisableSuggestions disables the suggestions based on Levenshtein distance // that go along with 'unknown command' messages. DisableSuggestions bool @@ -138,6 +147,11 @@ type Command struct { commandsMaxNameLen int // commandsAreSorted defines, if command slice are sorted or not. commandsAreSorted bool + // commandCalledAs is the name or alias value used to call this command. + commandCalledAs struct { + name string + called bool + } // args is actual args parsed from flags. args []string @@ -173,6 +187,8 @@ type Command struct { // helpCommand is command with usage 'help'. If it's not defined by user, // cobra uses default help command. helpCommand *Command + // versionTemplate is the version template defined by user. + versionTemplate string } // SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden @@ -218,6 +234,11 @@ func (c *Command) SetHelpTemplate(s string) { c.helpTemplate = s } +// SetVersionTemplate sets version template to be used. Application can use it to set custom template. +func (c *Command) SetVersionTemplate(s string) { + c.versionTemplate = s +} + // SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands. // The user should not have a cyclic dependency on commands. func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) { @@ -407,6 +428,19 @@ func (c *Command) HelpTemplate() string { {{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}` } +// VersionTemplate return version template for the command. +func (c *Command) VersionTemplate() string { + if c.versionTemplate != "" { + return c.versionTemplate + } + + if c.HasParent() { + return c.parent.VersionTemplate() + } + return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}} +` +} + func hasNoOptDefVal(name string, fs *flag.FlagSet) bool { flag := fs.Lookup(name) if flag == nil { @@ -441,6 +475,9 @@ Loop: s := args[0] args = args[1:] switch { + case s == "--": + // "--" terminates the flags + break Loop case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags): // If '--flag arg' then // delete arg from args. @@ -528,6 +565,7 @@ func (c *Command) findNext(next string) *Command { matches := make([]*Command, 0) for _, cmd := range c.commands { if cmd.Name() == next || cmd.HasAlias(next) { + cmd.commandCalledAs.name = next return cmd } if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) { @@ -538,6 +576,7 @@ func (c *Command) findNext(next string) *Command { if len(matches) == 1 { return matches[0] } + return nil } @@ -621,10 +660,8 @@ func (c *Command) Root() *Command { return c } -// ArgsLenAtDash will return the length of f.Args at the moment when a -- was -// found during arg parsing. This allows your program to know which args were -// before the -- and which came after. (Description from -// https://godoc.org/github.com/spf13/pflag#FlagSet.ArgsLenAtDash). +// ArgsLenAtDash will return the length of c.Flags().Args at the moment +// when a -- was found during args parsing. func (c *Command) ArgsLenAtDash() int { return c.Flags().ArgsLenAtDash() } @@ -638,9 +675,10 @@ func (c *Command) execute(a []string) (err error) { c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated) } - // initialize help flag as the last point possible to allow for user + // initialize help and version flag at the last point possible to allow for user // overriding c.InitDefaultHelpFlag() + c.InitDefaultVersionFlag() err = c.ParseFlags(a) if err != nil { @@ -657,7 +695,27 @@ func (c *Command) execute(a []string) (err error) { return err } - if helpVal || !c.Runnable() { + if helpVal { + return flag.ErrHelp + } + + // for back-compat, only add version flag behavior if version is defined + if c.Version != "" { + versionVal, err := c.Flags().GetBool("version") + if err != nil { + c.Println("\"version\" flag declared as non-bool. Please correct your code") + return err + } + if versionVal { + err := tmpl(c.OutOrStdout(), c.VersionTemplate(), c) + if err != nil { + c.Println(err) + } + return err + } + } + + if !c.Runnable() { return flag.ErrHelp } @@ -780,6 +838,11 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { return c, err } + cmd.commandCalledAs.called = true + if cmd.commandCalledAs.name == "" { + cmd.commandCalledAs.name = cmd.Name() + } + err = cmd.execute(flags) if err != nil { // Always show help if requested, even if SilenceErrors is in @@ -825,7 +888,7 @@ func (c *Command) validateRequiredFlags() error { }) if len(missingFlagNames) > 0 { - return fmt.Errorf(`Required flag(s) "%s" have/has not been set`, strings.Join(missingFlagNames, `", "`)) + return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missingFlagNames, `", "`)) } return nil } @@ -846,6 +909,27 @@ func (c *Command) InitDefaultHelpFlag() { } } +// InitDefaultVersionFlag adds default version flag to c. +// It is called automatically by executing the c. +// If c already has a version flag, it will do nothing. +// If c.Version is empty, it will do nothing. +func (c *Command) InitDefaultVersionFlag() { + if c.Version == "" { + return + } + + c.mergePersistentFlags() + if c.Flags().Lookup("version") == nil { + usage := "version for " + if c.Name() == "" { + usage += "this command" + } else { + usage += c.Name() + } + c.Flags().Bool("version", false, usage) + } +} + // InitDefaultHelpCmd adds default help command to c. // It is called automatically by executing the c or by calling help and usage. // If c already has help command or c has no subcommands, it will do nothing. @@ -877,7 +961,7 @@ Simply type ` + c.Name() + ` help [path to command] for full details.`, c.AddCommand(c.helpCommand) } -// ResetCommands used for testing. +// ResetCommands delete parent, subcommand and help command from c. func (c *Command) ResetCommands() { c.parent = nil c.commands = nil @@ -996,6 +1080,9 @@ func (c *Command) UseLine() string { } else { useline = c.Use } + if c.DisableFlagsInUseLine { + return useline + } if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") { useline += " [flags]" } @@ -1063,14 +1150,25 @@ func (c *Command) HasAlias(s string) bool { return false } +// CalledAs returns the command name or alias that was used to invoke +// this command or an empty string if the command has not been called. +func (c *Command) CalledAs() string { + if c.commandCalledAs.called { + return c.commandCalledAs.name + } + return "" +} + // hasNameOrAliasPrefix returns true if the Name or any of aliases start // with prefix func (c *Command) hasNameOrAliasPrefix(prefix string) bool { if strings.HasPrefix(c.Name(), prefix) { + c.commandCalledAs.name = c.Name() return true } for _, alias := range c.Aliases { if strings.HasPrefix(alias, prefix) { + c.commandCalledAs.name = alias return true } } @@ -1163,7 +1261,7 @@ func (c *Command) HasAvailableSubCommands() bool { } } - // the command either has no sub comamnds, or no available (non deprecated/help/hidden) + // the command either has no sub commands, or no available (non deprecated/help/hidden) // sub commands return false } @@ -1173,7 +1271,7 @@ func (c *Command) HasParent() bool { return c.parent != nil } -// GlobalNormalizationFunc returns the global normalization function or nil if doesn't exists. +// GlobalNormalizationFunc returns the global normalization function or nil if it doesn't exist. func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName { return c.globNormFunc } @@ -1273,7 +1371,7 @@ func (c *Command) PersistentFlags() *flag.FlagSet { return c.pflags } -// ResetFlags is used in testing. +// ResetFlags deletes all flags from command. func (c *Command) ResetFlags() { c.flagErrorBuf = new(bytes.Buffer) c.flagErrorBuf.Reset() diff --git a/github.com/spf13/cobra/doc/md_docs.go b/github.com/spf13/cobra/doc/md_docs.go index 68cf5bf6..d7a2c2b6 100644 --- a/github.com/spf13/cobra/doc/md_docs.go +++ b/github.com/spf13/cobra/doc/md_docs.go @@ -67,7 +67,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) buf.WriteString("## " + name + "\n\n") buf.WriteString(short + "\n\n") buf.WriteString("### Synopsis\n\n") - buf.WriteString("\n" + long + "\n\n") + buf.WriteString(long + "\n\n") if cmd.Runnable() { buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine())) @@ -82,7 +82,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) return err } if hasSeeAlso(cmd) { - buf.WriteString("### SEE ALSO\n") + buf.WriteString("### SEE ALSO\n\n") if cmd.HasParent() { parent := cmd.Parent() pname := parent.CommandPath() diff --git a/github.com/uber/jaeger-client-go/constants.go b/github.com/uber/jaeger-client-go/constants.go index 1f00d1c0..ff931269 100644 --- a/github.com/uber/jaeger-client-go/constants.go +++ b/github.com/uber/jaeger-client-go/constants.go @@ -16,7 +16,7 @@ package jaeger const ( // JaegerClientVersion is the version of the client library reported as Span tag. - JaegerClientVersion = "Go-2.11.2" + JaegerClientVersion = "Go-2.12.0" // JaegerClientVersionTagKey is the name of the tag used to report client version. JaegerClientVersionTagKey = "jaeger.version" diff --git a/github.com/uber/jaeger-client-go/internal/throttler/throttler.go b/github.com/uber/jaeger-client-go/internal/throttler/throttler.go new file mode 100644 index 00000000..196ed69c --- /dev/null +++ b/github.com/uber/jaeger-client-go/internal/throttler/throttler.go @@ -0,0 +1,32 @@ +// Copyright (c) 2018 The Jaeger 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 throttler + +// Throttler is used to rate limits operations. For example, given how debug spans +// are always sampled, a throttler can be enabled per client to rate limit the amount +// of debug spans a client can start. +type Throttler interface { + // IsAllowed determines whether the operation should be allowed and not be + // throttled. + IsAllowed(operation string) bool +} + +// DefaultThrottler doesn't throttle at all. +type DefaultThrottler struct{} + +// IsAllowed implements Throttler#IsAllowed. +func (t DefaultThrottler) IsAllowed(operation string) bool { + return true +} diff --git a/github.com/uber/jaeger-client-go/log/logger.go b/github.com/uber/jaeger-client-go/log/logger.go index b002cda5..894bb3db 100644 --- a/github.com/uber/jaeger-client-go/log/logger.go +++ b/github.com/uber/jaeger-client-go/log/logger.go @@ -47,7 +47,7 @@ func (l *stdLogger) Infof(msg string, args ...interface{}) { log.Printf(msg, args...) } -// NullLogger is implementation of the Logger interface that delegates to default `log` package +// NullLogger is implementation of the Logger interface that is no-op var NullLogger = &nullLogger{} type nullLogger struct{} @@ -81,3 +81,10 @@ func (l *BytesBufferLogger) String() string { defer l.mux.Unlock() return l.buf.String() } + +// Flush empties the underlying buffer. +func (l *BytesBufferLogger) Flush() { + l.mux.Lock() + defer l.mux.Unlock() + l.buf.Reset() +} diff --git a/github.com/uber/jaeger-client-go/process.go b/github.com/uber/jaeger-client-go/process.go new file mode 100644 index 00000000..30cbf996 --- /dev/null +++ b/github.com/uber/jaeger-client-go/process.go @@ -0,0 +1,29 @@ +// Copyright (c) 2018 The Jaeger 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 jaeger + +// Process holds process specific metadata that's relevant to this client. +type Process struct { + Service string + UUID string + Tags []Tag +} + +// ProcessSetter sets a process. This can be used by any class that requires +// the process to be set as part of initialization. +// See internal/throttler/remote/throttler.go for an example. +type ProcessSetter interface { + SetProcess(process Process) +} diff --git a/github.com/uber/jaeger-client-go/span.go b/github.com/uber/jaeger-client-go/span.go index 132fb721..17f7f35c 100644 --- a/github.com/uber/jaeger-client-go/span.go +++ b/github.com/uber/jaeger-client-go/span.go @@ -202,6 +202,8 @@ func (s *Span) FinishWithOptions(options opentracing.FinishOptions) { // Context implements opentracing.Span API func (s *Span) Context() opentracing.SpanContext { + s.Lock() + defer s.Unlock() return s.context } diff --git a/github.com/uber/jaeger-client-go/tracer.go b/github.com/uber/jaeger-client-go/tracer.go index 49fb099e..58d5eaf8 100644 --- a/github.com/uber/jaeger-client-go/tracer.go +++ b/github.com/uber/jaeger-client-go/tracer.go @@ -26,6 +26,7 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/uber/jaeger-client-go/internal/baggage" + "github.com/uber/jaeger-client-go/internal/throttler" "github.com/uber/jaeger-client-go/log" "github.com/uber/jaeger-client-go/utils" ) @@ -58,10 +59,13 @@ type Tracer struct { observer compositeObserver - tags []Tag + tags []Tag + process Process baggageRestrictionManager baggage.RestrictionManager baggageSetter *baggageSetter + + debugThrottler throttler.Throttler } // NewTracer creates Tracer implementation that reports tracing to Jaeger. @@ -111,6 +115,9 @@ func NewTracer( } else { t.baggageSetter = newBaggageSetter(baggage.NewDefaultRestrictionManager(0), &t.metrics) } + if t.debugThrottler == nil { + t.debugThrottler = throttler.DefaultThrottler{} + } if t.randomNumber == nil { rng := utils.NewRand(time.Now().UnixNano()) t.randomNumber = func() uint64 { @@ -143,6 +150,14 @@ func NewTracer( t.logger.Error("Overriding high trace ID generator but not generating " + "128 bit trace IDs, consider enabling the \"Gen128Bit\" option") } + t.process = Process{ + UUID: "PLACEHOLDER", // TODO + Service: serviceName, + Tags: t.tags, + } + if throttler, ok := t.debugThrottler.(ProcessSetter); ok { + throttler.SetProcess(t.process) + } return t, t } @@ -294,6 +309,9 @@ func (t *Tracer) Close() error { if mgr, ok := t.baggageRestrictionManager.(io.Closer); ok { mgr.Close() } + if throttler, ok := t.debugThrottler.(io.Closer); ok { + throttler.Close() + } return nil } @@ -390,7 +408,7 @@ func (t *Tracer) randomID() uint64 { return val } -// (NB) span should hold the lock before making this call +// (NB) span must hold the lock before making this call func (t *Tracer) setBaggage(sp *Span, key, value string) { t.baggageSetter.setBaggage(sp, key, value) } diff --git a/github.com/uber/jaeger-client-go/tracer_options.go b/github.com/uber/jaeger-client-go/tracer_options.go index 72edf6db..389d676d 100644 --- a/github.com/uber/jaeger-client-go/tracer_options.go +++ b/github.com/uber/jaeger-client-go/tracer_options.go @@ -20,6 +20,7 @@ import ( "github.com/opentracing/opentracing-go" "github.com/uber/jaeger-client-go/internal/baggage" + "github.com/uber/jaeger-client-go/internal/throttler" ) // TracerOption is a function that sets some option on the tracer @@ -144,3 +145,9 @@ func (tracerOptions) BaggageRestrictionManager(mgr baggage.RestrictionManager) T tracer.baggageRestrictionManager = mgr } } + +func (tracerOptions) DebugThrottler(throttler throttler.Throttler) TracerOption { + return func(tracer *Tracer) { + tracer.debugThrottler = throttler + } +} diff --git a/github.com/yashtewari/glob-intersection/LICENSE b/github.com/yashtewari/glob-intersection/LICENSE new file mode 100644 index 00000000..8dada3ed --- /dev/null +++ b/github.com/yashtewari/glob-intersection/LICENSE @@ -0,0 +1,201 @@ + 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/github.com/yashtewari/glob-intersection/glob.go b/github.com/yashtewari/glob-intersection/glob.go new file mode 100644 index 00000000..54d4729b --- /dev/null +++ b/github.com/yashtewari/glob-intersection/glob.go @@ -0,0 +1,182 @@ +// Package gintersect provides methods to check whether the intersection of several globs matches a non-empty set of strings. +package gintersect + +import ( + "fmt" + "strings" +) + +// Glob represents a glob. +type Glob []Token + +// NewGlob constructs a Glob from the given string by tokenizing and then simplifying it, or reports errors if any. +func NewGlob(input string) (Glob, error) { + tokens, err := Tokenize([]rune(input)) + if err != nil { + return nil, err + } + + tokens = Simplify(tokens) + + return Glob(tokens), nil +} + +// TokenType is the type of a Token. +type TokenType uint + +const ( + TTCharacter TokenType = iota + TTDot + TTSet +) + +// Flag applies to a token. +type Flag uint + +func (f Flag) String() (s string) { + for r, flag := range flagRunes { + if f == flag { + s = string(r) + break + } + } + return +} + +const ( + FlagNone = iota + FlagPlus + FlagStar +) + +// Token is the element that makes up a Glob. +type Token interface { + Type() TokenType + Flag() Flag + SetFlag(Flag) + // Equal describes whether the given Token is exactly equal to this one, barring differences in flags. + Equal(Token) bool + String() string +} + +// token is the base for all structs implementing Token. +type token struct { + ttype TokenType + flag Flag +} + +func (t token) Type() TokenType { + return t.ttype +} + +func (t token) Flag() Flag { + return t.flag +} + +func (t *token) SetFlag(f Flag) { + t.flag = f +} + +// character is a specific rune. It implements Token. +type character struct { + token + r rune +} + +func NewCharacter(r rune) Token { + return &character{ + token: token{ttype: TTCharacter}, + r: r, + } +} + +func (c character) Equal(other Token) bool { + if c.Type() != other.Type() { + return false + } + + o := other.(*character) + return c.Rune() == o.Rune() +} + +func (c character) String() string { + return fmt.Sprintf("{character: %s flag: %s}", string(c.Rune()), c.Flag().String()) +} + +func (c character) Rune() rune { + return c.r +} + +// dot is any character. It implements Token. +type dot struct { + token +} + +func NewDot() Token { + return &dot{ + token: token{ttype: TTDot}, + } +} + +func (d dot) Equal(other Token) bool { + if d.Type() != other.Type() { + return false + } + + return true +} + +func (d dot) String() string { + return fmt.Sprintf("{dot flag: %s}", d.Flag().String()) +} + +// set is a set of characters (similar to regexp character class). +// It implements Token. +type set struct { + token + runes map[rune]bool +} + +func NewSet(runes []rune) Token { + m := map[rune]bool{} + for _, r := range runes { + m[r] = true + } + return &set{ + token: token{ttype: TTSet}, + runes: m, + } +} + +func (s set) Equal(other Token) bool { + if s.Type() != other.Type() { + return false + } + + o := other.(*set) + r1, r2 := s.Runes(), o.Runes() + + if len(r1) != len(r2) { + return false + } + + for k, _ := range r1 { + if _, ok := r2[k]; !ok { + return false + } + } + + return true +} + +func (s set) String() string { + rs := make([]string, 0, 30) + for r, _ := range s.Runes() { + rs = append(rs, string(r)) + } + return fmt.Sprintf("{set: %s flag: %s}", strings.Join(rs, ""), s.Flag().String()) +} + +func (s set) Runes() map[rune]bool { + return s.runes +} diff --git a/github.com/yashtewari/glob-intersection/match.go b/github.com/yashtewari/glob-intersection/match.go new file mode 100644 index 00000000..45a988a8 --- /dev/null +++ b/github.com/yashtewari/glob-intersection/match.go @@ -0,0 +1,91 @@ +package gintersect + +import ( + "github.com/pkg/errors" +) + +var ( + errBadImplementation = errors.New("this logical path is invalid") +) + +// Match implements single-Token matching, ignoring flags. +// Example: [a-d] and [b-e] match, while [a-z] and [0-9] do not. +func Match(t1 Token, t2 Token) bool { + var temp Token + if t1.Type() > t2.Type() { + temp = t1 + t1 = t2 + t2 = temp + } + + switch t1.Type() { + case TTCharacter: + ch := t1.(*character) + + switch t2.Type() { + case TTCharacter: + return matchCharacters(ch, t2.(*character)) + case TTDot: + return matchCharacterDot(ch, t2.(*dot)) + case TTSet: + return matchCharacterSet(ch, t2.(*set)) + default: + panic(errBadImplementation) + } + + case TTDot: + d := t1.(*dot) + + switch t2.Type() { + case TTDot: + return matchDots(d, t2.(*dot)) + case TTSet: + return matchDotSet(d, t2.(*set)) + default: + panic(errBadImplementation) + } + + case TTSet: + switch t2.Type() { + case TTSet: + return matchSets(t1.(*set), t2.(*set)) + default: + panic(errBadImplementation) + } + + default: + panic(errBadImplementation) + + } +} + +func matchCharacters(a *character, b *character) bool { + return a.Rune() == b.Rune() +} + +func matchCharacterDot(a *character, b *dot) bool { + return true +} + +func matchCharacterSet(a *character, b *set) bool { + _, ok := b.Runes()[a.Rune()] + return ok +} + +func matchDots(a *dot, b *dot) bool { + return true +} + +func matchDotSet(a *dot, b *set) bool { + return true +} + +func matchSets(a *set, b *set) bool { + for k, _ := range a.Runes() { + if _, ok := b.Runes()[k]; ok { + return true + } + } + + return false +} diff --git a/github.com/yashtewari/glob-intersection/non_empty.go b/github.com/yashtewari/glob-intersection/non_empty.go new file mode 100644 index 00000000..1238becf --- /dev/null +++ b/github.com/yashtewari/glob-intersection/non_empty.go @@ -0,0 +1,143 @@ +package gintersect + +// NonEmpty is true if the intersection of lhs and rhs matches a non-empty set of non-empty str1ngs. +func NonEmpty(lhs string, rhs string) (bool, error) { + g1, err := NewGlob(lhs) + if err != nil { + return false, err + } + + g2, err := NewGlob(rhs) + if err != nil { + return false, err + } + + var match bool + g1, g2, match = trimGlobs(g1, g2) + if !match { + return false, nil + } + + return intersectNormal(g1, g2), nil +} + +// trimGlobs removes matching prefixes and suffixes from g1, g2, or returns false if prefixes/suffixes don't match. +func trimGlobs(g1, g2 Glob) (Glob, Glob, bool) { + var l1, r1, l2, r2 int + + // Trim from the beginning until a flagged Token or a mismatch is found. + for l1, l2 = 0, 0; l1 < len(g1) && l2 < len(g2) && g1[l1].Flag() == FlagNone && g2[l2].Flag() == FlagNone; l1, l2 = l1+1, l2+1 { + if !Match(g1[l1], g2[l2]) { + return nil, nil, false + } + } + + // Trim from the end until a flagged Token or a mismatch is found. + for r1, r2 = len(g1)-1, len(g2)-1; r1 >= 0 && r1 >= l1 && r2 >= 0 && r2 >= l2 && g1[r1].Flag() == FlagNone && g2[r2].Flag() == FlagNone; r1, r2 = r1-1, r2-1 { + if !Match(g1[r1], g2[r2]) { + return nil, nil, false + } + } + + return g1[l1 : r1+1], g2[l2 : r2+1], true +} + +// All uses of `intersection exists` below mean that the intersection of the globs matches a non-empty set of non-empty strings. + +// intersectNormal accepts two globs and returns a boolean describing whether their intersection exists. +// It traverses g1, g2 while ensuring that their Tokens match. +// If a flagged Token is encountered, flow of control is handed off to intersectSpecial. +func intersectNormal(g1, g2 Glob) bool { + var i, j int + for i, j = 0, 0; i < len(g1) && j < len(g2); i, j = i+1, j+1 { + if g1[i].Flag() == FlagNone && g2[j].Flag() == FlagNone { + if !Match(g1[i], g2[j]) { + return false + } + } else { + return intersectSpecial(g1[i:], g2[j:]) + } + } + + if i == len(g1) && j == len(g2) { + return true + } + + return false +} + +// intersectSpecial accepts two globs such that at least one starts with a flagged Token. +// It returns a boolean describing whether their intersection exists. +// It hands flow of control to intersectPlus or intersectStar correctly. +func intersectSpecial(g1, g2 Glob) bool { + if g1[0].Flag() != FlagNone { // If g1 starts with a Token having a Flag. + switch g1[0].Flag() { + case FlagPlus: + return intersectPlus(g1, g2) + case FlagStar: + return intersectStar(g1, g2) + } + } else { // If g2 starts with a Token having a Flag. + switch g2[0].Flag() { + case FlagPlus: + return intersectPlus(g2, g1) + case FlagStar: + return intersectStar(g2, g1) + } + } + + return false +} + +// intersectPlus accepts two globs such that plussed[0].Flag() == FlagPlus. +// It returns a boolean describing whether their intersection exists. +// It ensures that at least one token in other maches plussed[0], before handing flow of control to intersectSpecial. +func intersectPlus(plussed, other Glob) bool { + if !Match(plussed[0], other[0]) { + return false + } + return intersectStar(plussed, other[1:]) +} + +// intersectStar accepts two globs such that starred[0].Flag() == FlagStar. +// It returns a boolean describing whether their intersection exists. +// It gobbles up Tokens from other until the Tokens remaining in other intersect with starred[1:] +func intersectStar(starred, other Glob) bool { + // starToken, nextToken are the token having FlagStar and the one that follows immediately after, respectively. + var starToken, nextToken Token + + starToken = starred[0] + if len(starred) > 1 { + nextToken = starred[1] + } + + for i, t := range other { + // Start gobbl1ng up tokens in other while they match starToken. + if nextToken != nil && Match(t, nextToken) { + // When a token in other matches the token after starToken, stop gobbl1ng and try to match the two all the way. + allTheWay := intersectNormal(starred[1:], other[i:]) + // If they match all the way, the Globs intersect. + if allTheWay { + return true + } else { + // If they don't match all the way, then the current token from other should still match starToken. + if !Match(t, starToken) { + return false + } + } + } else { + // Only move forward if this token can be gobbled up by starToken. + if !Match(t, starToken) { + return false + } + } + } + + // If there was no token following starToken, and everything from other was gobbled, the Globs intersect. + if nextToken == nil { + return true + } + + // If everything from other was gobbles but there was a nextToken to match, they don't intersect. + return false +} diff --git a/github.com/yashtewari/glob-intersection/simplify.go b/github.com/yashtewari/glob-intersection/simplify.go new file mode 100644 index 00000000..7704fb10 --- /dev/null +++ b/github.com/yashtewari/glob-intersection/simplify.go @@ -0,0 +1,43 @@ +package gintersect + +// Simplify accepts a Token slice and returns a equivalient Token slice that is shorter/simpler. +// The only simplification currently applied is removing redundant flagged Tokens. +// TODO: Remove unflagged Tokens next to equivalen Tokens with FlagPlus. Example: tt+t == t+ +func Simplify(tokens []Token) []Token { + if len(tokens) == 0 { + return tokens + } + simple := make([]Token, 1, len(tokens)) + simple[0] = tokens[0] + + latest := simple[0] + + for i := 1; i < len(tokens); i++ { + handled := false + // Possible simplifications to apply if there is a flag. + if tokens[i].Flag() != FlagNone && latest.Flag() != FlagNone { + // If the token contents are the same, then apply simplification. + if tokens[i].Equal(latest) { + var flag Flag + // FlagPlus takes precedence, because: + // t+t* == t+ + // t*t+ == t+ + if tokens[i].Flag() == FlagPlus || latest.Flag() == FlagPlus { + flag = FlagPlus + } else { + flag = FlagStar + } + + simple[len(simple)-1].SetFlag(flag) + handled = true + } + } + + if !handled { + latest = tokens[i] + simple = append(simple, tokens[i]) + } + } + + return simple +} diff --git a/github.com/yashtewari/glob-intersection/test_samples.go b/github.com/yashtewari/glob-intersection/test_samples.go new file mode 100644 index 00000000..5d2922c7 --- /dev/null +++ b/github.com/yashtewari/glob-intersection/test_samples.go @@ -0,0 +1,84 @@ +package gintersect + +var ( + samplesInitialized = false + + testCharacters map[rune]Token + testCharactersPlus map[rune]Token + testCharactersStar map[rune]Token + + testDot, testDotPlus, testDotStar Token + + testLowerAlphaSet, testLowerAlphaSetPlus, lowerAplhaSetStar Token + testUpperAlphaSet, testUpperAlphaSetPlus, testUpperAlphaSetStar Token + testNumSet, testNumSetPlus, testNumSetStar Token + testSymbolSet, testSymbolSetPlus, testSymbolSetStar Token + + testEmptySet Token +) + +func initializeTestSamples() { + if samplesInitialized { + return + } + + testCharacters, testCharactersPlus, testCharactersStar = make(map[rune]Token), make(map[rune]Token), make(map[rune]Token) + + testDot, testDotPlus, testDotStar = NewDot(), NewDot(), NewDot() + testDotPlus.SetFlag(FlagPlus) + testDotStar.SetFlag(FlagStar) + + var runes []rune + runes = makeRunes('a', 'z') + + testLowerAlphaSet, testLowerAlphaSetPlus, lowerAplhaSetStar = NewSet(runes), NewSet(runes), NewSet(runes) + testLowerAlphaSetPlus.SetFlag(FlagPlus) + lowerAplhaSetStar.SetFlag(FlagStar) + + runes = makeRunes('A', 'Z') + + testUpperAlphaSet, testUpperAlphaSetPlus, testUpperAlphaSetStar = NewSet(runes), NewSet(runes), NewSet(runes) + testUpperAlphaSetPlus.SetFlag(FlagPlus) + testUpperAlphaSetStar.SetFlag(FlagStar) + + runes = makeRunes('0', '9') + + testNumSet, testNumSetPlus, testNumSetStar = NewSet(runes), NewSet(runes), NewSet(runes) + testNumSetPlus.SetFlag(FlagPlus) + testNumSetStar.SetFlag(FlagStar) + + runes = makeRunes('!', '/') + + testSymbolSet, testSymbolSetPlus, testSymbolSetStar = NewSet(runes), NewSet(runes), NewSet(runes) + testSymbolSetPlus.SetFlag(FlagPlus) + testSymbolSetStar.SetFlag(FlagStar) + + testEmptySet = NewSet([]rune{}) + + samplesInitialized = true +} + +func makeRunes(from rune, to rune) []rune { + runes := make([]rune, 0, 30) + for r := from; r <= to; r++ { + runes = append(runes, r) + addToCharacters(r) + } + + return runes +} + +func addToCharacters(r rune) { + var t Token + + t = NewCharacter(r) + testCharacters[r] = t + + t = NewCharacter(r) + t.SetFlag(FlagPlus) + testCharactersPlus[r] = t + + t = NewCharacter(r) + t.SetFlag(FlagStar) + testCharactersStar[r] = t +} diff --git a/github.com/yashtewari/glob-intersection/tokenize.go b/github.com/yashtewari/glob-intersection/tokenize.go new file mode 100644 index 00000000..0b674316 --- /dev/null +++ b/github.com/yashtewari/glob-intersection/tokenize.go @@ -0,0 +1,251 @@ +package gintersect + +import ( + "fmt" + + "github.com/pkg/errors" +) + +// Modifier is a special character that affects lexical analysis. +type Modifier uint + +const ( + ModifierBackslash Modifier = iota +) + +var ( + // Special runes. + tokenTypeRunes = map[rune]TokenType{ + '.': TTDot, + '[': TTSet, + ']': TTSet, + } + flagRunes = map[rune]Flag{ + '+': FlagPlus, + '*': FlagStar, + } + modifierRunes = map[rune]Modifier{ + '\\': ModifierBackslash, + } + + // Errors. + ErrInvalidInput = errors.New("the input provided is invalid") + errEndOfInput = errors.New("reached end of input") +) + +// Tokenize converts a rune slice into a Token slice. +func Tokenize(input []rune) ([]Token, error) { + tokens := []Token{} + for i, t, err := nextToken(0, input); err != errEndOfInput; i, t, err = nextToken(i, input) { + if err != nil { + return nil, err + } + + tokens = append(tokens, t) + } + + return tokens, nil +} + +// nextToken yields the Token starting at the given index of input, and newIndex at which the next Token should start. +func nextToken(index int, input []rune) (newIndex int, token Token, err error) { + var r rune + var escaped bool + + newIndex, r, escaped, err = nextRune(index, input) + if err != nil { + return + } + + if !escaped { + if ttype, ok := tokenTypeRunes[r]; ok { + switch ttype { + case TTDot: + token = NewDot() + + case TTSet: + if r == ']' { + err = errors.Wrap(ErrInvalidInput, invalidInputMessage(input, newIndex, "set-close ']' with no preceding '['")) + return + } + + newIndex, token, err = nextTokenSet(newIndex, input) + if err != nil { + return + } + + default: + panic(errors.Wrapf(errBadImplementation, "encountered unhandled token type: %v", ttype)) + } + + } else if _, ok := flagRunes[r]; ok { + err = errors.Wrap(ErrInvalidInput, invalidInputMessage(input, newIndex, "flag '%s' must be preceded by a non-flag", string(r))) + return + + } else if m, ok := modifierRunes[r]; ok { + panic(errors.Wrapf(errBadImplementation, "encountered unhandled modifier: %v", m)) + } else { + // Nothing special to do. + token = NewCharacter(r) + } + } else { + // Nothing special to do. + token = NewCharacter(r) + } + + var f Flag + newIndex, f, err = nextFlag(newIndex, input) + if err == errEndOfInput { + // Let this err be passed in the next cycle, after the current token is consumed. + err = nil + } else if err != nil { + return + } + + token.SetFlag(f) + + return +} + +// nextTokenSet yields a Token having type TokenSet and starting at the given index of input. +// The next Token/Flag should start at newIndex. +func nextTokenSet(index int, input []rune) (newIndex int, t Token, err error) { + var r, prev rune + var escaped bool + + runes := make([]rune, 0, 30) + complete, prevExists := false, false + + newIndex, r, escaped, err = nextRune(index, input) + // If errEndOfInput is encountered, flow of control proceeds to the end of the function, + // where the error is handled. + if err != nil && err != errEndOfInput { + return + } + + for ; err != errEndOfInput; newIndex, r, escaped, err = nextRune(newIndex, input) { + if err != nil { + return + } + + if !escaped { + // Handle symbols. + switch r { + case '-': + if !prevExists { + err = errors.Wrap(ErrInvalidInput, invalidInputMessage(input, newIndex, "range character '-' must be preceded by a Unicode character")) + return + } + if newIndex >= len(input)-1 { + err = errors.Wrap(ErrInvalidInput, invalidInputMessage(input, newIndex, "range character '-' must be followed by a Unicode character")) + return + } + + // Get the next rune to know the extent of the range. + newIndex, r, escaped, err = nextRune(newIndex, input) + + if !escaped { + if r == ']' || r == '-' { + err = errors.Wrap(ErrInvalidInput, invalidInputMessage(input, newIndex, "range character '-' cannot be followed by a special symbol")) + return + } + } + if r < prev { + err = errors.Wrap(ErrInvalidInput, invalidInputMessage(input, newIndex, "range is out of order: '%s' comes before '%s' in Unicode", string(r), string(prev))) + return + } + + for x := prev; x <= r; x++ { + runes = append(runes, x) + } + + prevExists = false + + case ']': + complete = true + + // Nothing special to do. + default: + runes = append(runes, r) + prev, prevExists = r, true + } + } else { + // Nothing special to do. + runes = append(runes, r) + prev, prevExists = r, true + } + + // Don't move the index forward if the set is complete. + if complete { + break + } + } + + // End of input is reached before the set completes. + if !complete { + err = errors.Wrap(ErrInvalidInput, invalidInputMessage(input, newIndex, "found [ without matching ]")) + } else { + t = NewSet(runes) + } + + return +} + +// nextFlag yields the Flag starting at the given index of input, if any. +// The next Token should start at newIndex. +func nextFlag(index int, input []rune) (newIndex int, f Flag, err error) { + var escaped, ok bool + var r rune + + f = FlagNone + + newIndex, r, escaped, err = nextRune(index, input) + if err != nil { + return + } + + if !escaped { + // Revert back to index for later consumption. + if f, ok = flagRunes[r]; !ok { + newIndex = index + } + } else { + // Revert back to index for later consumption. + newIndex = index + } + + return +} + +// nextRune yields the rune starting (with modifiers) at the given index of input, with boolean escaped describing whether the rune is escaped. +// The next rune should start at newIndex. +func nextRune(index int, input []rune) (newIndex int, r rune, escaped bool, err error) { + if index >= len(input) { + newIndex = index + err = errEndOfInput + return + } + + if m, ok := modifierRunes[input[index]]; ok { + switch m { + + case ModifierBackslash: + if index < len(input)-1 { + newIndex, r, escaped = index+2, input[index+1], true + } else if index == len(input)-1 { + err = errors.Wrap(ErrInvalidInput, invalidInputMessage(input, index, "input ends with a \\ (escape) character")) + } + default: + panic(errors.Wrapf(errBadImplementation, "encountered unhandled modifier: %v", m)) + } + } else { + newIndex, r, escaped = index+1, input[index], false + } + + return +} + +// invalidInputMessage wraps the message describing invalid input with the input itself and index at which it is invalid. +func invalidInputMessage(input []rune, index int, message string, args ...interface{}) string { + return fmt.Sprintf("input:%s, pos:%d, %s", string(input), index, fmt.Sprintf(message, args...)) +} diff --git a/go.opencensus.io/AUTHORS b/go.opencensus.io/AUTHORS new file mode 100644 index 00000000..e491a9e7 --- /dev/null +++ b/go.opencensus.io/AUTHORS @@ -0,0 +1 @@ +Google Inc. diff --git a/go.opencensus.io/LICENSE b/go.opencensus.io/LICENSE new file mode 100644 index 00000000..7a4a3ea2 --- /dev/null +++ b/go.opencensus.io/LICENSE @@ -0,0 +1,202 @@ + + 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. \ No newline at end of file diff --git a/go.opencensus.io/exporter/stackdriver/propagation/http.go b/go.opencensus.io/exporter/stackdriver/propagation/http.go new file mode 100644 index 00000000..7cc02a11 --- /dev/null +++ b/go.opencensus.io/exporter/stackdriver/propagation/http.go @@ -0,0 +1,94 @@ +// Copyright 2018, OpenCensus 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 propagation implement X-Cloud-Trace-Context header propagation used +// by Google Cloud products. +package propagation // import "go.opencensus.io/exporter/stackdriver/propagation" + +import ( + "encoding/binary" + "encoding/hex" + "fmt" + "net/http" + "strconv" + "strings" + + "go.opencensus.io/trace" + "go.opencensus.io/trace/propagation" +) + +const ( + httpHeaderMaxSize = 200 + httpHeader = `X-Cloud-Trace-Context` +) + +var _ propagation.HTTPFormat = (*HTTPFormat)(nil) + +// HTTPFormat implements propagation.HTTPFormat to propagate +// traces in HTTP headers for Google Cloud Platform and Stackdriver Trace. +type HTTPFormat struct{} + +// SpanContextFromRequest extracts a Stackdriver Trace span context from incoming requests. +func (f *HTTPFormat) SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool) { + h := req.Header.Get(httpHeader) + // See https://cloud.google.com/trace/docs/faq for the header HTTPFormat. + // Return if the header is empty or missing, or if the header is unreasonably + // large, to avoid making unnecessary copies of a large string. + if h == "" || len(h) > httpHeaderMaxSize { + return trace.SpanContext{}, false + } + + // Parse the trace id field. + slash := strings.Index(h, `/`) + if slash == -1 { + return trace.SpanContext{}, false + } + tid, h := h[:slash], h[slash+1:] + + buf, err := hex.DecodeString(tid) + if err != nil { + return trace.SpanContext{}, false + } + copy(sc.TraceID[:], buf) + + // Parse the span id field. + spanstr := h + semicolon := strings.Index(h, `;`) + if semicolon != -1 { + spanstr, h = h[:semicolon], h[semicolon+1:] + } + sid, err := strconv.ParseUint(spanstr, 10, 64) + if err != nil { + return trace.SpanContext{}, false + } + binary.BigEndian.PutUint64(sc.SpanID[:], sid) + + // Parse the options field, options field is optional. + if !strings.HasPrefix(h, "o=") { + return sc, true + } + o, err := strconv.ParseUint(h[2:], 10, 64) + if err != nil { + return trace.SpanContext{}, false + } + sc.TraceOptions = trace.TraceOptions(o) + return sc, true +} + +// SpanContextToRequest modifies the given request to include a Stackdriver Trace header. +func (f *HTTPFormat) SpanContextToRequest(sc trace.SpanContext, req *http.Request) { + sid := binary.BigEndian.Uint64(sc.SpanID[:]) + header := fmt.Sprintf("%s/%d;o=%d", hex.EncodeToString(sc.TraceID[:]), sid, int64(sc.TraceOptions)) + req.Header.Set(httpHeader, header) +} diff --git a/go.opencensus.io/internal/internal.go b/go.opencensus.io/internal/internal.go new file mode 100644 index 00000000..8907e4e3 --- /dev/null +++ b/go.opencensus.io/internal/internal.go @@ -0,0 +1,32 @@ +// Copyright 2017, OpenCensus 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 "time" + +// UserAgent is the user agent to be added to the outgoing +// requests from the exporters. +const UserAgent = "opencensus-go-v0.4.0" + +// MonotonicEndTime returns the end time at present +// but offset from start, monotonically. +// +// The monotonic clock is used in subtractions hence +// the duration since start added back to start gives +// end as a monotonic time. +// See https://golang.org/pkg/time/#hdr-Monotonic_Clocks +func MonotonicEndTime(start time.Time) time.Time { + return start.Add(time.Now().Sub(start)) +} diff --git a/go.opencensus.io/internal/sanitize.go b/go.opencensus.io/internal/sanitize.go new file mode 100644 index 00000000..de8ccf23 --- /dev/null +++ b/go.opencensus.io/internal/sanitize.go @@ -0,0 +1,50 @@ +// Copyright 2017, OpenCensus 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 ( + "strings" + "unicode" +) + +const labelKeySizeLimit = 100 + +// Sanitize returns a string that is trunacated to 100 characters if it's too +// long, and replaces non-alphanumeric characters to underscores. +func Sanitize(s string) string { + if len(s) == 0 { + return s + } + if len(s) > labelKeySizeLimit { + s = s[:labelKeySizeLimit] + } + s = strings.Map(sanitizeRune, s) + if unicode.IsDigit(rune(s[0])) { + s = "key_" + s + } + if s[0] == '_' { + s = "key" + s + } + return s +} + +// converts anything that is not a letter or digit to an underscore +func sanitizeRune(r rune) rune { + if unicode.IsLetter(r) || unicode.IsDigit(r) { + return r + } + // Everything else turns into an underscore + return '_' +} diff --git a/go.opencensus.io/internal/tagencoding/tagencoding.go b/go.opencensus.io/internal/tagencoding/tagencoding.go new file mode 100644 index 00000000..d9f23abe --- /dev/null +++ b/go.opencensus.io/internal/tagencoding/tagencoding.go @@ -0,0 +1,72 @@ +// Copyright 2017, OpenCensus 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 tagencoding contains the tag encoding +// used interally by the stats collector. +package tagencoding + +type Values struct { + Buffer []byte + WriteIndex int + ReadIndex int +} + +func (vb *Values) growIfRequired(expected int) { + if len(vb.Buffer)-vb.WriteIndex < expected { + tmp := make([]byte, 2*(len(vb.Buffer)+1)+expected) + copy(tmp, vb.Buffer) + vb.Buffer = tmp + } +} + +func (vb *Values) WriteValue(v []byte) { + length := len(v) & 0xff + vb.growIfRequired(1 + length) + + // writing length of v + vb.Buffer[vb.WriteIndex] = byte(length) + vb.WriteIndex++ + + if length == 0 { + // No value was encoded for this key + return + } + + // writing v + copy(vb.Buffer[vb.WriteIndex:], v[:length]) + vb.WriteIndex += length +} + +// ReadValue is the helper method to read the values when decoding valuesBytes to a map[Key][]byte. +func (vb *Values) ReadValue() []byte { + // read length of v + length := int(vb.Buffer[vb.ReadIndex]) + vb.ReadIndex++ + if length == 0 { + // No value was encoded for this key + return nil + } + + // read value of v + v := make([]byte, length) + endIdx := vb.ReadIndex + length + copy(v, vb.Buffer[vb.ReadIndex:endIdx]) + vb.ReadIndex = endIdx + return v +} + +func (vb *Values) Bytes() []byte { + return vb.Buffer[:vb.WriteIndex] +} diff --git a/go.opencensus.io/internal/traceinternals.go b/go.opencensus.io/internal/traceinternals.go new file mode 100644 index 00000000..553ca68d --- /dev/null +++ b/go.opencensus.io/internal/traceinternals.go @@ -0,0 +1,52 @@ +// Copyright 2017, OpenCensus 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 ( + "time" +) + +// Trace allows internal access to some trace functionality. +// TODO(#412): remove this +var Trace interface{} + +var LocalSpanStoreEnabled bool + +// BucketConfiguration stores the number of samples to store for span buckets +// for successful and failed spans for a particular span name. +type BucketConfiguration struct { + Name string + MaxRequestsSucceeded int + MaxRequestsErrors int +} + +// PerMethodSummary is a summary of the spans stored for a single span name. +type PerMethodSummary struct { + Active int + LatencyBuckets []LatencyBucketSummary + ErrorBuckets []ErrorBucketSummary +} + +// LatencyBucketSummary is a summary of a latency bucket. +type LatencyBucketSummary struct { + MinLatency, MaxLatency time.Duration + Size int +} + +// ErrorBucketSummary is a summary of an error bucket. +type ErrorBucketSummary struct { + ErrorCode int32 + Size int +} diff --git a/go.opencensus.io/plugin/ocgrpc/client.go b/go.opencensus.io/plugin/ocgrpc/client.go new file mode 100644 index 00000000..f4a2d4d2 --- /dev/null +++ b/go.opencensus.io/plugin/ocgrpc/client.go @@ -0,0 +1,55 @@ +// Copyright 2018, OpenCensus 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 ocgrpc + +import ( + "go.opencensus.io/trace" + "golang.org/x/net/context" + + "google.golang.org/grpc/stats" +) + +// ClientHandler implements a gRPC stats.Handler for recording OpenCensus stats and +// traces. Use with gRPC clients only. +type ClientHandler struct { + // StartOptions allows configuring the StartOptions used to create new spans. + // + // StartOptions.SpanKind will always be set to trace.SpanKindClient + // for spans started by this handler. + StartOptions trace.StartOptions +} + +func (c *ClientHandler) HandleConn(ctx context.Context, cs stats.ConnStats) { + // no-op +} + +// TagConn exists to satisfy gRPC stats.Handler. +func (c *ClientHandler) TagConn(ctx context.Context, cti *stats.ConnTagInfo) context.Context { + // no-op + return ctx +} + +// HandleRPC implements per-RPC tracing and stats instrumentation. +func (c *ClientHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) { + traceHandleRPC(ctx, rs) + c.statsHandleRPC(ctx, rs) +} + +// TagRPC implements per-RPC context management. +func (c *ClientHandler) TagRPC(ctx context.Context, rti *stats.RPCTagInfo) context.Context { + ctx = c.traceTagRPC(ctx, rti) + ctx = c.statsTagRPC(ctx, rti) + return ctx +} diff --git a/go.opencensus.io/plugin/ocgrpc/client_metrics.go b/go.opencensus.io/plugin/ocgrpc/client_metrics.go new file mode 100644 index 00000000..e9a4d2bd --- /dev/null +++ b/go.opencensus.io/plugin/ocgrpc/client_metrics.go @@ -0,0 +1,103 @@ +// Copyright 2017, OpenCensus 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 ocgrpc + +import ( + "go.opencensus.io/stats" + "go.opencensus.io/stats/view" + "go.opencensus.io/tag" +) + +// The following variables are measures are recorded by ClientHandler: +var ( + ClientErrorCount, _ = stats.Int64("grpc.io/client/error_count", "RPC Errors", stats.UnitNone) + ClientRequestBytes, _ = stats.Int64("grpc.io/client/request_bytes", "Request bytes", stats.UnitBytes) + ClientResponseBytes, _ = stats.Int64("grpc.io/client/response_bytes", "Response bytes", stats.UnitBytes) + ClientStartedCount, _ = stats.Int64("grpc.io/client/started_count", "Number of client RPCs (streams) started", stats.UnitNone) + ClientFinishedCount, _ = stats.Int64("grpc.io/client/finished_count", "Number of client RPCs (streams) finished", stats.UnitNone) + ClientRequestCount, _ = stats.Int64("grpc.io/client/request_count", "Number of client RPC request messages", stats.UnitNone) + ClientResponseCount, _ = stats.Int64("grpc.io/client/response_count", "Number of client RPC response messages", stats.UnitNone) + ClientRoundTripLatency, _ = stats.Float64("grpc.io/client/roundtrip_latency", "RPC roundtrip latency in msecs", stats.UnitMilliseconds) +) + +// Predefined views may be subscribed to collect data for the above measures. +// As always, you may also define your own custom views over measures collected by this +// package. These are declared as a convenience only; none are subscribed by +// default. +var ( + ClientErrorCountView = &view.View{ + Name: "grpc.io/client/error_count", + Description: "RPC Errors", + TagKeys: []tag.Key{KeyStatus, KeyMethod}, + Measure: ClientErrorCount, + Aggregation: view.Mean(), + } + + ClientRoundTripLatencyView = &view.View{ + Name: "grpc.io/client/roundtrip_latency", + Description: "Latency in msecs", + TagKeys: []tag.Key{KeyMethod}, + Measure: ClientRoundTripLatency, + Aggregation: DefaultMillisecondsDistribution, + } + + ClientRequestBytesView = &view.View{ + Name: "grpc.io/client/request_bytes", + Description: "Request bytes", + TagKeys: []tag.Key{KeyMethod}, + Measure: ClientRequestBytes, + Aggregation: DefaultBytesDistribution, + } + + ClientResponseBytesView = &view.View{ + Name: "grpc.io/client/response_bytes", + Description: "Response bytes", + TagKeys: []tag.Key{KeyMethod}, + Measure: ClientResponseBytes, + Aggregation: DefaultBytesDistribution, + } + + ClientRequestCountView = &view.View{ + Name: "grpc.io/client/request_count", + Description: "Count of request messages per client RPC", + TagKeys: []tag.Key{KeyMethod}, + Measure: ClientRequestCount, + Aggregation: DefaultMessageCountDistribution, + } + + ClientResponseCountView = &view.View{ + Name: "grpc.io/client/response_count", + Description: "Count of response messages per client RPC", + TagKeys: []tag.Key{KeyMethod}, + Measure: ClientResponseCount, + Aggregation: DefaultMessageCountDistribution, + } +) + +// DefaultClientViews are the default client views provided by this package. +var DefaultClientViews = []*view.View{ + ClientErrorCountView, + ClientRoundTripLatencyView, + ClientRequestBytesView, + ClientResponseBytesView, + ClientRequestCountView, + ClientResponseCountView, +} + +// TODO(jbd): Add roundtrip_latency, uncompressed_request_bytes, uncompressed_response_bytes, request_count, response_count. +// TODO(acetechnologist): This is temporary and will need to be replaced by a +// mechanism to load these defaults from a common repository/config shared by +// all supported languages. Likely a serialized protobuf of these defaults. diff --git a/go.opencensus.io/plugin/ocgrpc/client_stats_handler.go b/go.opencensus.io/plugin/ocgrpc/client_stats_handler.go new file mode 100644 index 00000000..22d076dc --- /dev/null +++ b/go.opencensus.io/plugin/ocgrpc/client_stats_handler.go @@ -0,0 +1,128 @@ +// Copyright 2017, OpenCensus 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 ocgrpc + +import ( + "sync/atomic" + "time" + + ocstats "go.opencensus.io/stats" + "go.opencensus.io/tag" + "golang.org/x/net/context" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/stats" + "google.golang.org/grpc/status" +) + +// statsTagRPC gets the tag.Map populated by the application code, serializes +// its tags into the GRPC metadata in order to be sent to the server. +func (h *ClientHandler) statsTagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context { + startTime := time.Now() + if info == nil { + if grpclog.V(2) { + grpclog.Infof("clientHandler.TagRPC called with nil info.", info.FullMethodName) + } + return ctx + } + + d := &rpcData{ + startTime: startTime, + method: info.FullMethodName, + } + ts := tag.FromContext(ctx) + if ts != nil { + encoded := tag.Encode(ts) + ctx = stats.SetTags(ctx, encoded) + } + + // TODO(acetechnologist): should we be recording this later? What is the + // point of updating d.reqLen & d.reqCount if we update now? + record(ctx, d, "", ClientStartedCount.M(1)) + return context.WithValue(ctx, grpcClientRPCKey, d) +} + +// statsHandleRPC processes the RPC events. +func (h *ClientHandler) statsHandleRPC(ctx context.Context, s stats.RPCStats) { + switch st := s.(type) { + case *stats.Begin, *stats.OutHeader, *stats.InHeader, *stats.InTrailer, *stats.OutTrailer: + // do nothing for client + case *stats.OutPayload: + h.handleRPCOutPayload(ctx, st) + case *stats.InPayload: + h.handleRPCInPayload(ctx, st) + case *stats.End: + h.handleRPCEnd(ctx, st) + default: + grpclog.Infof("unexpected stats: %T", st) + } +} + +func (h *ClientHandler) handleRPCOutPayload(ctx context.Context, s *stats.OutPayload) { + d, ok := ctx.Value(grpcClientRPCKey).(*rpcData) + if !ok { + if grpclog.V(2) { + grpclog.Infoln("clientHandler.handleRPCOutPayload failed to retrieve *rpcData from context") + } + return + } + + record(ctx, d, "", ClientRequestBytes.M(int64(s.Length))) + atomic.AddInt64(&d.reqCount, 1) +} + +func (h *ClientHandler) handleRPCInPayload(ctx context.Context, s *stats.InPayload) { + d, ok := ctx.Value(grpcClientRPCKey).(*rpcData) + if !ok { + if grpclog.V(2) { + grpclog.Infoln("failed to retrieve *rpcData from context") + } + return + } + + record(ctx, d, "", ClientResponseBytes.M(int64(s.Length))) + atomic.AddInt64(&d.respCount, 1) +} + +func (h *ClientHandler) handleRPCEnd(ctx context.Context, s *stats.End) { + d, ok := ctx.Value(grpcClientRPCKey).(*rpcData) + if !ok { + if grpclog.V(2) { + grpclog.Infoln("failed to retrieve *rpcData from context") + } + return + } + + elapsedTime := time.Since(d.startTime) + reqCount := atomic.LoadInt64(&d.reqCount) + respCount := atomic.LoadInt64(&d.respCount) + + m := []ocstats.Measurement{ + ClientRequestCount.M(reqCount), + ClientResponseCount.M(respCount), + ClientFinishedCount.M(1), + ClientRoundTripLatency.M(float64(elapsedTime) / float64(time.Millisecond)), + } + + var st string + if s.Error != nil { + s, ok := status.FromError(s.Error) + if ok { + st = s.Code().String() + } + m = append(m, ClientErrorCount.M(1)) + } + record(ctx, d, st, m...) +} diff --git a/go.opencensus.io/plugin/ocgrpc/doc.go b/go.opencensus.io/plugin/ocgrpc/doc.go new file mode 100644 index 00000000..1370323f --- /dev/null +++ b/go.opencensus.io/plugin/ocgrpc/doc.go @@ -0,0 +1,19 @@ +// Copyright 2017, OpenCensus 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 ocgrpc contains OpenCensus stats and trace +// integrations for gRPC. +// +// Use ServerHandler for servers and ClientHandler for clients. +package ocgrpc // import "go.opencensus.io/plugin/ocgrpc" diff --git a/go.opencensus.io/plugin/ocgrpc/server.go b/go.opencensus.io/plugin/ocgrpc/server.go new file mode 100644 index 00000000..f5da89b9 --- /dev/null +++ b/go.opencensus.io/plugin/ocgrpc/server.go @@ -0,0 +1,80 @@ +// Copyright 2018, OpenCensus 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 ocgrpc + +import ( + "go.opencensus.io/trace" + "golang.org/x/net/context" + + "google.golang.org/grpc/stats" +) + +// ServerHandler implements gRPC stats.Handler recording OpenCensus stats and +// traces. Use with gRPC servers. +// +// When installed (see Example), tracing metadata is read from inbound RPCs +// by default. If no tracing metadata is present, or if the tracing metadata is +// present but the SpanContext isn't sampled, then a new trace may be started +// (as determined by Sampler). +type ServerHandler struct { + // IsPublicEndpoint may be set to true to always start a new trace around + // each RPC. Any SpanContext in the RPC metadata will be added as a linked + // span instead of making it the parent of the span created around the + // server RPC. + // + // Be aware that if you leave this false (the default) on a public-facing + // server, callers will be able to send tracing metadata in gRPC headers + // and trigger traces in your backend. + IsPublicEndpoint bool + + // StartOptions to use for to spans started around RPCs handled by this server. + // + // These will apply even if there is tracing metadata already + // present on the inbound RPC but the SpanContext is not sampled. This + // ensures that each service has some opportunity to be traced. If you would + // like to not add any additional traces for this gRPC service, set: + // + // StartOptions.Sampler = trace.ProbabilitySampler(0.0) + // + // StartOptions.SpanKind will always be set to trace.SpanKindServer + // for spans started by this handler. + StartOptions trace.StartOptions +} + +var _ stats.Handler = (*ServerHandler)(nil) + +// HandleConn exists to satisfy gRPC stats.Handler. +func (s *ServerHandler) HandleConn(ctx context.Context, cs stats.ConnStats) { + // no-op +} + +// TagConn exists to satisfy gRPC stats.Handler. +func (s *ServerHandler) TagConn(ctx context.Context, cti *stats.ConnTagInfo) context.Context { + // no-op + return ctx +} + +// HandleRPC implements per-RPC tracing and stats instrumentation. +func (s *ServerHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) { + traceHandleRPC(ctx, rs) + s.statsHandleRPC(ctx, rs) +} + +// TagRPC implements per-RPC context management. +func (s *ServerHandler) TagRPC(ctx context.Context, rti *stats.RPCTagInfo) context.Context { + ctx = s.traceTagRPC(ctx, rti) + ctx = s.statsTagRPC(ctx, rti) + return ctx +} diff --git a/go.opencensus.io/plugin/ocgrpc/server_metrics.go b/go.opencensus.io/plugin/ocgrpc/server_metrics.go new file mode 100644 index 00000000..7ff4d24a --- /dev/null +++ b/go.opencensus.io/plugin/ocgrpc/server_metrics.go @@ -0,0 +1,104 @@ +// Copyright 2017, OpenCensus 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 ocgrpc + +import ( + "go.opencensus.io/stats" + "go.opencensus.io/stats/view" + "go.opencensus.io/tag" +) + +// The following variables are measures are recorded by ServerHandler: +var ( + ServerErrorCount, _ = stats.Int64("grpc.io/server/error_count", "RPC Errors", stats.UnitNone) + ServerServerElapsedTime, _ = stats.Float64("grpc.io/server/server_elapsed_time", "Server elapsed time in msecs", stats.UnitMilliseconds) + ServerRequestBytes, _ = stats.Int64("grpc.io/server/request_bytes", "Request bytes", stats.UnitBytes) + ServerResponseBytes, _ = stats.Int64("grpc.io/server/response_bytes", "Response bytes", stats.UnitBytes) + ServerStartedCount, _ = stats.Int64("grpc.io/server/started_count", "Number of server RPCs (streams) started", stats.UnitNone) + ServerFinishedCount, _ = stats.Int64("grpc.io/server/finished_count", "Number of server RPCs (streams) finished", stats.UnitNone) + ServerRequestCount, _ = stats.Int64("grpc.io/server/request_count", "Number of server RPC request messages", stats.UnitNone) + ServerResponseCount, _ = stats.Int64("grpc.io/server/response_count", "Number of server RPC response messages", stats.UnitNone) +) + +// TODO(acetechnologist): This is temporary and will need to be replaced by a +// mechanism to load these defaults from a common repository/config shared by +// all supported languages. Likely a serialized protobuf of these defaults. + +// Predefined views may be subscribed to collect data for the above measures. +// As always, you may also define your own custom views over measures collected by this +// package. These are declared as a convenience only; none are subscribed by +// default. +var ( + ServerErrorCountView = &view.View{ + Name: "grpc.io/server/error_count", + Description: "RPC Errors", + TagKeys: []tag.Key{KeyMethod, KeyStatus}, + Measure: ServerErrorCount, + Aggregation: view.Count(), + } + + ServerServerElapsedTimeView = &view.View{ + Name: "grpc.io/server/server_elapsed_time", + Description: "Server elapsed time in msecs", + TagKeys: []tag.Key{KeyMethod}, + Measure: ServerServerElapsedTime, + Aggregation: DefaultMillisecondsDistribution, + } + + ServerRequestBytesView = &view.View{ + Name: "grpc.io/server/request_bytes", + Description: "Request bytes", + TagKeys: []tag.Key{KeyMethod}, + Measure: ServerRequestBytes, + Aggregation: DefaultBytesDistribution, + } + + ServerResponseBytesView = &view.View{ + Name: "grpc.io/server/response_bytes", + Description: "Response bytes", + TagKeys: []tag.Key{KeyMethod}, + Measure: ServerResponseBytes, + Aggregation: DefaultBytesDistribution, + } + + ServerRequestCountView = &view.View{ + Name: "grpc.io/server/request_count", + Description: "Count of request messages per server RPC", + TagKeys: []tag.Key{KeyMethod}, + Measure: ServerRequestCount, + Aggregation: DefaultMessageCountDistribution, + } + + ServerResponseCountView = &view.View{ + Name: "grpc.io/server/response_count", + Description: "Count of response messages per server RPC", + TagKeys: []tag.Key{KeyMethod}, + Measure: ServerResponseCount, + Aggregation: DefaultMessageCountDistribution, + } +) + +// DefaultServerViews are the default server views provided by this package. +var DefaultServerViews = []*view.View{ + ServerErrorCountView, + ServerServerElapsedTimeView, + ServerRequestBytesView, + ServerResponseBytesView, + ServerRequestCountView, + ServerResponseCountView, +} + +// TODO(jbd): Add roundtrip_latency, uncompressed_request_bytes, uncompressed_response_bytes, request_count, response_count. diff --git a/go.opencensus.io/plugin/ocgrpc/server_stats_handler.go b/go.opencensus.io/plugin/ocgrpc/server_stats_handler.go new file mode 100644 index 00000000..c146da5d --- /dev/null +++ b/go.opencensus.io/plugin/ocgrpc/server_stats_handler.go @@ -0,0 +1,137 @@ +// Copyright 2017, OpenCensus 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 ocgrpc + +import ( + "fmt" + "sync/atomic" + "time" + + "golang.org/x/net/context" + + ocstats "go.opencensus.io/stats" + "go.opencensus.io/tag" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/stats" + "google.golang.org/grpc/status" +) + +// statsTagRPC gets the metadata from gRPC context, extracts the encoded tags from +// it and creates a new tag.Map and puts them into the returned context. +func (h *ServerHandler) statsTagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context { + startTime := time.Now() + if info == nil { + if grpclog.V(2) { + grpclog.Infof("serverHandler.TagRPC called with nil info.", info.FullMethodName) + } + return ctx + } + d := &rpcData{ + startTime: startTime, + method: info.FullMethodName, + } + ctx, _ = h.createTags(ctx) + record(ctx, d, "", ServerStartedCount.M(1)) + return context.WithValue(ctx, grpcServerRPCKey, d) +} + +// statsHandleRPC processes the RPC events. +func (h *ServerHandler) statsHandleRPC(ctx context.Context, s stats.RPCStats) { + switch st := s.(type) { + case *stats.Begin, *stats.InHeader, *stats.InTrailer, *stats.OutHeader, *stats.OutTrailer: + // Do nothing for server + case *stats.InPayload: + h.handleRPCInPayload(ctx, st) + case *stats.OutPayload: + // For stream it can be called multiple times per RPC. + h.handleRPCOutPayload(ctx, st) + case *stats.End: + h.handleRPCEnd(ctx, st) + default: + grpclog.Infof("unexpected stats: %T", st) + } +} + +func (h *ServerHandler) handleRPCInPayload(ctx context.Context, s *stats.InPayload) { + d, ok := ctx.Value(grpcServerRPCKey).(*rpcData) + if !ok { + if grpclog.V(2) { + grpclog.Infoln("handleRPCInPayload: failed to retrieve *rpcData from context") + } + return + } + + record(ctx, d, "", ServerRequestBytes.M(int64(s.Length))) + atomic.AddInt64(&d.reqCount, 1) +} + +func (h *ServerHandler) handleRPCOutPayload(ctx context.Context, s *stats.OutPayload) { + d, ok := ctx.Value(grpcServerRPCKey).(*rpcData) + if !ok { + if grpclog.V(2) { + grpclog.Infoln("handleRPCOutPayload: failed to retrieve *rpcData from context") + } + return + } + + record(ctx, d, "", ServerResponseBytes.M(int64(s.Length))) + atomic.AddInt64(&d.respCount, 1) +} + +func (h *ServerHandler) handleRPCEnd(ctx context.Context, s *stats.End) { + d, ok := ctx.Value(grpcServerRPCKey).(*rpcData) + if !ok { + if grpclog.V(2) { + grpclog.Infoln("serverHandler.handleRPCEnd failed to retrieve *rpcData from context") + } + return + } + + elapsedTime := time.Since(d.startTime) + reqCount := atomic.LoadInt64(&d.reqCount) + respCount := atomic.LoadInt64(&d.respCount) + + m := []ocstats.Measurement{ + ServerRequestCount.M(reqCount), + ServerResponseCount.M(respCount), + ServerFinishedCount.M(1), + ServerServerElapsedTime.M(float64(elapsedTime) / float64(time.Millisecond)), + } + + var st string + if s.Error != nil { + s, ok := status.FromError(s.Error) + if ok { + st = s.Code().String() + } + m = append(m, ServerErrorCount.M(1)) + } + record(ctx, d, st, m...) +} + +// createTags creates a new tag map containing the tags extracted from the +// gRPC metadata. +func (h *ServerHandler) createTags(ctx context.Context) (context.Context, error) { + buf := stats.Tags(ctx) + if buf == nil { + return ctx, nil + } + propagated, err := tag.Decode(buf) + if err != nil { + return nil, fmt.Errorf("serverHandler.createTags failed to decode: %v", err) + } + return tag.NewContext(ctx, propagated), nil +} diff --git a/go.opencensus.io/plugin/ocgrpc/stats_common.go b/go.opencensus.io/plugin/ocgrpc/stats_common.go new file mode 100644 index 00000000..52b41ac2 --- /dev/null +++ b/go.opencensus.io/plugin/ocgrpc/stats_common.go @@ -0,0 +1,77 @@ +// Copyright 2017, OpenCensus 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 ocgrpc + +import ( + "strings" + "time" + + ocstats "go.opencensus.io/stats" + "go.opencensus.io/stats/view" + "go.opencensus.io/tag" + "golang.org/x/net/context" +) + +type grpcInstrumentationKey string + +// rpcData holds the instrumentation RPC data that is needed between the start +// and end of an call. It holds the info that this package needs to keep track +// of between the various GRPC events. +type rpcData struct { + // reqCount and respCount has to be the first words + // in order to be 64-aligned on 32-bit architectures. + reqCount, respCount int64 // access atomically + + // startTime represents the time at which TagRPC was invoked at the + // beginning of an RPC. It is an appoximation of the time when the + // application code invoked GRPC code. + startTime time.Time + method string +} + +// The following variables define the default hard-coded auxiliary data used by +// both the default GRPC client and GRPC server metrics. +var ( + DefaultBytesDistribution = view.Distribution(0, 1024, 2048, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216, 67108864, 268435456, 1073741824, 4294967296) + DefaultMillisecondsDistribution = view.Distribution(0, 1, 2, 3, 4, 5, 6, 8, 10, 13, 16, 20, 25, 30, 40, 50, 65, 80, 100, 130, 160, 200, 250, 300, 400, 500, 650, 800, 1000, 2000, 5000, 10000, 20000, 50000, 100000) + DefaultMessageCountDistribution = view.Distribution(0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536) +) + +var ( + KeyMethod, _ = tag.NewKey("method") // gRPC service and method name + KeyStatus, _ = tag.NewKey("canonical_status") // Canonical status code +) + +var ( + grpcServerConnKey = grpcInstrumentationKey("server-conn") + grpcServerRPCKey = grpcInstrumentationKey("server-rpc") + grpcClientRPCKey = grpcInstrumentationKey("client-rpc") +) + +func methodName(fullname string) string { + return strings.TrimLeft(fullname, "/") +} + +func record(ctx context.Context, data *rpcData, status string, m ...ocstats.Measurement) { + mods := []tag.Mutator{ + tag.Upsert(KeyMethod, methodName(data.method)), + } + if status != "" { + mods = append(mods, tag.Upsert(KeyStatus, status)) + } + ctx, _ = tag.New(ctx, mods...) + ocstats.Record(ctx, m...) +} diff --git a/go.opencensus.io/plugin/ocgrpc/trace_common.go b/go.opencensus.io/plugin/ocgrpc/trace_common.go new file mode 100644 index 00000000..6d6836f0 --- /dev/null +++ b/go.opencensus.io/plugin/ocgrpc/trace_common.go @@ -0,0 +1,109 @@ +// Copyright 2017, OpenCensus 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 ocgrpc + +import ( + "strings" + + "google.golang.org/grpc/codes" + + "go.opencensus.io/trace" + "go.opencensus.io/trace/propagation" + "golang.org/x/net/context" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/stats" + "google.golang.org/grpc/status" +) + +const traceContextKey = "grpc-trace-bin" + +// TagRPC creates a new trace span for the client side of the RPC. +// +// It returns ctx with the new trace span added and a serialization of the +// SpanContext added to the outgoing gRPC metadata. +func (c *ClientHandler) traceTagRPC(ctx context.Context, rti *stats.RPCTagInfo) context.Context { + name := strings.TrimPrefix(rti.FullMethodName, "/") + name = strings.Replace(name, "/", ".", -1) + span := trace.NewSpan(name, trace.FromContext(ctx), trace.StartOptions{ + Sampler: c.StartOptions.Sampler, + SpanKind: trace.SpanKindClient, + }) // span is ended by traceHandleRPC + ctx = trace.WithSpan(ctx, span) + traceContextBinary := propagation.Binary(span.SpanContext()) + return metadata.AppendToOutgoingContext(ctx, traceContextKey, string(traceContextBinary)) +} + +// TagRPC creates a new trace span for the server side of the RPC. +// +// It checks the incoming gRPC metadata in ctx for a SpanContext, and if +// it finds one, uses that SpanContext as the parent context of the new span. +// +// It returns ctx, with the new trace span added. +func (s *ServerHandler) traceTagRPC(ctx context.Context, rti *stats.RPCTagInfo) context.Context { + opts := trace.StartOptions{ + Sampler: s.StartOptions.Sampler, + SpanKind: trace.SpanKindServer, + } + + md, _ := metadata.FromIncomingContext(ctx) + name := strings.TrimPrefix(rti.FullMethodName, "/") + name = strings.Replace(name, "/", ".", -1) + traceContext := md[traceContextKey] + var ( + parent trace.SpanContext + haveParent bool + ) + if len(traceContext) > 0 { + // Metadata with keys ending in -bin are actually binary. They are base64 + // encoded before being put on the wire, see: + // https://github.com/grpc/grpc-go/blob/08d6261/Documentation/grpc-metadata.md#storing-binary-data-in-metadata + traceContextBinary := []byte(traceContext[0]) + parent, haveParent = propagation.FromBinary(traceContextBinary) + if haveParent && !s.IsPublicEndpoint { + span := trace.NewSpanWithRemoteParent(name, parent, opts) + return trace.WithSpan(ctx, span) + } + } + span := trace.NewSpan(name, nil, opts) + if haveParent { + span.AddLink(trace.Link{TraceID: parent.TraceID, SpanID: parent.SpanID, Type: trace.LinkTypeChild}) + } + return trace.WithSpan(ctx, span) +} + +func traceHandleRPC(ctx context.Context, rs stats.RPCStats) { + span := trace.FromContext(ctx) + // TODO: compressed and uncompressed sizes are not populated in every message. + switch rs := rs.(type) { + case *stats.Begin: + span.AddAttributes( + trace.BoolAttribute("Client", rs.Client), + trace.BoolAttribute("FailFast", rs.FailFast)) + case *stats.InPayload: + span.AddMessageReceiveEvent(0 /* TODO: messageID */, int64(rs.Length), int64(rs.WireLength)) + case *stats.OutPayload: + span.AddMessageSendEvent(0, int64(rs.Length), int64(rs.WireLength)) + case *stats.End: + if rs.Error != nil { + s, ok := status.FromError(rs.Error) + if ok { + span.SetStatus(trace.Status{Code: int32(s.Code()), Message: s.Message()}) + } else { + span.SetStatus(trace.Status{Code: int32(codes.Internal), Message: rs.Error.Error()}) + } + } + span.End() + } +} diff --git a/go.opencensus.io/plugin/ochttp/client.go b/go.opencensus.io/plugin/ochttp/client.go new file mode 100644 index 00000000..37f42b3b --- /dev/null +++ b/go.opencensus.io/plugin/ochttp/client.go @@ -0,0 +1,84 @@ +// Copyright 2018, OpenCensus 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 ochttp + +import ( + "net/http" + + "go.opencensus.io/trace" + "go.opencensus.io/trace/propagation" +) + +// Transport is an http.RoundTripper that instruments all outgoing requests with +// stats and tracing. The zero value is intended to be a useful default, but for +// now it's recommended that you explicitly set Propagation. +type Transport struct { + // Base may be set to wrap another http.RoundTripper that does the actual + // requests. By default http.DefaultTransport is used. + // + // If base HTTP roundtripper implements CancelRequest, + // the returned round tripper will be cancelable. + Base http.RoundTripper + + // Propagation defines how traces are propagated. If unspecified, a default + // (currently B3 format) will be used. + Propagation propagation.HTTPFormat + + // StartOptions are applied to the span started by this Transport around each + // request. + // + // StartOptions.SpanKind will always be set to trace.SpanKindClient + // for spans started by this transport. + StartOptions trace.StartOptions + + // TODO: Implement tag propagation for HTTP. +} + +// RoundTrip implements http.RoundTripper, delegating to Base and recording stats and traces for the request. +func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { + rt := t.base() + // TODO: remove excessive nesting of http.RoundTrippers here. + format := t.Propagation + if format == nil { + format = defaultFormat + } + rt = &traceTransport{ + base: rt, + format: format, + startOptions: trace.StartOptions{ + Sampler: t.StartOptions.Sampler, + SpanKind: trace.SpanKindClient, + }, + } + rt = statsTransport{base: rt} + return rt.RoundTrip(req) +} + +func (t *Transport) base() http.RoundTripper { + if t.Base != nil { + return t.Base + } + return http.DefaultTransport +} + +// CancelRequest cancels an in-flight request by closing its connection. +func (t *Transport) CancelRequest(req *http.Request) { + type canceler interface { + CancelRequest(*http.Request) + } + if cr, ok := t.base().(canceler); ok { + cr.CancelRequest(req) + } +} diff --git a/go.opencensus.io/plugin/ochttp/client_stats.go b/go.opencensus.io/plugin/ochttp/client_stats.go new file mode 100644 index 00000000..9b286b92 --- /dev/null +++ b/go.opencensus.io/plugin/ochttp/client_stats.go @@ -0,0 +1,125 @@ +// Copyright 2018, OpenCensus 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 ochttp + +import ( + "context" + "io" + "net/http" + "strconv" + "sync" + "time" + + "go.opencensus.io/stats" + "go.opencensus.io/tag" +) + +// statsTransport is an http.RoundTripper that collects stats for the outgoing requests. +type statsTransport struct { + base http.RoundTripper +} + +// RoundTrip implements http.RoundTripper, delegating to Base and recording stats for the request. +func (t statsTransport) RoundTrip(req *http.Request) (*http.Response, error) { + ctx, _ := tag.New(req.Context(), + tag.Upsert(Host, req.URL.Host), + tag.Upsert(Path, req.URL.Path), + tag.Upsert(Method, req.Method)) + req = req.WithContext(ctx) + track := &tracker{ + start: time.Now(), + ctx: ctx, + } + if req.Body == nil { + // TODO: Handle cases where ContentLength is not set. + track.reqSize = -1 + } else if req.ContentLength > 0 { + track.reqSize = req.ContentLength + } + stats.Record(ctx, ClientRequestCount.M(1)) + + // Perform request. + resp, err := t.base.RoundTrip(req) + + if err != nil { + track.statusCode = http.StatusInternalServerError + track.end() + } else { + track.statusCode = resp.StatusCode + if resp.Body == nil { + track.end() + } else { + track.body = resp.Body + resp.Body = track + } + } + return resp, err +} + +// CancelRequest cancels an in-flight request by closing its connection. +func (t statsTransport) CancelRequest(req *http.Request) { + type canceler interface { + CancelRequest(*http.Request) + } + if cr, ok := t.base.(canceler); ok { + cr.CancelRequest(req) + } +} + +type tracker struct { + ctx context.Context + respSize int64 + reqSize int64 + start time.Time + body io.ReadCloser + statusCode int + endOnce sync.Once +} + +var _ io.ReadCloser = (*tracker)(nil) + +func (t *tracker) end() { + t.endOnce.Do(func() { + m := []stats.Measurement{ + ClientLatency.M(float64(time.Since(t.start)) / float64(time.Millisecond)), + ClientResponseBytes.M(t.respSize), + } + if t.reqSize >= 0 { + m = append(m, ClientRequestBytes.M(t.reqSize)) + } + ctx, _ := tag.New(t.ctx, tag.Upsert(StatusCode, strconv.Itoa(t.statusCode))) + stats.Record(ctx, m...) + }) +} + +func (t *tracker) Read(b []byte) (int, error) { + n, err := t.body.Read(b) + switch err { + case nil: + t.respSize += int64(n) + return n, nil + case io.EOF: + t.end() + } + return n, err +} + +func (t *tracker) Close() error { + // Invoking endSpan on Close will help catch the cases + // in which a read returned a non-nil error, we set the + // span status but didn't end the span. + t.end() + return t.body.Close() +} diff --git a/go.opencensus.io/plugin/ochttp/doc.go b/go.opencensus.io/plugin/ochttp/doc.go new file mode 100644 index 00000000..10e626b1 --- /dev/null +++ b/go.opencensus.io/plugin/ochttp/doc.go @@ -0,0 +1,19 @@ +// Copyright 2018, OpenCensus 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 ochttp provides OpenCensus instrumentation for net/http package. +// +// For server instrumentation, see Handler. For client-side instrumentation, +// see Transport. +package ochttp // import "go.opencensus.io/plugin/ochttp" diff --git a/go.opencensus.io/plugin/ochttp/propagation/b3/b3.go b/go.opencensus.io/plugin/ochttp/propagation/b3/b3.go new file mode 100644 index 00000000..ddc99460 --- /dev/null +++ b/go.opencensus.io/plugin/ochttp/propagation/b3/b3.go @@ -0,0 +1,119 @@ +// Copyright 2018, OpenCensus 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 b3 contains a propagation.HTTPFormat implementation +// for B3 propagation. See https://github.com/openzipkin/b3-propagation +// for more details. +package b3 + +import ( + "encoding/hex" + "net/http" + + "go.opencensus.io/trace" + "go.opencensus.io/trace/propagation" +) + +const ( + traceIDHeader = "X-B3-TraceId" + spanIDHeader = "X-B3-SpanId" + sampledHeader = "X-B3-Sampled" +) + +// HTTPFormat implements propagation.HTTPFormat to propagate +// traces in HTTP headers in B3 propagation format. +// HTTPFormat skips the X-B3-ParentId and X-B3-Flags headers +// because there are additional fields not represented in the +// OpenCensus span context. Spans created from the incoming +// header will be the direct children of the client-side span. +// Similarly, reciever of the outgoing spans should use client-side +// span created by OpenCensus as the parent. +type HTTPFormat struct{} + +var _ propagation.HTTPFormat = (*HTTPFormat)(nil) + +// SpanContextFromRequest extracts a B3 span context from incoming requests. +func (f *HTTPFormat) SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool) { + tid, ok := parseTraceID(req.Header.Get(traceIDHeader)) + if !ok { + return trace.SpanContext{}, false + } + sid, ok := parseSpanID(req.Header.Get(spanIDHeader)) + if !ok { + return trace.SpanContext{}, false + } + sampled, _ := parseSampled(req.Header.Get(sampledHeader)) + return trace.SpanContext{ + TraceID: tid, + SpanID: sid, + TraceOptions: sampled, + }, true +} + +func parseTraceID(tid string) (trace.TraceID, bool) { + if tid == "" { + return trace.TraceID{}, false + } + b, err := hex.DecodeString(tid) + if err != nil { + return trace.TraceID{}, false + } + var traceID trace.TraceID + if len(b) <= 8 { + // The lower 64-bits. + start := 8 + (8 - len(b)) + copy(traceID[start:], b) + } else { + start := 16 - len(b) + copy(traceID[start:], b) + } + + return traceID, true +} + +func parseSpanID(sid string) (spanID trace.SpanID, ok bool) { + if sid == "" { + return trace.SpanID{}, false + } + b, err := hex.DecodeString(sid) + if err != nil { + return trace.SpanID{}, false + } + start := (8 - len(b)) + copy(spanID[start:], b) + return spanID, true +} + +func parseSampled(sampled string) (trace.TraceOptions, bool) { + switch sampled { + case "true", "1": + return trace.TraceOptions(1), true + default: + return trace.TraceOptions(0), false + } +} + +// SpanContextToRequest modifies the given request to include B3 headers. +func (f *HTTPFormat) SpanContextToRequest(sc trace.SpanContext, req *http.Request) { + req.Header.Set(traceIDHeader, hex.EncodeToString(sc.TraceID[:])) + req.Header.Set(spanIDHeader, hex.EncodeToString(sc.SpanID[:])) + + var sampled string + if sc.IsSampled() { + sampled = "1" + } else { + sampled = "0" + } + req.Header.Set(sampledHeader, sampled) +} diff --git a/go.opencensus.io/plugin/ochttp/server.go b/go.opencensus.io/plugin/ochttp/server.go new file mode 100644 index 00000000..b402a65f --- /dev/null +++ b/go.opencensus.io/plugin/ochttp/server.go @@ -0,0 +1,180 @@ +// Copyright 2018, OpenCensus 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 ochttp + +import ( + "context" + "net/http" + "strconv" + "sync" + "time" + + "go.opencensus.io/stats" + "go.opencensus.io/tag" + "go.opencensus.io/trace" + "go.opencensus.io/trace/propagation" +) + +// Handler is a http.Handler that is aware of the incoming request's span. +// +// The extracted span can be accessed from the incoming request's +// context. +// +// span := trace.FromContext(r.Context()) +// +// The server span will be automatically ended at the end of ServeHTTP. +// +// Incoming propagation mechanism is determined by the given HTTP propagators. +type Handler struct { + // Propagation defines how traces are propagated. If unspecified, + // B3 propagation will be used. + Propagation propagation.HTTPFormat + + // Handler is the handler used to handle the incoming request. + Handler http.Handler + + // StartOptions are applied to the span started by this Handler around each + // request. + // + // StartOptions.SpanKind will always be set to trace.SpanKindServer + // for spans started by this transport. + StartOptions trace.StartOptions + + // IsPublicEndpoint should be set to true for publicly accessible HTTP(S) + // servers. If true, any trace metadata set on the incoming request will + // be added as a linked trace instead of being added as a parent of the + // current trace. + IsPublicEndpoint bool +} + +func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + var traceEnd, statsEnd func() + r, traceEnd = h.startTrace(w, r) + defer traceEnd() + w, statsEnd = h.startStats(w, r) + defer statsEnd() + + handler := h.Handler + if handler == nil { + handler = http.DefaultServeMux + } + handler.ServeHTTP(w, r) +} + +func (h *Handler) startTrace(w http.ResponseWriter, r *http.Request) (*http.Request, func()) { + opts := trace.StartOptions{ + Sampler: h.StartOptions.Sampler, + SpanKind: trace.SpanKindServer, + } + + name := spanNameFromURL(r.URL) + ctx := r.Context() + var span *trace.Span + sc, ok := h.extractSpanContext(r) + if ok && !h.IsPublicEndpoint { + span = trace.NewSpanWithRemoteParent(name, sc, opts) + ctx = trace.WithSpan(ctx, span) + } else { + span = trace.NewSpan(name, nil, opts) + if ok { + span.AddLink(trace.Link{ + TraceID: sc.TraceID, + SpanID: sc.SpanID, + Type: trace.LinkTypeChild, + Attributes: nil, + }) + } + } + ctx = trace.WithSpan(ctx, span) + span.AddAttributes(requestAttrs(r)...) + return r.WithContext(trace.WithSpan(r.Context(), span)), span.End +} + +func (h *Handler) extractSpanContext(r *http.Request) (trace.SpanContext, bool) { + if h.Propagation == nil { + return defaultFormat.SpanContextFromRequest(r) + } + return h.Propagation.SpanContextFromRequest(r) +} + +func (h *Handler) startStats(w http.ResponseWriter, r *http.Request) (http.ResponseWriter, func()) { + ctx, _ := tag.New(r.Context(), + tag.Upsert(Host, r.URL.Host), + tag.Upsert(Path, r.URL.Path), + tag.Upsert(Method, r.Method)) + track := &trackingResponseWriter{ + start: time.Now(), + ctx: ctx, + writer: w, + } + if r.Body == nil { + // TODO: Handle cases where ContentLength is not set. + track.reqSize = -1 + } else if r.ContentLength > 0 { + track.reqSize = r.ContentLength + } + stats.Record(ctx, ServerRequestCount.M(1)) + return track, track.end +} + +type trackingResponseWriter struct { + ctx context.Context + reqSize int64 + respSize int64 + start time.Time + statusCode int + endOnce sync.Once + writer http.ResponseWriter +} + +var _ http.ResponseWriter = (*trackingResponseWriter)(nil) + +func (t *trackingResponseWriter) end() { + t.endOnce.Do(func() { + if t.statusCode == 0 { + t.statusCode = 200 + } + m := []stats.Measurement{ + ServerLatency.M(float64(time.Since(t.start)) / float64(time.Millisecond)), + ServerResponseBytes.M(t.respSize), + } + if t.reqSize >= 0 { + m = append(m, ServerRequestBytes.M(t.reqSize)) + } + ctx, _ := tag.New(t.ctx, tag.Upsert(StatusCode, strconv.Itoa(t.statusCode))) + stats.Record(ctx, m...) + }) +} + +func (t *trackingResponseWriter) Header() http.Header { + return t.writer.Header() +} + +func (t *trackingResponseWriter) Write(data []byte) (int, error) { + n, err := t.writer.Write(data) + t.respSize += int64(n) + return n, err +} + +func (t *trackingResponseWriter) WriteHeader(statusCode int) { + t.writer.WriteHeader(statusCode) + t.statusCode = statusCode +} + +func (t *trackingResponseWriter) Flush() { + if flusher, ok := t.writer.(http.Flusher); ok { + flusher.Flush() + } +} diff --git a/go.opencensus.io/plugin/ochttp/stats.go b/go.opencensus.io/plugin/ochttp/stats.go new file mode 100644 index 00000000..02858a5f --- /dev/null +++ b/go.opencensus.io/plugin/ochttp/stats.go @@ -0,0 +1,173 @@ +// Copyright 2018, OpenCensus 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 ochttp + +import ( + "go.opencensus.io/stats" + "go.opencensus.io/stats/view" + "go.opencensus.io/tag" +) + +// The following client HTTP measures are supported for use in custom views. +var ( + ClientRequestCount, _ = stats.Int64("opencensus.io/http/client/request_count", "Number of HTTP requests started", stats.UnitNone) + ClientRequestBytes, _ = stats.Int64("opencensus.io/http/client/request_bytes", "HTTP request body size if set as ContentLength (uncompressed)", stats.UnitBytes) + ClientResponseBytes, _ = stats.Int64("opencensus.io/http/client/response_bytes", "HTTP response body size (uncompressed)", stats.UnitBytes) + ClientLatency, _ = stats.Float64("opencensus.io/http/client/latency", "End-to-end latency", stats.UnitMilliseconds) +) + +// The following server HTTP measures are supported for use in custom views: +var ( + ServerRequestCount, _ = stats.Int64("opencensus.io/http/server/request_count", "Number of HTTP requests started", stats.UnitNone) + ServerRequestBytes, _ = stats.Int64("opencensus.io/http/server/request_bytes", "HTTP request body size if set as ContentLength (uncompressed)", stats.UnitBytes) + ServerResponseBytes, _ = stats.Int64("opencensus.io/http/server/response_bytes", "HTTP response body size (uncompressed)", stats.UnitBytes) + ServerLatency, _ = stats.Float64("opencensus.io/http/server/latency", "End-to-end latency", stats.UnitMilliseconds) +) + +// The following tags are applied to stats recorded by this package. Host, Path +// and Method are applied to all measures. StatusCode is not applied to +// ClientRequestCount or ServerRequestCount, since it is recorded before the status is known. +var ( + // Host is the value of the HTTP Host header. + Host, _ = tag.NewKey("http.host") + + // StatusCode is the numeric HTTP response status code, + // or "error" if a transport error occurred and no status code was read. + StatusCode, _ = tag.NewKey("http.status") + + // Path is the URL path (not including query string) in the request. + Path, _ = tag.NewKey("http.path") + + // Method is the HTTP method of the request, capitalized (GET, POST, etc.). + Method, _ = tag.NewKey("http.method") +) + +// Default distributions used by views in this package. +var ( + DefaultSizeDistribution = view.Distribution(0, 1024, 2048, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216, 67108864, 268435456, 1073741824, 4294967296) + DefaultLatencyDistribution = view.Distribution(0, 1, 2, 3, 4, 5, 6, 8, 10, 13, 16, 20, 25, 30, 40, 50, 65, 80, 100, 130, 160, 200, 250, 300, 400, 500, 650, 800, 1000, 2000, 5000, 10000, 20000, 50000, 100000) +) + +// Package ochttp provides some convenience views. +// You need to subscribe to the views for data to actually be collected. +var ( + ClientRequestCountView = &view.View{ + Name: "opencensus.io/http/client/request_count", + Description: "Count of HTTP requests started", + Measure: ClientRequestCount, + Aggregation: view.Count(), + } + + ClientRequestBytesView = &view.View{ + Name: "opencensus.io/http/client/request_bytes", + Description: "Size distribution of HTTP request body", + Measure: ClientRequestBytes, + Aggregation: DefaultSizeDistribution, + } + + ClientResponseBytesView = &view.View{ + Name: "opencensus.io/http/client/response_bytes", + Description: "Size distribution of HTTP response body", + Measure: ClientResponseBytes, + Aggregation: DefaultSizeDistribution, + } + + ClientLatencyView = &view.View{ + Name: "opencensus.io/http/client/latency", + Description: "Latency distribution of HTTP requests", + Measure: ClientLatency, + Aggregation: DefaultLatencyDistribution, + } + + ClientRequestCountByMethod = &view.View{ + Name: "opencensus.io/http/client/request_count_by_method", + Description: "Client request count by HTTP method", + TagKeys: []tag.Key{Method}, + Measure: ClientRequestCount, + Aggregation: view.Count(), + } + + ClientResponseCountByStatusCode = &view.View{ + Name: "opencensus.io/http/client/response_count_by_status_code", + Description: "Client response count by status code", + TagKeys: []tag.Key{StatusCode}, + Measure: ClientLatency, + Aggregation: view.Count(), + } + + ServerRequestCountView = &view.View{ + Name: "opencensus.io/http/server/request_count", + Description: "Count of HTTP requests started", + Measure: ServerRequestCount, + Aggregation: view.Count(), + } + + ServerRequestBytesView = &view.View{ + Name: "opencensus.io/http/server/request_bytes", + Description: "Size distribution of HTTP request body", + Measure: ServerRequestBytes, + Aggregation: DefaultSizeDistribution, + } + + ServerResponseBytesView = &view.View{ + Name: "opencensus.io/http/server/response_bytes", + Description: "Size distribution of HTTP response body", + Measure: ServerResponseBytes, + Aggregation: DefaultSizeDistribution, + } + + ServerLatencyView = &view.View{ + Name: "opencensus.io/http/server/latency", + Description: "Latency distribution of HTTP requests", + Measure: ServerLatency, + Aggregation: DefaultLatencyDistribution, + } + + ServerRequestCountByMethod = &view.View{ + Name: "opencensus.io/http/server/request_count_by_method", + Description: "Server request count by HTTP method", + TagKeys: []tag.Key{Method}, + Measure: ServerRequestCount, + Aggregation: view.Count(), + } + + ServerResponseCountByStatusCode = &view.View{ + Name: "opencensus.io/http/server/response_count_by_status_code", + Description: "Server response count by status code", + TagKeys: []tag.Key{StatusCode}, + Measure: ServerLatency, + Aggregation: view.Count(), + } +) + +// DefaultClientViews are the default client views provided by this package. +var DefaultClientViews = []*view.View{ + ClientRequestCountView, + ClientRequestBytesView, + ClientResponseBytesView, + ClientLatencyView, + ClientRequestCountByMethod, + ClientResponseCountByStatusCode, +} + +// DefaultServerViews are the default server views provided by this package. +var DefaultServerViews = []*view.View{ + ServerRequestCountView, + ServerRequestBytesView, + ServerResponseBytesView, + ServerLatencyView, + ServerRequestCountByMethod, + ServerResponseCountByStatusCode, +} diff --git a/go.opencensus.io/plugin/ochttp/trace.go b/go.opencensus.io/plugin/ochttp/trace.go new file mode 100644 index 00000000..10d4a706 --- /dev/null +++ b/go.opencensus.io/plugin/ochttp/trace.go @@ -0,0 +1,215 @@ +// Copyright 2018, OpenCensus 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 ochttp + +import ( + "io" + "net/http" + "net/url" + + "go.opencensus.io/plugin/ochttp/propagation/b3" + "go.opencensus.io/trace" + "go.opencensus.io/trace/propagation" +) + +// TODO(jbd): Add godoc examples. + +var defaultFormat propagation.HTTPFormat = &b3.HTTPFormat{} + +// Attributes recorded on the span for the requests. +// Only trace exporters will need them. +const ( + HostAttribute = "http.host" + MethodAttribute = "http.method" + PathAttribute = "http.path" + UserAgentAttribute = "http.user_agent" + StatusCodeAttribute = "http.status_code" +) + +type traceTransport struct { + base http.RoundTripper + startOptions trace.StartOptions + format propagation.HTTPFormat +} + +// TODO(jbd): Add message events for request and response size. + +// RoundTrip creates a trace.Span and inserts it into the outgoing request's headers. +// The created span can follow a parent span, if a parent is presented in +// the request's context. +func (t *traceTransport) RoundTrip(req *http.Request) (*http.Response, error) { + name := spanNameFromURL(req.URL) + // TODO(jbd): Discuss whether we want to prefix + // outgoing requests with Sent. + parent := trace.FromContext(req.Context()) + span := trace.NewSpan(name, parent, t.startOptions) + req = req.WithContext(trace.WithSpan(req.Context(), span)) + + if t.format != nil { + t.format.SpanContextToRequest(span.SpanContext(), req) + } + + span.AddAttributes(requestAttrs(req)...) + resp, err := t.base.RoundTrip(req) + if err != nil { + span.SetStatus(trace.Status{Code: 2, Message: err.Error()}) + span.End() + return resp, err + } + + span.AddAttributes(responseAttrs(resp)...) + span.SetStatus(status(resp.StatusCode)) + + // span.End() will be invoked after + // a read from resp.Body returns io.EOF or when + // resp.Body.Close() is invoked. + resp.Body = &bodyTracker{rc: resp.Body, span: span} + return resp, err +} + +// bodyTracker wraps a response.Body and invokes +// trace.EndSpan on encountering io.EOF on reading +// the body of the original response. +type bodyTracker struct { + rc io.ReadCloser + span *trace.Span +} + +var _ io.ReadCloser = (*bodyTracker)(nil) + +func (bt *bodyTracker) Read(b []byte) (int, error) { + n, err := bt.rc.Read(b) + + switch err { + case nil: + return n, nil + case io.EOF: + bt.span.End() + default: + // For all other errors, set the span status + bt.span.SetStatus(trace.Status{ + // Code 2 is the error code for Internal server error. + Code: 2, + Message: err.Error(), + }) + } + return n, err +} + +func (bt *bodyTracker) Close() error { + // Invoking endSpan on Close will help catch the cases + // in which a read returned a non-nil error, we set the + // span status but didn't end the span. + bt.span.End() + return bt.rc.Close() +} + +// CancelRequest cancels an in-flight request by closing its connection. +func (t *traceTransport) CancelRequest(req *http.Request) { + type canceler interface { + CancelRequest(*http.Request) + } + if cr, ok := t.base.(canceler); ok { + cr.CancelRequest(req) + } +} + +func spanNameFromURL(u *url.URL) string { + return u.Path +} + +func requestAttrs(r *http.Request) []trace.Attribute { + return []trace.Attribute{ + trace.StringAttribute(PathAttribute, r.URL.Path), + trace.StringAttribute(HostAttribute, r.URL.Host), + trace.StringAttribute(MethodAttribute, r.Method), + trace.StringAttribute(UserAgentAttribute, r.UserAgent()), + } +} + +func responseAttrs(resp *http.Response) []trace.Attribute { + return []trace.Attribute{ + trace.Int64Attribute(StatusCodeAttribute, int64(resp.StatusCode)), + } +} + +func status(statusCode int) trace.Status { + var code int32 + if statusCode < 200 || statusCode >= 400 { + code = codeUnknown + } + switch statusCode { + case 499: + code = codeCancelled + case http.StatusBadRequest: + code = codeInvalidArgument + case http.StatusGatewayTimeout: + code = codeDeadlineExceeded + case http.StatusNotFound: + code = codeNotFound + case http.StatusForbidden: + code = codePermissionDenied + case http.StatusUnauthorized: // 401 is actually unauthenticated. + code = codeUnathenticated + case http.StatusTooManyRequests: + code = codeResourceExhausted + case http.StatusNotImplemented: + code = codeUnimplemented + case http.StatusServiceUnavailable: + code = codeUnavailable + } + return trace.Status{Code: code, Message: codeToStr[code]} +} + +// TODO(jbd): Provide status codes from trace package. +const ( + codeOK = 0 + codeCancelled = 1 + codeUnknown = 2 + codeInvalidArgument = 3 + codeDeadlineExceeded = 4 + codeNotFound = 5 + codeAlreadyExists = 6 + codePermissionDenied = 7 + codeResourceExhausted = 8 + codeFailedPrecondition = 9 + codeAborted = 10 + codeOutOfRange = 11 + codeUnimplemented = 12 + codeInternal = 13 + codeUnavailable = 14 + codeDataLoss = 15 + codeUnathenticated = 16 +) + +var codeToStr = map[int32]string{ + codeOK: `"OK"`, + codeCancelled: `"CANCELLED"`, + codeUnknown: `"UNKNOWN"`, + codeInvalidArgument: `"INVALID_ARGUMENT"`, + codeDeadlineExceeded: `"DEADLINE_EXCEEDED"`, + codeNotFound: `"NOT_FOUND"`, + codeAlreadyExists: `"ALREADY_EXISTS"`, + codePermissionDenied: `"PERMISSION_DENIED"`, + codeResourceExhausted: `"RESOURCE_EXHAUSTED"`, + codeFailedPrecondition: `"FAILED_PRECONDITION"`, + codeAborted: `"ABORTED"`, + codeOutOfRange: `"OUT_OF_RANGE"`, + codeUnimplemented: `"UNIMPLEMENTED"`, + codeInternal: `"INTERNAL"`, + codeUnavailable: `"UNAVAILABLE"`, + codeDataLoss: `"DATA_LOSS"`, + codeUnathenticated: `"UNAUTHENTICATED"`, +} diff --git a/go.opencensus.io/stats/doc.go b/go.opencensus.io/stats/doc.go new file mode 100644 index 00000000..7a8a62c1 --- /dev/null +++ b/go.opencensus.io/stats/doc.go @@ -0,0 +1,55 @@ +// Copyright 2017, OpenCensus 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 stats contains support for OpenCensus stats recording. + +OpenCensus allows users to create typed measures, record measurements, +aggregate the collected data, and export the aggregated data. + +Measures + +A measure represents a type of metric to be tracked and recorded. +For example, latency, request Mb/s, and response Mb/s are measures +to collect from a server. + +Each measure needs to be registered before being used. Measure +constructors such as Int64 and Float64 automatically +register the measure by the given name. Each registered measure needs +to be unique by name. Measures also have a description and a unit. + +Libraries can define and export measures for their end users to +create views and collect instrumentation data. + +Recording measurements + +Measurement is a data point to be collected for a measure. For example, +for a latency (ms) measure, 100 is a measurement that represents a 100ms +latency event. Users collect data points on the existing measures with +the current context. Tags from the current context are recorded with the +measurements if they are any. + +Recorded measurements are dropped immediately if user is not aggregating +them via views. Users don't necessarily need to conditionally enable/disable +recording to reduce cost. Recording of measurements is cheap. + +Libraries can always record measurements, and end-users can later decide +on which measurements they want to collect by registering views. This allows +libraries to turn on the instrumentation by default. +*/ +package stats // import "go.opencensus.io/stats" + +// TODO(acetechnologist): Add a link to the language independent OpenCensus +// spec when it is available. diff --git a/go.opencensus.io/stats/internal/record.go b/go.opencensus.io/stats/internal/record.go new file mode 100644 index 00000000..6341eb2a --- /dev/null +++ b/go.opencensus.io/stats/internal/record.go @@ -0,0 +1,25 @@ +// Copyright 2018, OpenCensus 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 ( + "go.opencensus.io/tag" +) + +// DefaultRecorder will be called for each Record call. +var DefaultRecorder func(*tag.Map, interface{}) + +// SubscriptionReporter reports when a view subscribed with a measure. +var SubscriptionReporter func(measure string) diff --git a/go.opencensus.io/stats/internal/validation.go b/go.opencensus.io/stats/internal/validation.go new file mode 100644 index 00000000..b962d524 --- /dev/null +++ b/go.opencensus.io/stats/internal/validation.go @@ -0,0 +1,28 @@ +// Copyright 2018, OpenCensus 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 + +const ( + MaxNameLength = 255 +) + +func IsPrintable(str string) bool { + for _, r := range str { + if !(r >= ' ' && r <= '~') { + return false + } + } + return true +} diff --git a/go.opencensus.io/stats/measure.go b/go.opencensus.io/stats/measure.go new file mode 100644 index 00000000..ad00aff2 --- /dev/null +++ b/go.opencensus.io/stats/measure.go @@ -0,0 +1,132 @@ +// Copyright 2017, OpenCensus 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 stats + +import ( + "errors" + "fmt" + "sync" + "sync/atomic" + + "go.opencensus.io/stats/internal" +) + +// Measure represents a type of metric to be tracked and recorded. +// For example, latency, request Mb/s, and response Mb/s are measures +// to collect from a server. +// +// Each measure needs to be registered before being used. +// Measure constructors such as Int64 and +// Float64 automatically registers the measure +// by the given name. +// Each registered measure needs to be unique by name. +// Measures also have a description and a unit. +type Measure interface { + Name() string + Description() string + Unit() string + + subscribe() + subscribed() bool +} + +type measure struct { + subs int32 // access atomically + + name string + description string + unit string +} + +func (m *measure) subscribe() { + atomic.StoreInt32(&m.subs, 1) +} + +func (m *measure) subscribed() bool { + return atomic.LoadInt32(&m.subs) == 1 +} + +// Name returns the name of the measure. +func (m *measure) Name() string { + return m.name +} + +// Description returns the description of the measure. +func (m *measure) Description() string { + return m.description +} + +// Unit returns the unit of the measure. +func (m *measure) Unit() string { + return m.unit +} + +var ( + mu sync.RWMutex + measures = make(map[string]Measure) +) + +var ( + errDuplicate = errors.New("duplicate measure name") + errMeasureNameTooLong = fmt.Errorf("measure name cannot be longer than %v", internal.MaxNameLength) +) + +// FindMeasure finds the Measure instance, if any, associated with the given name. +func FindMeasure(name string) Measure { + mu.RLock() + m := measures[name] + mu.RUnlock() + return m +} + +func register(m Measure) (Measure, error) { + key := m.Name() + mu.Lock() + defer mu.Unlock() + if stored, ok := measures[key]; ok { + return stored, errDuplicate + } + measures[key] = m + return m, nil +} + +// Measurement is the numeric value measured when recording stats. Each measure +// provides methods to create measurements of their kind. For example, Int64Measure +// provides M to convert an int64 into a measurement. +type Measurement struct { + v float64 + m Measure +} + +// Value returns the value of the Measurement as a float64. +func (m Measurement) Value() float64 { + return m.v +} + +// Measure returns the Measure from which this Measurement was created. +func (m Measurement) Measure() Measure { + return m.m +} + +func checkName(name string) error { + if len(name) > internal.MaxNameLength { + return errMeasureNameTooLong + } + if !internal.IsPrintable(name) { + return errors.New("measure name needs to be an ASCII string") + } + return nil +} diff --git a/go.opencensus.io/stats/measure_float64.go b/go.opencensus.io/stats/measure_float64.go new file mode 100644 index 00000000..7009ceea --- /dev/null +++ b/go.opencensus.io/stats/measure_float64.go @@ -0,0 +1,57 @@ +// Copyright 2017, OpenCensus 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 stats + +// Float64Measure is a measure of type float64. +type Float64Measure struct { + measure +} + +func (m *Float64Measure) subscribe() { + m.measure.subscribe() +} + +func (m *Float64Measure) subscribed() bool { + return m.measure.subscribed() +} + +// M creates a new float64 measurement. +// Use Record to record measurements. +func (m *Float64Measure) M(v float64) Measurement { + if !m.subscribed() { + return Measurement{} + } + return Measurement{m: m, v: v} +} + +// Float64 creates a new measure of type Float64Measure. It returns +// an error if a measure with the same name already exists. +func Float64(name, description, unit string) (*Float64Measure, error) { + if err := checkName(name); err != nil { + return nil, err + } + m := &Float64Measure{ + measure: measure{ + name: name, + description: description, + unit: unit, + }, + } + if _, err := register(m); err != nil { + return nil, err + } + return m, nil +} diff --git a/go.opencensus.io/stats/measure_int64.go b/go.opencensus.io/stats/measure_int64.go new file mode 100644 index 00000000..5b820b6a --- /dev/null +++ b/go.opencensus.io/stats/measure_int64.go @@ -0,0 +1,57 @@ +// Copyright 2017, OpenCensus 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 stats + +// Int64Measure is a measure of type int64. +type Int64Measure struct { + measure +} + +func (m *Int64Measure) subscribe() { + m.measure.subscribe() +} + +func (m *Int64Measure) subscribed() bool { + return m.measure.subscribed() +} + +// M creates a new int64 measurement. +// Use Record to record measurements. +func (m *Int64Measure) M(v int64) Measurement { + if !m.subscribed() { + return Measurement{} + } + return Measurement{m: m, v: float64(v)} +} + +// Int64 creates a new measure of type Int64Measure. It returns an +// error if a measure with the same name already exists. +func Int64(name, description, unit string) (*Int64Measure, error) { + if err := checkName(name); err != nil { + return nil, err + } + m := &Int64Measure{ + measure: measure{ + name: name, + description: description, + unit: unit, + }, + } + if _, err := register(m); err != nil { + return nil, err + } + return m, nil +} diff --git a/go.opencensus.io/stats/record.go b/go.opencensus.io/stats/record.go new file mode 100644 index 00000000..98865ff6 --- /dev/null +++ b/go.opencensus.io/stats/record.go @@ -0,0 +1,52 @@ +// Copyright 2018, OpenCensus 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 stats + +import ( + "context" + + "go.opencensus.io/stats/internal" + "go.opencensus.io/tag" +) + +func init() { + internal.SubscriptionReporter = func(measure string) { + mu.Lock() + measures[measure].subscribe() + mu.Unlock() + } +} + +// Record records one or multiple measurements with the same tags at once. +// If there are any tags in the context, measurements will be tagged with them. +func Record(ctx context.Context, ms ...Measurement) { + if len(ms) == 0 { + return + } + var record bool + for _, m := range ms { + if (m != Measurement{}) { + record = true + break + } + } + if !record { + return + } + if internal.DefaultRecorder != nil { + internal.DefaultRecorder(tag.FromContext(ctx), ms) + } +} diff --git a/go.opencensus.io/stats/units.go b/go.opencensus.io/stats/units.go new file mode 100644 index 00000000..d37e2152 --- /dev/null +++ b/go.opencensus.io/stats/units.go @@ -0,0 +1,24 @@ +// Copyright 2018, OpenCensus 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 stats + +// Units are encoded according to the case-sensitive abbreviations from the +// Unified Code for Units of Measure: http://unitsofmeasure.org/ucum.html +const ( + UnitNone = "1" + UnitBytes = "By" + UnitMilliseconds = "ms" +) diff --git a/go.opencensus.io/stats/view/aggregation.go b/go.opencensus.io/stats/view/aggregation.go new file mode 100644 index 00000000..3ae6d02b --- /dev/null +++ b/go.opencensus.io/stats/view/aggregation.go @@ -0,0 +1,112 @@ +// Copyright 2017, OpenCensus 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 view + +//go:generate stringer -type AggType + +// AggType represents the type of aggregation function used on a View. +type AggType int + +const ( + AggTypeNone AggType = iota // no aggregation; reserved for future use. + AggTypeCount // the count aggregation, see Count. + AggTypeSum // the sum aggregation, see Sum. + AggTypeMean // the mean aggregation, see Mean. + AggTypeDistribution // the distribution aggregation, see Distribution. +) + +// Aggregation represents a data aggregation method. Use one of the functions: +// Count, Sum, Mean, or Distribution to construct an Aggregation. +type Aggregation struct { + Type AggType // Type is the AggType of this Aggregation. + Buckets []float64 // Buckets are the bucket endpoints if this Aggregation represents a distribution, see Distribution. + + newData func() AggregationData +} + +var ( + aggCount = &Aggregation{ + Type: AggTypeCount, + newData: func() AggregationData { + return newCountData(0) + }, + } + aggSum = &Aggregation{ + Type: AggTypeSum, + newData: func() AggregationData { + return newSumData(0) + }, + } + aggMean = &Aggregation{ + Type: AggTypeMean, + newData: func() AggregationData { + return newMeanData(0, 0) + }, + } +) + +// Count indicates that data collected and aggregated +// with this method will be turned into a count value. +// For example, total number of accepted requests can be +// aggregated by using Count. +func Count() *Aggregation { + return aggCount +} + +// Sum indicates that data collected and aggregated +// with this method will be summed up. +// For example, accumulated request bytes can be aggregated by using +// Sum. +func Sum() *Aggregation { + return aggSum +} + +// Mean indicates that collect and aggregate data and maintain +// the mean value. +// For example, average latency in milliseconds can be aggregated by using +// Mean, although in most cases it is preferable to use a Distribution. +func Mean() *Aggregation { + return aggMean +} + +// Distribution indicates that the desired aggregation is +// a histogram distribution. +// +// An distribution aggregation may contain a histogram of the values in the +// population. The bucket boundaries for that histogram are described +// by the bounds. This defines len(bounds)+1 buckets. +// +// If len(bounds) >= 2 then the boundaries for bucket index i are: +// +// [-infinity, bounds[i]) for i = 0 +// [bounds[i-1], bounds[i]) for 0 < i < length +// [bounds[i-1], +infinity) for i = length +// +// If len(bounds) is 0 then there is no histogram associated with the +// distribution. There will be a single bucket with boundaries +// (-infinity, +infinity). +// +// If len(bounds) is 1 then there is no finite buckets, and that single +// element is the common boundary of the overflow and underflow buckets. +func Distribution(bounds ...float64) *Aggregation { + return &Aggregation{ + Type: AggTypeDistribution, + Buckets: bounds, + newData: func() AggregationData { + return newDistributionData(bounds) + }, + } +} diff --git a/go.opencensus.io/stats/view/aggregation_data.go b/go.opencensus.io/stats/view/aggregation_data.go new file mode 100644 index 00000000..8d74bc47 --- /dev/null +++ b/go.opencensus.io/stats/view/aggregation_data.go @@ -0,0 +1,230 @@ +// Copyright 2017, OpenCensus 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 view + +import ( + "math" +) + +// AggregationData represents an aggregated value from a collection. +// They are reported on the view data during exporting. +// Mosts users won't directly access aggregration data. +type AggregationData interface { + isAggregationData() bool + addSample(v float64) + clone() AggregationData + equal(other AggregationData) bool +} + +const epsilon = 1e-9 + +// CountData is the aggregated data for the Count aggregation. +// A count aggregation processes data and counts the recordings. +// +// Most users won't directly access count data. +type CountData int64 + +func newCountData(v int64) *CountData { + tmp := CountData(v) + return &tmp +} + +func (a *CountData) isAggregationData() bool { return true } + +func (a *CountData) addSample(_ float64) { + *a = *a + 1 +} + +func (a *CountData) clone() AggregationData { + return newCountData(int64(*a)) +} + +func (a *CountData) equal(other AggregationData) bool { + a2, ok := other.(*CountData) + if !ok { + return false + } + + return int64(*a) == int64(*a2) +} + +// SumData is the aggregated data for the Sum aggregation. +// A sum aggregation processes data and sums up the recordings. +// +// Most users won't directly access sum data. +type SumData float64 + +func newSumData(v float64) *SumData { + tmp := SumData(v) + return &tmp +} + +func (a *SumData) isAggregationData() bool { return true } + +func (a *SumData) addSample(f float64) { + *a += SumData(f) +} + +func (a *SumData) clone() AggregationData { + return newSumData(float64(*a)) +} + +func (a *SumData) equal(other AggregationData) bool { + a2, ok := other.(*SumData) + if !ok { + return false + } + return math.Pow(float64(*a)-float64(*a2), 2) < epsilon +} + +// MeanData is the aggregated data for the Mean aggregation. +// A mean aggregation processes data and maintains the mean value. +// +// Most users won't directly access mean data. +type MeanData struct { + Count int64 // number of data points aggregated + Mean float64 // mean of all data points +} + +func newMeanData(mean float64, count int64) *MeanData { + return &MeanData{ + Mean: mean, + Count: count, + } +} + +// Sum returns the sum of all samples collected. +func (a *MeanData) Sum() float64 { return a.Mean * float64(a.Count) } + +func (a *MeanData) isAggregationData() bool { return true } + +func (a *MeanData) addSample(f float64) { + a.Count++ + if a.Count == 1 { + a.Mean = f + return + } + a.Mean = a.Mean + (f-a.Mean)/float64(a.Count) +} + +func (a *MeanData) clone() AggregationData { + return newMeanData(a.Mean, a.Count) +} + +func (a *MeanData) equal(other AggregationData) bool { + a2, ok := other.(*MeanData) + if !ok { + return false + } + return a.Count == a2.Count && math.Pow(a.Mean-a2.Mean, 2) < epsilon +} + +// DistributionData is the aggregated data for the +// Distribution aggregation. +// +// Most users won't directly access distribution data. +type DistributionData struct { + Count int64 // number of data points aggregated + Min float64 // minimum value in the distribution + Max float64 // max value in the distribution + Mean float64 // mean of the distribution + SumOfSquaredDev float64 // sum of the squared deviation from the mean + CountPerBucket []int64 // number of occurrences per bucket + bounds []float64 // histogram distribution of the values +} + +func newDistributionData(bounds []float64) *DistributionData { + return &DistributionData{ + CountPerBucket: make([]int64, len(bounds)+1), + bounds: bounds, + Min: math.MaxFloat64, + Max: math.SmallestNonzeroFloat64, + } +} + +// Sum returns the sum of all samples collected. +func (a *DistributionData) Sum() float64 { return a.Mean * float64(a.Count) } + +func (a *DistributionData) variance() float64 { + if a.Count <= 1 { + return 0 + } + return a.SumOfSquaredDev / float64(a.Count-1) +} + +func (a *DistributionData) isAggregationData() bool { return true } + +func (a *DistributionData) addSample(f float64) { + if f < a.Min { + a.Min = f + } + if f > a.Max { + a.Max = f + } + a.Count++ + a.incrementBucketCount(f) + + if a.Count == 1 { + a.Mean = f + return + } + + oldMean := a.Mean + a.Mean = a.Mean + (f-a.Mean)/float64(a.Count) + a.SumOfSquaredDev = a.SumOfSquaredDev + (f-oldMean)*(f-a.Mean) +} + +func (a *DistributionData) incrementBucketCount(f float64) { + if len(a.bounds) == 0 { + a.CountPerBucket[0]++ + return + } + + for i, b := range a.bounds { + if f < b { + a.CountPerBucket[i]++ + return + } + } + a.CountPerBucket[len(a.bounds)]++ +} + +func (a *DistributionData) clone() AggregationData { + counts := make([]int64, len(a.CountPerBucket)) + copy(counts, a.CountPerBucket) + c := *a + c.CountPerBucket = counts + return &c +} + +func (a *DistributionData) equal(other AggregationData) bool { + a2, ok := other.(*DistributionData) + if !ok { + return false + } + if a2 == nil { + return false + } + if len(a.CountPerBucket) != len(a2.CountPerBucket) { + return false + } + for i := range a.CountPerBucket { + if a.CountPerBucket[i] != a2.CountPerBucket[i] { + return false + } + } + return a.Count == a2.Count && a.Min == a2.Min && a.Max == a2.Max && math.Pow(a.Mean-a2.Mean, 2) < epsilon && math.Pow(a.variance()-a2.variance(), 2) < epsilon +} diff --git a/go.opencensus.io/stats/view/aggtype_string.go b/go.opencensus.io/stats/view/aggtype_string.go new file mode 100644 index 00000000..b6ad7411 --- /dev/null +++ b/go.opencensus.io/stats/view/aggtype_string.go @@ -0,0 +1,16 @@ +// Code generated by "stringer -type AggType"; DO NOT EDIT. + +package view + +import "strconv" + +const _AggType_name = "AggTypeNoneAggTypeCountAggTypeSumAggTypeMeanAggTypeDistribution" + +var _AggType_index = [...]uint8{0, 11, 23, 33, 44, 63} + +func (i AggType) String() string { + if i < 0 || i >= AggType(len(_AggType_index)-1) { + return "AggType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _AggType_name[_AggType_index[i]:_AggType_index[i+1]] +} diff --git a/go.opencensus.io/stats/view/collector.go b/go.opencensus.io/stats/view/collector.go new file mode 100644 index 00000000..863a5b62 --- /dev/null +++ b/go.opencensus.io/stats/view/collector.go @@ -0,0 +1,84 @@ +// Copyright 2017, OpenCensus 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 view + +import ( + "sort" + + "go.opencensus.io/internal/tagencoding" + "go.opencensus.io/tag" +) + +type collector struct { + // signatures holds the aggregations values for each unique tag signature + // (values for all keys) to its aggregator. + signatures map[string]AggregationData + // Aggregation is the description of the aggregation to perform for this + // view. + a *Aggregation +} + +func (c *collector) addSample(s string, v float64) { + aggregator, ok := c.signatures[s] + if !ok { + aggregator = c.a.newData() + c.signatures[s] = aggregator + } + aggregator.addSample(v) +} + +func (c *collector) collectedRows(keys []tag.Key) []*Row { + var rows []*Row + for sig, aggregator := range c.signatures { + tags := decodeTags([]byte(sig), keys) + row := &Row{tags, aggregator} + rows = append(rows, row) + } + return rows +} + +func (c *collector) clearRows() { + c.signatures = make(map[string]AggregationData) +} + +// encodeWithKeys encodes the map by using values +// only associated with the keys provided. +func encodeWithKeys(m *tag.Map, keys []tag.Key) []byte { + vb := &tagencoding.Values{ + Buffer: make([]byte, len(keys)), + } + for _, k := range keys { + v, _ := m.Value(k) + vb.WriteValue([]byte(v)) + } + return vb.Bytes() +} + +// decodeTags decodes tags from the buffer and +// orders them by the keys. +func decodeTags(buf []byte, keys []tag.Key) []tag.Tag { + vb := &tagencoding.Values{Buffer: buf} + var tags []tag.Tag + for _, k := range keys { + v := vb.ReadValue() + if v != nil { + tags = append(tags, tag.Tag{Key: k, Value: string(v)}) + } + } + vb.ReadIndex = 0 + sort.Slice(tags, func(i, j int) bool { return tags[i].Key.Name() < tags[j].Key.Name() }) + return tags +} diff --git a/go.opencensus.io/stats/view/doc.go b/go.opencensus.io/stats/view/doc.go new file mode 100644 index 00000000..fcaae6ef --- /dev/null +++ b/go.opencensus.io/stats/view/doc.go @@ -0,0 +1,47 @@ +// Copyright 2017, OpenCensus 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 view contains support for collecting and exposing aggregates over stats. + +In order to collect measurements, views need to be defined and registered. +A view allows recorded measurements to be filtered and aggregated over a time window. + +All recorded measurements can be filtered by a list of tags. + +OpenCensus provides several aggregation methods: count, distribution, sum and mean. +Count aggregation only counts the number of measurement points. Distribution +aggregation provides statistical summary of the aggregated data. Sum distribution +sums up the measurement points. Mean provides the mean of the recorded measurements. +Aggregations can either happen cumulatively or over an interval. + +Users can dynamically create and delete views. + +Libraries can export their own views and claim the view names +by registering them themselves. + +Exporting + +Collected and aggregated data can be exported to a metric collection +backend by registering its exporter. + +Multiple exporters can be registered to upload the data to various +different backends. Users need to unregister the exporters once they +no longer are needed. +*/ +package view // import "go.opencensus.io/stats/view" + +// TODO(acetechnologist): Add a link to the language independent OpenCensus +// spec when it is available. diff --git a/go.opencensus.io/stats/view/export.go b/go.opencensus.io/stats/view/export.go new file mode 100644 index 00000000..fac37871 --- /dev/null +++ b/go.opencensus.io/stats/view/export.go @@ -0,0 +1,53 @@ +// Copyright 2017, OpenCensus 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 view + +import "sync" + +var ( + exportersMu sync.RWMutex // guards exporters + exporters = make(map[Exporter]struct{}) +) + +// Exporter exports the collected records as view data. +// +// The ExportView method should return quickly; if an +// Exporter takes a significant amount of time to +// process a Data, that work should be done on another goroutine. +// +// The Data should not be modified. +type Exporter interface { + ExportView(viewData *Data) +} + +// RegisterExporter registers an exporter. +// Collected data will be reported via all the +// registered exporters. Once you no longer +// want data to be exported, invoke UnregisterExporter +// with the previously registered exporter. +func RegisterExporter(e Exporter) { + exportersMu.Lock() + defer exportersMu.Unlock() + + exporters[e] = struct{}{} +} + +// UnregisterExporter unregisters an exporter. +func UnregisterExporter(e Exporter) { + exportersMu.Lock() + defer exportersMu.Unlock() + + delete(exporters, e) +} diff --git a/go.opencensus.io/stats/view/view.go b/go.opencensus.io/stats/view/view.go new file mode 100644 index 00000000..d289b590 --- /dev/null +++ b/go.opencensus.io/stats/view/view.go @@ -0,0 +1,197 @@ +// Copyright 2017, OpenCensus 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 view + +import ( + "bytes" + "fmt" + "reflect" + "sort" + "sync/atomic" + "time" + + "go.opencensus.io/stats" + "go.opencensus.io/stats/internal" + "go.opencensus.io/tag" +) + +// View allows users to aggregate the recorded stats.Measurements. +// Views need to be passed to the Subscribe function to be before data will be +// collected and sent to Exporters. +type View struct { + Name string // Name of View. Must be unique. If unset, will default to the name of the Measure. + Description string // Description is a human-readable description for this view. + + // TagKeys are the tag keys describing the grouping of this view. + // A single Row will be produced for each combination of associated tag values. + TagKeys []tag.Key + + // Measure is a stats.Measure to aggregate in this view. + Measure stats.Measure + + // Aggregation is the aggregation function tp apply to the set of Measurements. + Aggregation *Aggregation +} + +// Deprecated: Use &View{}. +func New(name, description string, keys []tag.Key, measure stats.Measure, agg *Aggregation) (*View, error) { + if measure == nil { + panic("measure may not be nil") + } + return &View{ + Name: name, + Description: description, + TagKeys: keys, + Measure: measure, + Aggregation: agg, + }, nil +} + +// WithName returns a copy of the View with a new name. This is useful for +// renaming views to cope with limitations placed on metric names by various +// backends. +func (v *View) WithName(name string) *View { + vNew := *v + vNew.Name = name + return &vNew +} + +// same compares two views and returns true if they represent the same aggregation. +func (v *View) same(other *View) bool { + if v == other { + return true + } + if v == nil { + return false + } + return reflect.DeepEqual(v.Aggregation, other.Aggregation) && + v.Measure.Name() == other.Measure.Name() +} + +// canonicalized returns a validated View canonicalized by setting explicit +// defaults for Name and Description and sorting the TagKeys +func (v *View) canonicalize() error { + if v.Measure == nil { + return fmt.Errorf("cannot subscribe view %q: measure not set", v.Name) + } + if v.Aggregation == nil { + return fmt.Errorf("cannot subscribe view %q: aggregation not set", v.Name) + } + if v.Name == "" { + v.Name = v.Measure.Name() + } + if v.Description == "" { + v.Description = v.Measure.Description() + } + if err := checkViewName(v.Name); err != nil { + return err + } + sort.Slice(v.TagKeys, func(i, j int) bool { + return v.TagKeys[i].Name() < v.TagKeys[j].Name() + }) + return nil +} + +// viewInternal is the internal representation of a View. +type viewInternal struct { + view *View // view is the canonicalized View definition associated with this view. + subscribed uint32 // 1 if someone is subscribed and data need to be exported, use atomic to access + collector *collector +} + +func newViewInternal(v *View) (*viewInternal, error) { + return &viewInternal{ + view: v, + collector: &collector{make(map[string]AggregationData), v.Aggregation}, + }, nil +} + +func (v *viewInternal) subscribe() { + atomic.StoreUint32(&v.subscribed, 1) +} + +func (v *viewInternal) unsubscribe() { + atomic.StoreUint32(&v.subscribed, 0) +} + +// isSubscribed returns true if the view is exporting +// data by subscription. +func (v *viewInternal) isSubscribed() bool { + return atomic.LoadUint32(&v.subscribed) == 1 +} + +func (v *viewInternal) clearRows() { + v.collector.clearRows() +} + +func (v *viewInternal) collectedRows() []*Row { + return v.collector.collectedRows(v.view.TagKeys) +} + +func (v *viewInternal) addSample(m *tag.Map, val float64) { + if !v.isSubscribed() { + return + } + sig := string(encodeWithKeys(m, v.view.TagKeys)) + v.collector.addSample(sig, val) +} + +// A Data is a set of rows about usage of the single measure associated +// with the given view. Each row is specific to a unique set of tags. +type Data struct { + View *View + Start, End time.Time + Rows []*Row +} + +// Row is the collected value for a specific set of key value pairs a.k.a tags. +type Row struct { + Tags []tag.Tag + Data AggregationData +} + +func (r *Row) String() string { + var buffer bytes.Buffer + buffer.WriteString("{ ") + buffer.WriteString("{ ") + for _, t := range r.Tags { + buffer.WriteString(fmt.Sprintf("{%v %v}", t.Key.Name(), t.Value)) + } + buffer.WriteString(" }") + buffer.WriteString(fmt.Sprintf("%v", r.Data)) + buffer.WriteString(" }") + return buffer.String() +} + +// same returns true if both Rows are equal. Tags are expected to be ordered +// by the key name. Even both rows have the same tags but the tags appear in +// different orders it will return false. +func (r *Row) Equal(other *Row) bool { + if r == other { + return true + } + return reflect.DeepEqual(r.Tags, other.Tags) && r.Data.equal(other.Data) +} + +func checkViewName(name string) error { + if len(name) > internal.MaxNameLength { + return fmt.Errorf("view name cannot be larger than %v", internal.MaxNameLength) + } + if !internal.IsPrintable(name) { + return fmt.Errorf("view name needs to be an ASCII string") + } + return nil +} diff --git a/go.opencensus.io/stats/view/worker.go b/go.opencensus.io/stats/view/worker.go new file mode 100644 index 00000000..2b4f6bee --- /dev/null +++ b/go.opencensus.io/stats/view/worker.go @@ -0,0 +1,257 @@ +// Copyright 2017, OpenCensus 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 view + +import ( + "fmt" + "time" + + "go.opencensus.io/stats" + "go.opencensus.io/stats/internal" + "go.opencensus.io/tag" +) + +func init() { + defaultWorker = newWorker() + go defaultWorker.start() + internal.DefaultRecorder = record +} + +type measureRef struct { + measure string + views map[*viewInternal]struct{} +} + +type worker struct { + measures map[string]*measureRef + views map[string]*viewInternal + startTimes map[*viewInternal]time.Time + + timer *time.Ticker + c chan command + quit, done chan bool +} + +var defaultWorker *worker + +var defaultReportingDuration = 10 * time.Second + +// Find returns a subscribed view associated with this name. +// If no subscribed view is found, nil is returned. +func Find(name string) (v *View) { + req := &getViewByNameReq{ + name: name, + c: make(chan *getViewByNameResp), + } + defaultWorker.c <- req + resp := <-req.c + return resp.v +} + +// Deprecated: Registering is a no-op. Use the Subscribe function. +func Register(_ *View) error { + return nil +} + +// Deprecated: Unregistering is a no-op, see: Unsubscribe. +func Unregister(_ *View) error { + return nil +} + +// Deprecated: Use the Subscribe function. +func (v *View) Subscribe() error { + return Subscribe(v) +} + +// Subscribe begins collecting data for the given views. +// Once a view is subscribed, it reports data to the registered exporters. +func Subscribe(views ...*View) error { + for _, v := range views { + if err := v.canonicalize(); err != nil { + return err + } + } + req := &subscribeToViewReq{ + views: views, + err: make(chan error), + } + defaultWorker.c <- req + return <-req.err +} + +// Unsubscribe the given views. Data will not longer be exported for these views +// after Unsubscribe returns. +// It is not necessary to unsubscribe from views you expect to collect for the +// duration of your program execution. +func Unsubscribe(views ...*View) { + names := make([]string, len(views)) + for i := range views { + names[i] = views[i].Name + } + req := &unsubscribeFromViewReq{ + views: names, + done: make(chan struct{}), + } + defaultWorker.c <- req + <-req.done +} + +// Deprecated: Use the Unsubscribe function instead. +func (v *View) Unsubscribe() error { + if v == nil { + return nil + } + Unsubscribe(v) + return nil +} + +func RetrieveData(viewName string) ([]*Row, error) { + req := &retrieveDataReq{ + now: time.Now(), + v: viewName, + c: make(chan *retrieveDataResp), + } + defaultWorker.c <- req + resp := <-req.c + return resp.rows, resp.err +} + +func record(tags *tag.Map, ms interface{}) { + req := &recordReq{ + tm: tags, + ms: ms.([]stats.Measurement), + } + defaultWorker.c <- req +} + +// SetReportingPeriod sets the interval between reporting aggregated views in +// the program. If duration is less than or +// equal to zero, it enables the default behavior. +func SetReportingPeriod(d time.Duration) { + // TODO(acetechnologist): ensure that the duration d is more than a certain + // value. e.g. 1s + req := &setReportingPeriodReq{ + d: d, + c: make(chan bool), + } + defaultWorker.c <- req + <-req.c // don't return until the timer is set to the new duration. +} + +func newWorker() *worker { + return &worker{ + measures: make(map[string]*measureRef), + views: make(map[string]*viewInternal), + startTimes: make(map[*viewInternal]time.Time), + timer: time.NewTicker(defaultReportingDuration), + c: make(chan command, 1024), + quit: make(chan bool), + done: make(chan bool), + } +} + +func (w *worker) start() { + for { + select { + case cmd := <-w.c: + if cmd != nil { + cmd.handleCommand(w) + } + case <-w.timer.C: + w.reportUsage(time.Now()) + case <-w.quit: + w.timer.Stop() + close(w.c) + w.done <- true + return + } + } +} + +func (w *worker) stop() { + w.quit <- true + <-w.done +} + +func (w *worker) getMeasureRef(name string) *measureRef { + if mr, ok := w.measures[name]; ok { + return mr + } + mr := &measureRef{ + measure: name, + views: make(map[*viewInternal]struct{}), + } + w.measures[name] = mr + return mr +} + +func (w *worker) tryRegisterView(v *View) (*viewInternal, error) { + vi, err := newViewInternal(v) + if err != nil { + return nil, err + } + if x, ok := w.views[vi.view.Name]; ok { + if !x.view.same(vi.view) { + return nil, fmt.Errorf("cannot subscribe view %q; a different view with the same name is already subscribed", v.Name) + } + + // the view is already registered so there is nothing to do and the + // command is considered successful. + return x, nil + } + w.views[vi.view.Name] = vi + ref := w.getMeasureRef(vi.view.Measure.Name()) + ref.views[vi] = struct{}{} + return vi, nil +} + +func (w *worker) reportUsage(now time.Time) { + for _, v := range w.views { + if !v.isSubscribed() { + continue + } + rows := v.collectedRows() + _, ok := w.startTimes[v] + if !ok { + w.startTimes[v] = now + } + // Make sure collector is never going + // to mutate the exported data. + rows = deepCopyRowData(rows) + viewData := &Data{ + View: v.view, + Start: w.startTimes[v], + End: time.Now(), + Rows: rows, + } + exportersMu.Lock() + for e := range exporters { + e.ExportView(viewData) + } + exportersMu.Unlock() + } +} + +func deepCopyRowData(rows []*Row) []*Row { + newRows := make([]*Row, 0, len(rows)) + for _, r := range rows { + newRows = append(newRows, &Row{ + Data: r.Data.clone(), + Tags: r.Tags, + }) + } + return newRows +} diff --git a/go.opencensus.io/stats/view/worker_commands.go b/go.opencensus.io/stats/view/worker_commands.go new file mode 100644 index 00000000..8c6cde62 --- /dev/null +++ b/go.opencensus.io/stats/view/worker_commands.go @@ -0,0 +1,165 @@ +// Copyright 2017, OpenCensus 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 view + +import ( + "errors" + "fmt" + "strings" + "time" + + "go.opencensus.io/stats" + "go.opencensus.io/stats/internal" + "go.opencensus.io/tag" +) + +type command interface { + handleCommand(w *worker) +} + +// getViewByNameReq is the command to get a view given its name. +type getViewByNameReq struct { + name string + c chan *getViewByNameResp +} + +type getViewByNameResp struct { + v *View +} + +func (cmd *getViewByNameReq) handleCommand(w *worker) { + cmd.c <- &getViewByNameResp{w.views[cmd.name].view} +} + +// subscribeToViewReq is the command to subscribe to a view. +type subscribeToViewReq struct { + views []*View + err chan error +} + +func (cmd *subscribeToViewReq) handleCommand(w *worker) { + var errstr []string + for _, view := range cmd.views { + vi, err := w.tryRegisterView(view) + if err != nil { + errstr = append(errstr, fmt.Sprintf("%s: %v", view.Name, err)) + continue + } + internal.SubscriptionReporter(view.Measure.Name()) + vi.subscribe() + } + if len(errstr) > 0 { + cmd.err <- errors.New(strings.Join(errstr, "\n")) + } else { + cmd.err <- nil + } +} + +// unsubscribeFromViewReq is the command to unsubscribe to a view. Has no +// impact on the data collection for client that are pulling data from the +// library. +type unsubscribeFromViewReq struct { + views []string + done chan struct{} +} + +func (cmd *unsubscribeFromViewReq) handleCommand(w *worker) { + for _, name := range cmd.views { + vi, ok := w.views[name] + if !ok { + continue + } + + vi.unsubscribe() + if !vi.isSubscribed() { + // this was the last subscription and view is not collecting anymore. + // The collected data can be cleared. + vi.clearRows() + } + } + cmd.done <- struct{}{} +} + +// retrieveDataReq is the command to retrieve data for a view. +type retrieveDataReq struct { + now time.Time + v string + c chan *retrieveDataResp +} + +type retrieveDataResp struct { + rows []*Row + err error +} + +func (cmd *retrieveDataReq) handleCommand(w *worker) { + vi, ok := w.views[cmd.v] + if !ok { + cmd.c <- &retrieveDataResp{ + nil, + fmt.Errorf("cannot retrieve data; view %q is not registered", cmd.v), + } + return + } + + if !vi.isSubscribed() { + cmd.c <- &retrieveDataResp{ + nil, + fmt.Errorf("cannot retrieve data; view %q has no subscriptions or collection is not forcibly started", cmd.v), + } + return + } + cmd.c <- &retrieveDataResp{ + vi.collectedRows(), + nil, + } +} + +// recordReq is the command to record data related to multiple measures +// at once. +type recordReq struct { + tm *tag.Map + ms []stats.Measurement +} + +func (cmd *recordReq) handleCommand(w *worker) { + for _, m := range cmd.ms { + if (m == stats.Measurement{}) { // not subscribed + continue + } + ref := w.getMeasureRef(m.Measure().Name()) + for v := range ref.views { + v.addSample(cmd.tm, m.Value()) + } + } +} + +// setReportingPeriodReq is the command to modify the duration between +// reporting the collected data to the subscribed clients. +type setReportingPeriodReq struct { + d time.Duration + c chan bool +} + +func (cmd *setReportingPeriodReq) handleCommand(w *worker) { + w.timer.Stop() + if cmd.d <= 0 { + w.timer = time.NewTicker(defaultReportingDuration) + } else { + w.timer = time.NewTicker(cmd.d) + } + cmd.c <- true +} diff --git a/go.opencensus.io/tag/context.go b/go.opencensus.io/tag/context.go new file mode 100644 index 00000000..ed528bcb --- /dev/null +++ b/go.opencensus.io/tag/context.go @@ -0,0 +1,41 @@ +// Copyright 2017, OpenCensus 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 tag + +import "context" + +// FromContext returns the tag map stored in the context. +func FromContext(ctx context.Context) *Map { + // The returned tag map shouldn't be mutated. + ts := ctx.Value(mapCtxKey) + if ts == nil { + return nil + } + return ts.(*Map) +} + +// NewContext creates a new context with the given tag map. +// To propagate a tag map to downstream methods and downstream RPCs, add a tag map +// to the current context. NewContext will return a copy of the current context, +// and put the tag map into the returned one. +// If there is already a tag map in the current context, it will be replaced with m. +func NewContext(ctx context.Context, m *Map) context.Context { + return context.WithValue(ctx, mapCtxKey, m) +} + +type ctxKey struct{} + +var mapCtxKey = ctxKey{} diff --git a/go.opencensus.io/tag/doc.go b/go.opencensus.io/tag/doc.go new file mode 100644 index 00000000..da16b74e --- /dev/null +++ b/go.opencensus.io/tag/doc.go @@ -0,0 +1,26 @@ +// Copyright 2017, OpenCensus 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 tag contains OpenCensus tags. + +Tags are key-value pairs. Tags provide additional cardinality to +the OpenCensus instrumentation data. + +Tags can be propagated on the wire and in the same +process via context.Context. Encode and Decode should be +used to represent tags into their binary propagation form. +*/ +package tag // import "go.opencensus.io/tag" diff --git a/go.opencensus.io/tag/key.go b/go.opencensus.io/tag/key.go new file mode 100644 index 00000000..ebbed950 --- /dev/null +++ b/go.opencensus.io/tag/key.go @@ -0,0 +1,35 @@ +// Copyright 2017, OpenCensus 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 tag + +// Key represents a tag key. +type Key struct { + name string +} + +// NewKey creates or retrieves a string key identified by name. +// Calling NewKey consequently with the same name returns the same key. +func NewKey(name string) (Key, error) { + if !checkKeyName(name) { + return Key{}, errInvalidKeyName + } + return Key{name: name}, nil +} + +// Name returns the name of the key. +func (k Key) Name() string { + return k.name +} diff --git a/go.opencensus.io/tag/map.go b/go.opencensus.io/tag/map.go new file mode 100644 index 00000000..f6237b31 --- /dev/null +++ b/go.opencensus.io/tag/map.go @@ -0,0 +1,197 @@ +// Copyright 2017, OpenCensus 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 tag + +import ( + "bytes" + "context" + "fmt" + "sort" +) + +// Tag is a key value pair that can be propagated on wire. +type Tag struct { + Key Key + Value string +} + +// Map is a map of tags. Use NewMap to build tag maps. +type Map struct { + m map[Key]string +} + +// Value returns the value for the key if a value +// for the key exists. +func (m *Map) Value(k Key) (string, bool) { + if m == nil { + return "", false + } + v, ok := m.m[k] + return v, ok +} + +func (m *Map) String() string { + if m == nil { + return "nil" + } + var keys []Key + for k := range m.m { + keys = append(keys, k) + } + sort.Slice(keys, func(i, j int) bool { return keys[i].Name() < keys[j].Name() }) + + var buffer bytes.Buffer + buffer.WriteString("{ ") + for _, k := range keys { + buffer.WriteString(fmt.Sprintf("{%v %v}", k.name, m.m[k])) + } + buffer.WriteString(" }") + return buffer.String() +} + +func (m *Map) insert(k Key, v string) { + if _, ok := m.m[k]; ok { + return + } + m.m[k] = v +} + +func (m *Map) update(k Key, v string) { + if _, ok := m.m[k]; ok { + m.m[k] = v + } +} + +func (m *Map) upsert(k Key, v string) { + m.m[k] = v +} + +func (m *Map) delete(k Key) { + delete(m.m, k) +} + +func newMap(sizeHint int) *Map { + return &Map{m: make(map[Key]string, sizeHint)} +} + +// Mutator modifies a tag map. +type Mutator interface { + Mutate(t *Map) (*Map, error) +} + +// Insert returns a mutator that inserts a +// value associated with k. If k already exists in the tag map, +// mutator doesn't update the value. +func Insert(k Key, v string) Mutator { + return &mutator{ + fn: func(m *Map) (*Map, error) { + if !checkValue(v) { + return nil, errInvalidValue + } + m.insert(k, v) + return m, nil + }, + } +} + +// Update returns a mutator that updates the +// value of the tag associated with k with v. If k doesn't +// exists in the tag map, the mutator doesn't insert the value. +func Update(k Key, v string) Mutator { + return &mutator{ + fn: func(m *Map) (*Map, error) { + if !checkValue(v) { + return nil, errInvalidValue + } + m.update(k, v) + return m, nil + }, + } +} + +// Upsert returns a mutator that upserts the +// value of the tag associated with k with v. It inserts the +// value if k doesn't exist already. It mutates the value +// if k already exists. +func Upsert(k Key, v string) Mutator { + return &mutator{ + fn: func(m *Map) (*Map, error) { + if !checkValue(v) { + return nil, errInvalidValue + } + m.upsert(k, v) + return m, nil + }, + } +} + +// Delete returns a mutator that deletes +// the value associated with k. +func Delete(k Key) Mutator { + return &mutator{ + fn: func(m *Map) (*Map, error) { + m.delete(k) + return m, nil + }, + } +} + +// New returns a new context that contains a tag map +// originated from the incoming context and modified +// with the provided mutators. +func New(ctx context.Context, mutator ...Mutator) (context.Context, error) { + m := newMap(0) + orig := FromContext(ctx) + if orig != nil { + for k, v := range orig.m { + if !checkKeyName(k.Name()) { + return ctx, fmt.Errorf("key:%q: %v", k, errInvalidKeyName) + } + if !checkValue(v) { + return ctx, fmt.Errorf("key:%q value:%q: %v", k.Name(), v, errInvalidValue) + } + m.insert(k, v) + } + } + var err error + for _, mod := range mutator { + m, err = mod.Mutate(m) + if err != nil { + return ctx, err + } + } + return NewContext(ctx, m), nil +} + +// Do is similar to pprof.Do: a convenience for installing the tags +// from the context as Go profiler labels. This allows you to +// correlated runtime profiling with stats. +// +// It converts the key/values from the given map to Go profiler labels +// and calls pprof.Do. +// +// Do is going to do nothing if your Go version is below 1.9. +func Do(ctx context.Context, f func(ctx context.Context)) { + do(ctx, f) +} + +type mutator struct { + fn func(t *Map) (*Map, error) +} + +func (m *mutator) Mutate(t *Map) (*Map, error) { + return m.fn(t) +} diff --git a/go.opencensus.io/tag/map_codec.go b/go.opencensus.io/tag/map_codec.go new file mode 100644 index 00000000..38f54591 --- /dev/null +++ b/go.opencensus.io/tag/map_codec.go @@ -0,0 +1,221 @@ +// Copyright 2017, OpenCensus 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 tag + +import ( + "encoding/binary" + "fmt" +) + +// KeyType defines the types of keys allowed. Currently only keyTypeString is +// supported. +type keyType byte + +const ( + keyTypeString keyType = iota + keyTypeInt64 + keyTypeTrue + keyTypeFalse + + tagsVersionID = byte(0) +) + +type encoderGRPC struct { + buf []byte + writeIdx, readIdx int +} + +// writeKeyString writes the fieldID '0' followed by the key string and value +// string. +func (eg *encoderGRPC) writeTagString(k, v string) { + eg.writeByte(byte(keyTypeString)) + eg.writeStringWithVarintLen(k) + eg.writeStringWithVarintLen(v) +} + +func (eg *encoderGRPC) writeTagUint64(k string, i uint64) { + eg.writeByte(byte(keyTypeInt64)) + eg.writeStringWithVarintLen(k) + eg.writeUint64(i) +} + +func (eg *encoderGRPC) writeTagTrue(k string) { + eg.writeByte(byte(keyTypeTrue)) + eg.writeStringWithVarintLen(k) +} + +func (eg *encoderGRPC) writeTagFalse(k string) { + eg.writeByte(byte(keyTypeFalse)) + eg.writeStringWithVarintLen(k) +} + +func (eg *encoderGRPC) writeBytesWithVarintLen(bytes []byte) { + length := len(bytes) + + eg.growIfRequired(binary.MaxVarintLen64 + length) + eg.writeIdx += binary.PutUvarint(eg.buf[eg.writeIdx:], uint64(length)) + copy(eg.buf[eg.writeIdx:], bytes) + eg.writeIdx += length +} + +func (eg *encoderGRPC) writeStringWithVarintLen(s string) { + length := len(s) + + eg.growIfRequired(binary.MaxVarintLen64 + length) + eg.writeIdx += binary.PutUvarint(eg.buf[eg.writeIdx:], uint64(length)) + copy(eg.buf[eg.writeIdx:], s) + eg.writeIdx += length +} + +func (eg *encoderGRPC) writeByte(v byte) { + eg.growIfRequired(1) + eg.buf[eg.writeIdx] = v + eg.writeIdx++ +} + +func (eg *encoderGRPC) writeUint32(i uint32) { + eg.growIfRequired(4) + binary.LittleEndian.PutUint32(eg.buf[eg.writeIdx:], i) + eg.writeIdx += 4 +} + +func (eg *encoderGRPC) writeUint64(i uint64) { + eg.growIfRequired(8) + binary.LittleEndian.PutUint64(eg.buf[eg.writeIdx:], i) + eg.writeIdx += 8 +} + +func (eg *encoderGRPC) readByte() byte { + b := eg.buf[eg.readIdx] + eg.readIdx++ + return b +} + +func (eg *encoderGRPC) readUint32() uint32 { + i := binary.LittleEndian.Uint32(eg.buf[eg.readIdx:]) + eg.readIdx += 4 + return i +} + +func (eg *encoderGRPC) readUint64() uint64 { + i := binary.LittleEndian.Uint64(eg.buf[eg.readIdx:]) + eg.readIdx += 8 + return i +} + +func (eg *encoderGRPC) readBytesWithVarintLen() ([]byte, error) { + if eg.readEnded() { + return nil, fmt.Errorf("unexpected end while readBytesWithVarintLen '%x' starting at idx '%v'", eg.buf, eg.readIdx) + } + length, valueStart := binary.Uvarint(eg.buf[eg.readIdx:]) + if valueStart <= 0 { + return nil, fmt.Errorf("unexpected end while readBytesWithVarintLen '%x' starting at idx '%v'", eg.buf, eg.readIdx) + } + + valueStart += eg.readIdx + valueEnd := valueStart + int(length) + if valueEnd > len(eg.buf) { + return nil, fmt.Errorf("malformed encoding: length:%v, upper:%v, maxLength:%v", length, valueEnd, len(eg.buf)) + } + + eg.readIdx = valueEnd + return eg.buf[valueStart:valueEnd], nil +} + +func (eg *encoderGRPC) readStringWithVarintLen() (string, error) { + bytes, err := eg.readBytesWithVarintLen() + if err != nil { + return "", err + } + return string(bytes), nil +} + +func (eg *encoderGRPC) growIfRequired(expected int) { + if len(eg.buf)-eg.writeIdx < expected { + tmp := make([]byte, 2*(len(eg.buf)+1)+expected) + copy(tmp, eg.buf) + eg.buf = tmp + } +} + +func (eg *encoderGRPC) readEnded() bool { + return eg.readIdx >= len(eg.buf) +} + +func (eg *encoderGRPC) bytes() []byte { + return eg.buf[:eg.writeIdx] +} + +// Encode encodes the tag map into a []byte. It is useful to propagate +// the tag maps on wire in binary format. +func Encode(m *Map) []byte { + eg := &encoderGRPC{ + buf: make([]byte, len(m.m)), + } + eg.writeByte(byte(tagsVersionID)) + for k, v := range m.m { + eg.writeByte(byte(keyTypeString)) + eg.writeStringWithVarintLen(k.name) + eg.writeBytesWithVarintLen([]byte(v)) + } + return eg.bytes() +} + +// Decode decodes the given []byte into a tag map. +func Decode(bytes []byte) (*Map, error) { + ts := newMap(0) + + eg := &encoderGRPC{ + buf: bytes, + } + if len(eg.buf) == 0 { + return ts, nil + } + + version := eg.readByte() + if version > tagsVersionID { + return nil, fmt.Errorf("cannot decode: unsupported version: %q; supports only up to: %q", version, tagsVersionID) + } + + for !eg.readEnded() { + typ := keyType(eg.readByte()) + + if typ != keyTypeString { + return nil, fmt.Errorf("cannot decode: invalid key type: %q", typ) + } + + k, err := eg.readBytesWithVarintLen() + if err != nil { + return nil, err + } + + v, err := eg.readBytesWithVarintLen() + if err != nil { + return nil, err + } + + key, err := NewKey(string(k)) + if err != nil { + return nil, err // no partial failures + } + val := string(v) + if !checkValue(val) { + return nil, errInvalidValue // no partial failures + } + ts.upsert(key, val) + } + return ts, nil +} diff --git a/go.opencensus.io/tag/profile_19.go b/go.opencensus.io/tag/profile_19.go new file mode 100644 index 00000000..f81cd0b4 --- /dev/null +++ b/go.opencensus.io/tag/profile_19.go @@ -0,0 +1,31 @@ +// Copyright 2018, OpenCensus 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. + +// +build go1.9 + +package tag + +import ( + "context" + "runtime/pprof" +) + +func do(ctx context.Context, f func(ctx context.Context)) { + m := FromContext(ctx) + keyvals := make([]string, 0, 2*len(m.m)) + for k, v := range m.m { + keyvals = append(keyvals, k.Name(), v) + } + pprof.Do(ctx, pprof.Labels(keyvals...), f) +} diff --git a/go.opencensus.io/tag/profile_not19.go b/go.opencensus.io/tag/profile_not19.go new file mode 100644 index 00000000..83adbce5 --- /dev/null +++ b/go.opencensus.io/tag/profile_not19.go @@ -0,0 +1,23 @@ +// Copyright 2018, OpenCensus 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. + +// +build !go1.9 + +package tag + +import "context" + +func do(ctx context.Context, f func(ctx context.Context)) { + f(ctx) +} diff --git a/go.opencensus.io/tag/validate.go b/go.opencensus.io/tag/validate.go new file mode 100644 index 00000000..0939fc67 --- /dev/null +++ b/go.opencensus.io/tag/validate.go @@ -0,0 +1,56 @@ +// Copyright 2017, OpenCensus 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 tag + +import "errors" + +const ( + maxKeyLength = 255 + + // valid are restricted to US-ASCII subset (range 0x20 (' ') to 0x7e ('~')). + validKeyValueMin = 32 + validKeyValueMax = 126 +) + +var ( + errInvalidKeyName = errors.New("invalid key name: only ASCII characters accepted; max length must be 255 characters") + errInvalidValue = errors.New("invalid value: only ASCII characters accepted; max length must be 255 characters") +) + +func checkKeyName(name string) bool { + if len(name) == 0 { + return false + } + if len(name) > maxKeyLength { + return false + } + return isASCII(name) +} + +func isASCII(s string) bool { + for _, c := range s { + if (c < validKeyValueMin) || (c > validKeyValueMax) { + return false + } + } + return true +} + +func checkValue(v string) bool { + if len(v) > maxKeyLength { + return false + } + return isASCII(v) +} diff --git a/go.opencensus.io/trace/basetypes.go b/go.opencensus.io/trace/basetypes.go new file mode 100644 index 00000000..3ba7f0a3 --- /dev/null +++ b/go.opencensus.io/trace/basetypes.go @@ -0,0 +1,113 @@ +// Copyright 2017, OpenCensus 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 trace + +import ( + "fmt" + "time" +) + +type ( + // TraceID is a 16-byte identifier for a set of spans. + TraceID [16]byte + // SpanID is an 8-byte identifier for a single span. + SpanID [8]byte +) + +func (t TraceID) String() string { + return fmt.Sprintf("%02x", t[:]) +} + +func (s SpanID) String() string { + return fmt.Sprintf("%02x", s[:]) +} + +// Annotation represents a text annotation with a set of attributes and a timestamp. +type Annotation struct { + Time time.Time + Message string + Attributes map[string]interface{} +} + +// Attribute represents a key-value pair on a span, link or annotation. +// Construct with one of: BoolAttribute, Int64Attribute, or StringAttribute. +type Attribute struct { + key string + value interface{} +} + +// BoolAttribute returns a bool-valued attribute. +func BoolAttribute(key string, value bool) Attribute { + return Attribute{key: key, value: value} +} + +// Int64Attribute returns an int64-valued attribute. +func Int64Attribute(key string, value int64) Attribute { + return Attribute{key: key, value: value} +} + +// StringAttribute returns a string-valued attribute. +func StringAttribute(key string, value string) Attribute { + return Attribute{key: key, value: value} +} + +// LinkType specifies the relationship between the span that had the link +// added, and the linked span. +type LinkType int32 + +// LinkType values. +const ( + LinkTypeUnspecified LinkType = iota // The relationship of the two spans is unknown. + LinkTypeChild // The current span is a child of the linked span. + LinkTypeParent // The current span is the parent of the linked span. +) + +// Link represents a reference from one span to another span. +type Link struct { + TraceID TraceID + SpanID SpanID + Type LinkType + // Attributes is a set of attributes on the link. + Attributes map[string]interface{} +} + +// MessageEventType specifies the type of message event. +type MessageEventType int32 + +// MessageEventType values. +const ( + MessageEventTypeUnspecified MessageEventType = iota // Unknown event type. + MessageEventTypeSent // Indicates a sent RPC message. + MessageEventTypeRecv // Indicates a received RPC message. +) + +// MessageEvent represents an event describing a message sent or received on the network. +type MessageEvent struct { + Time time.Time + EventType MessageEventType + MessageID int64 + UncompressedByteSize int64 + CompressedByteSize int64 +} + +// Status is the status of a Span. +type Status struct { + // Code is a status code. Zero indicates success. + // + // If Code will be propagated to Google APIs, it ideally should be a value from + // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto . + Code int32 + Message string +} diff --git a/go.opencensus.io/trace/doc.go b/go.opencensus.io/trace/doc.go new file mode 100644 index 00000000..6e962408 --- /dev/null +++ b/go.opencensus.io/trace/doc.go @@ -0,0 +1,55 @@ +// Copyright 2017, OpenCensus 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 trace contains types for representing trace information, and +functions for global configuration of tracing. + +The following assumes a basic familiarity with OpenCensus concepts. +See http://opencensus.io. + + +Enabling Tracing for a Program + +To use OpenCensus tracing, register at least one Exporter. You can use +one of the provided exporters or write your own. + + trace.RegisterExporter(anExporter) + +By default, traces will be sampled relatively rarely. To change the sampling +frequency for your entire program, call SetDefaultSampler. Use a ProbabilitySampler +to sample a subset of traces, or use AlwaysSample to collect a trace on every run: + + trace.SetDefaultSampler(trace.AlwaysSample()) + + +Adding Spans to a Trace + +A trace consists of a tree of spans. In Go, the current span is carried in a +context.Context. + +It is common to want to capture all the activity of a function call in a span. For +this to work, the function must take a context.Context as a parameter. Add these two +lines to the top of the function: + + ctx, span := trace.StartSpan(ctx, "your choice of name") + defer span.End() + +StartSpan will create a new top-level span if the context +doesn't contain another span, otherwise it will create a child span. + +As a suggestion, use the fully-qualified function name as the span name, e.g. +"github.com/me/mypackage.Run". +*/ +package trace // import "go.opencensus.io/trace" diff --git a/go.opencensus.io/trace/export.go b/go.opencensus.io/trace/export.go new file mode 100644 index 00000000..086612c9 --- /dev/null +++ b/go.opencensus.io/trace/export.go @@ -0,0 +1,74 @@ +// Copyright 2017, OpenCensus 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 trace + +import ( + "sync" + "time" +) + +// Exporter is a type for functions that receive sampled trace spans. +// +// The ExportSpan method should be safe for concurrent use and should return +// quickly; if an Exporter takes a significant amount of time to process a +// SpanData, that work should be done on another goroutine. +// +// The SpanData should not be modified, but a pointer to it can be kept. +type Exporter interface { + ExportSpan(s *SpanData) +} + +var ( + exportersMu sync.Mutex + exporters map[Exporter]struct{} +) + +// RegisterExporter adds to the list of Exporters that will receive sampled +// trace spans. +func RegisterExporter(e Exporter) { + exportersMu.Lock() + if exporters == nil { + exporters = make(map[Exporter]struct{}) + } + exporters[e] = struct{}{} + exportersMu.Unlock() +} + +// UnregisterExporter removes from the list of Exporters the Exporter that was +// registered with the given name. +func UnregisterExporter(e Exporter) { + exportersMu.Lock() + delete(exporters, e) + exportersMu.Unlock() +} + +// SpanData contains all the information collected by a Span. +type SpanData struct { + SpanContext + ParentSpanID SpanID + SpanKind int + Name string + StartTime time.Time + // The wall clock time of EndTime will be adjusted to always be offset + // from StartTime by the duration of the span. + EndTime time.Time + // The values of Attributes each have type string, bool, or int64. + Attributes map[string]interface{} + Annotations []Annotation + MessageEvents []MessageEvent + Status + Links []Link + HasRemoteParent bool +} diff --git a/go.opencensus.io/trace/propagation/propagation.go b/go.opencensus.io/trace/propagation/propagation.go new file mode 100644 index 00000000..a3b00f47 --- /dev/null +++ b/go.opencensus.io/trace/propagation/propagation.go @@ -0,0 +1,108 @@ +// Copyright 2017, OpenCensus 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 propagation implements the binary trace context format. +package propagation + +// TODO: link to external spec document. + +// BinaryFormat format: +// +// Binary value: +// version_id: 1 byte representing the version id. +// +// For version_id = 0: +// +// version_format: +// field_format: +// +// Fields: +// +// TraceId: (field_id = 0, len = 16, default = "0000000000000000") - 16-byte array representing the trace_id. +// SpanId: (field_id = 1, len = 8, default = "00000000") - 8-byte array representing the span_id. +// TraceOptions: (field_id = 2, len = 1, default = "0") - 1-byte array representing the trace_options. +// +// Fields MUST be encoded using the field id order (smaller to higher). +// +// Valid value example: +// +// {0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 1, 97, +// 98, 99, 100, 101, 102, 103, 104, 2, 1} +// +// version_id = 0; +// trace_id = {64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79} +// span_id = {97, 98, 99, 100, 101, 102, 103, 104}; +// trace_options = {1}; + +import ( + "net/http" + + "go.opencensus.io/trace" +) + +// Binary returns the binary format representation of a SpanContext. +// +// If sc is the zero value, Binary returns nil. +func Binary(sc trace.SpanContext) []byte { + if sc == (trace.SpanContext{}) { + return nil + } + var b [29]byte + copy(b[2:18], sc.TraceID[:]) + b[18] = 1 + copy(b[19:27], sc.SpanID[:]) + b[27] = 2 + b[28] = uint8(sc.TraceOptions) + return b[:] +} + +// FromBinary returns the SpanContext represented by b. +// +// If b has an unsupported version ID or contains no TraceID, FromBinary +// returns with ok==false. +func FromBinary(b []byte) (sc trace.SpanContext, ok bool) { + if len(b) == 0 || b[0] != 0 { + return trace.SpanContext{}, false + } + b = b[1:] + if len(b) >= 17 && b[0] == 0 { + copy(sc.TraceID[:], b[1:17]) + b = b[17:] + } else { + return trace.SpanContext{}, false + } + if len(b) >= 9 && b[0] == 1 { + copy(sc.SpanID[:], b[1:9]) + b = b[9:] + } + if len(b) >= 2 && b[0] == 2 { + sc.TraceOptions = trace.TraceOptions(b[1]) + } + return sc, true +} + +// HTTPFormat implementations propagate span contexts +// in HTTP requests. +// +// SpanContextFromRequest extracts a span context from incoming +// requests. +// +// SpanContextToRequest modifies the given request to include the given +// span context. +type HTTPFormat interface { + SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool) + SpanContextToRequest(sc trace.SpanContext, req *http.Request) +} + +// TODO(jbd): Find a more representative but short name for HTTPFormat. diff --git a/go.opencensus.io/trace/sampling.go b/go.opencensus.io/trace/sampling.go new file mode 100644 index 00000000..8ff8db96 --- /dev/null +++ b/go.opencensus.io/trace/sampling.go @@ -0,0 +1,90 @@ +// Copyright 2017, OpenCensus 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 trace + +import ( + "encoding/binary" +) + +const defaultSamplingProbability = 1e-4 + +func init() { + defaultSampler = ProbabilitySampler(defaultSamplingProbability) +} + +func newDefaultSampler() Sampler { + return ProbabilitySampler(defaultSamplingProbability) +} + +// SetDefaultSampler sets the default sampler used when creating new spans. +func SetDefaultSampler(sampler Sampler) { + if sampler == nil { + sampler = newDefaultSampler() + } + mu.Lock() + defaultSampler = sampler + mu.Unlock() +} + +// Sampler decides whether a trace should be sampled and exported. +type Sampler func(SamplingParameters) SamplingDecision + +// SamplingParameters contains the values passed to a Sampler. +type SamplingParameters struct { + ParentContext SpanContext + TraceID TraceID + SpanID SpanID + Name string + HasRemoteParent bool +} + +// SamplingDecision is the value returned by a Sampler. +type SamplingDecision struct { + Sample bool +} + +// ProbabilitySampler returns a Sampler that samples a given fraction of traces. +// +// It also samples spans whose parents are sampled. +func ProbabilitySampler(fraction float64) Sampler { + if !(fraction >= 0) { + fraction = 0 + } else if fraction >= 1 { + return AlwaysSample() + } + + traceIDUpperBound := uint64(fraction * (1 << 63)) + return Sampler(func(p SamplingParameters) SamplingDecision { + if p.ParentContext.IsSampled() { + return SamplingDecision{Sample: true} + } + x := binary.BigEndian.Uint64(p.TraceID[0:8]) >> 1 + return SamplingDecision{Sample: x < traceIDUpperBound} + }) +} + +// AlwaysSample returns a Sampler that samples every trace. +func AlwaysSample() Sampler { + return func(p SamplingParameters) SamplingDecision { + return SamplingDecision{Sample: true} + } +} + +// NeverSample returns a Sampler that samples no traces. +func NeverSample() Sampler { + return func(p SamplingParameters) SamplingDecision { + return SamplingDecision{Sample: false} + } +} diff --git a/go.opencensus.io/trace/spanbucket.go b/go.opencensus.io/trace/spanbucket.go new file mode 100644 index 00000000..fbabad34 --- /dev/null +++ b/go.opencensus.io/trace/spanbucket.go @@ -0,0 +1,130 @@ +// Copyright 2017, OpenCensus 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 trace + +import ( + "time" +) + +// samplePeriod is the minimum time between accepting spans in a single bucket. +const samplePeriod = time.Second + +// defaultLatencies contains the default latency bucket bounds. +// TODO: consider defaults, make configurable +var defaultLatencies = [...]time.Duration{ + 10 * time.Microsecond, + 100 * time.Microsecond, + time.Millisecond, + 10 * time.Millisecond, + 100 * time.Millisecond, + time.Second, + 10 * time.Second, + time.Minute, +} + +// bucket is a container for a set of spans for a particular error code or latency range. +type bucket struct { + nextTime time.Time // next time we can accept a span + buffer []*SpanData // circular buffer of spans + nextIndex int // location next SpanData should be placed in buffer + overflow bool // whether the circular buffer has wrapped around +} + +func makeBucket(bufferSize int) bucket { + return bucket{ + buffer: make([]*SpanData, bufferSize), + } +} + +// add adds a span to the bucket, if nextTime has been reached. +func (b *bucket) add(s *SpanData) { + if s.EndTime.Before(b.nextTime) { + return + } + if len(b.buffer) == 0 { + return + } + b.nextTime = s.EndTime.Add(samplePeriod) + b.buffer[b.nextIndex] = s + b.nextIndex++ + if b.nextIndex == len(b.buffer) { + b.nextIndex = 0 + b.overflow = true + } +} + +// size returns the number of spans in the bucket. +func (b *bucket) size() int { + if b.overflow { + return len(b.buffer) + } + return b.nextIndex +} + +// span returns the ith span in the bucket. +func (b *bucket) span(i int) *SpanData { + if !b.overflow { + return b.buffer[i] + } + if i < len(b.buffer)-b.nextIndex { + return b.buffer[b.nextIndex+i] + } + return b.buffer[b.nextIndex+i-len(b.buffer)] +} + +// resize changes the size of the bucket to n, keeping up to n existing spans. +func (b *bucket) resize(n int) { + cur := b.size() + newBuffer := make([]*SpanData, n) + if cur < n { + for i := 0; i < cur; i++ { + newBuffer[i] = b.span(i) + } + b.buffer = newBuffer + b.nextIndex = cur + b.overflow = false + return + } + for i := 0; i < n; i++ { + newBuffer[i] = b.span(i + cur - n) + } + b.buffer = newBuffer + b.nextIndex = 0 + b.overflow = true +} + +// latencyBucket returns the appropriate bucket number for a given latency. +func latencyBucket(latency time.Duration) int { + i := 0 + for i < len(defaultLatencies) && latency >= defaultLatencies[i] { + i++ + } + return i +} + +// latencyBucketBounds returns the lower and upper bounds for a latency bucket +// number. +// +// The lower bound is inclusive, the upper bound is exclusive (except for the +// last bucket.) +func latencyBucketBounds(index int) (lower time.Duration, upper time.Duration) { + if index == 0 { + return 0, defaultLatencies[index] + } + if index == len(defaultLatencies) { + return defaultLatencies[index-1], 1<<63 - 1 + } + return defaultLatencies[index-1], defaultLatencies[index] +} diff --git a/go.opencensus.io/trace/spanstore.go b/go.opencensus.io/trace/spanstore.go new file mode 100644 index 00000000..c442d990 --- /dev/null +++ b/go.opencensus.io/trace/spanstore.go @@ -0,0 +1,306 @@ +// Copyright 2017, OpenCensus 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 trace + +import ( + "sync" + "time" + + "go.opencensus.io/internal" +) + +const ( + maxBucketSize = 100000 + defaultBucketSize = 10 +) + +var ( + ssmu sync.RWMutex // protects spanStores + spanStores = make(map[string]*spanStore) +) + +// This exists purely to avoid exposing internal methods used by z-Pages externally. +type internalOnly struct{} + +func init() { + //TODO(#412): remove + internal.Trace = &internalOnly{} +} + +// ReportActiveSpans returns the active spans for the given name. +func (i internalOnly) ReportActiveSpans(name string) []*SpanData { + s := spanStoreForName(name) + if s == nil { + return nil + } + var out []*SpanData + s.mu.Lock() + defer s.mu.Unlock() + for span := range s.active { + out = append(out, span.makeSpanData()) + } + return out +} + +// ReportSpansByError returns a sample of error spans. +// +// If code is nonzero, only spans with that status code are returned. +func (i internalOnly) ReportSpansByError(name string, code int32) []*SpanData { + s := spanStoreForName(name) + if s == nil { + return nil + } + var out []*SpanData + s.mu.Lock() + defer s.mu.Unlock() + if code != 0 { + if b, ok := s.errors[code]; ok { + for _, sd := range b.buffer { + if sd == nil { + break + } + out = append(out, sd) + } + } + } else { + for _, b := range s.errors { + for _, sd := range b.buffer { + if sd == nil { + break + } + out = append(out, sd) + } + } + } + return out +} + +// ConfigureBucketSizes sets the number of spans to keep per latency and error +// bucket for different span names. +func (i internalOnly) ConfigureBucketSizes(bcs []internal.BucketConfiguration) { + for _, bc := range bcs { + latencyBucketSize := bc.MaxRequestsSucceeded + if latencyBucketSize < 0 { + latencyBucketSize = 0 + } + if latencyBucketSize > maxBucketSize { + latencyBucketSize = maxBucketSize + } + errorBucketSize := bc.MaxRequestsErrors + if errorBucketSize < 0 { + errorBucketSize = 0 + } + if errorBucketSize > maxBucketSize { + errorBucketSize = maxBucketSize + } + spanStoreSetSize(bc.Name, latencyBucketSize, errorBucketSize) + } +} + +// ReportSpansPerMethod returns a summary of what spans are being stored for each span name. +func (i internalOnly) ReportSpansPerMethod() map[string]internal.PerMethodSummary { + out := make(map[string]internal.PerMethodSummary) + ssmu.RLock() + defer ssmu.RUnlock() + for name, s := range spanStores { + s.mu.Lock() + p := internal.PerMethodSummary{ + Active: len(s.active), + } + for code, b := range s.errors { + p.ErrorBuckets = append(p.ErrorBuckets, internal.ErrorBucketSummary{ + ErrorCode: code, + Size: b.size(), + }) + } + for i, b := range s.latency { + min, max := latencyBucketBounds(i) + p.LatencyBuckets = append(p.LatencyBuckets, internal.LatencyBucketSummary{ + MinLatency: min, + MaxLatency: max, + Size: b.size(), + }) + } + s.mu.Unlock() + out[name] = p + } + return out +} + +// ReportSpansByLatency returns a sample of successful spans. +// +// minLatency is the minimum latency of spans to be returned. +// maxLatency, if nonzero, is the maximum latency of spans to be returned. +func (i internalOnly) ReportSpansByLatency(name string, minLatency, maxLatency time.Duration) []*SpanData { + s := spanStoreForName(name) + if s == nil { + return nil + } + var out []*SpanData + s.mu.Lock() + defer s.mu.Unlock() + for i, b := range s.latency { + min, max := latencyBucketBounds(i) + if i+1 != len(s.latency) && max <= minLatency { + continue + } + if maxLatency != 0 && maxLatency < min { + continue + } + for _, sd := range b.buffer { + if sd == nil { + break + } + if minLatency != 0 || maxLatency != 0 { + d := sd.EndTime.Sub(sd.StartTime) + if d < minLatency { + continue + } + if maxLatency != 0 && d > maxLatency { + continue + } + } + out = append(out, sd) + } + } + return out +} + +// spanStore keeps track of spans stored for a particular span name. +// +// It contains all active spans; a sample of spans for failed requests, +// categorized by error code; and a sample of spans for successful requests, +// bucketed by latency. +type spanStore struct { + mu sync.Mutex // protects everything below. + active map[*Span]struct{} + errors map[int32]*bucket + latency []bucket + maxSpansPerErrorBucket int +} + +// newSpanStore creates a span store. +func newSpanStore(name string, latencyBucketSize int, errorBucketSize int) *spanStore { + s := &spanStore{ + active: make(map[*Span]struct{}), + latency: make([]bucket, len(defaultLatencies)+1), + maxSpansPerErrorBucket: errorBucketSize, + } + for i := range s.latency { + s.latency[i] = makeBucket(latencyBucketSize) + } + return s +} + +// spanStoreForName returns the spanStore for the given name. +// +// It returns nil if it doesn't exist. +func spanStoreForName(name string) *spanStore { + var s *spanStore + ssmu.RLock() + s, _ = spanStores[name] + ssmu.RUnlock() + return s +} + +// spanStoreForNameCreateIfNew returns the spanStore for the given name. +// +// It creates it if it didn't exist. +func spanStoreForNameCreateIfNew(name string) *spanStore { + ssmu.RLock() + s, ok := spanStores[name] + ssmu.RUnlock() + if ok { + return s + } + ssmu.Lock() + defer ssmu.Unlock() + s, ok = spanStores[name] + if ok { + return s + } + s = newSpanStore(name, defaultBucketSize, defaultBucketSize) + spanStores[name] = s + return s +} + +// spanStoreSetSize resizes the spanStore for the given name. +// +// It creates it if it didn't exist. +func spanStoreSetSize(name string, latencyBucketSize int, errorBucketSize int) { + ssmu.RLock() + s, ok := spanStores[name] + ssmu.RUnlock() + if ok { + s.resize(latencyBucketSize, errorBucketSize) + return + } + ssmu.Lock() + defer ssmu.Unlock() + s, ok = spanStores[name] + if ok { + s.resize(latencyBucketSize, errorBucketSize) + return + } + s = newSpanStore(name, latencyBucketSize, errorBucketSize) + spanStores[name] = s +} + +func (s *spanStore) resize(latencyBucketSize int, errorBucketSize int) { + s.mu.Lock() + for i := range s.latency { + s.latency[i].resize(latencyBucketSize) + } + for _, b := range s.errors { + b.resize(errorBucketSize) + } + s.maxSpansPerErrorBucket = errorBucketSize + s.mu.Unlock() +} + +// add adds a span to the active bucket of the spanStore. +func (s *spanStore) add(span *Span) { + s.mu.Lock() + s.active[span] = struct{}{} + s.mu.Unlock() +} + +// finished removes a span from the active set, and adds a corresponding +// SpanData to a latency or error bucket. +func (s *spanStore) finished(span *Span, sd *SpanData) { + latency := sd.EndTime.Sub(sd.StartTime) + if latency < 0 { + latency = 0 + } + code := sd.Status.Code + + s.mu.Lock() + delete(s.active, span) + if code == 0 { + s.latency[latencyBucket(latency)].add(sd) + } else { + if s.errors == nil { + s.errors = make(map[int32]*bucket) + } + if b := s.errors[code]; b != nil { + b.add(sd) + } else { + b := makeBucket(s.maxSpansPerErrorBucket) + s.errors[code] = &b + b.add(sd) + } + } + s.mu.Unlock() +} diff --git a/go.opencensus.io/trace/trace.go b/go.opencensus.io/trace/trace.go new file mode 100644 index 00000000..0340b6a8 --- /dev/null +++ b/go.opencensus.io/trace/trace.go @@ -0,0 +1,450 @@ +// Copyright 2017, OpenCensus 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 trace + +import ( + "context" + crand "crypto/rand" + "encoding/binary" + "fmt" + "math/rand" + "sync" + "time" + + "go.opencensus.io/internal" +) + +// Span represents a span of a trace. It has an associated SpanContext, and +// stores data accumulated while the span is active. +// +// Ideally users should interact with Spans by calling the functions in this +// package that take a Context parameter. +type Span struct { + // data contains information recorded about the span. + // + // It will be non-nil if we are exporting the span or recording events for it. + // Otherwise, data is nil, and the Span is simply a carrier for the + // SpanContext, so that the trace ID is propagated. + data *SpanData + mu sync.Mutex // protects the contents of *data (but not the pointer value.) + spanContext SpanContext + // spanStore is the spanStore this span belongs to, if any, otherwise it is nil. + *spanStore + exportOnce sync.Once +} + +// IsRecordingEvents returns true if events are being recorded for this span. +// Use this check to avoid computing expensive annotations when they will never +// be used. +func (s *Span) IsRecordingEvents() bool { + if s == nil { + return false + } + return s.data != nil +} + +// TraceOptions contains options associated with a trace span. +type TraceOptions uint32 + +// IsSampled returns true if the span will be exported. +func (sc SpanContext) IsSampled() bool { + return sc.TraceOptions.IsSampled() +} + +// setIsSampled sets the TraceOptions bit that determines whether the span will be exported. +func (sc *SpanContext) setIsSampled(sampled bool) { + if sampled { + sc.TraceOptions |= 1 + } else { + sc.TraceOptions &= ^TraceOptions(1) + } +} + +// IsSampled returns true if the span will be exported. +func (t TraceOptions) IsSampled() bool { + return t&1 == 1 +} + +// SpanContext contains the state that must propagate across process boundaries. +// +// SpanContext is not an implementation of context.Context. +// TODO: add reference to external Census docs for SpanContext. +type SpanContext struct { + TraceID TraceID + SpanID SpanID + TraceOptions TraceOptions +} + +type contextKey struct{} + +// FromContext returns the Span stored in a context, or nil if there isn't one. +func FromContext(ctx context.Context) *Span { + s, _ := ctx.Value(contextKey{}).(*Span) + return s +} + +// WithSpan returns a new context with the given Span attached. +func WithSpan(parent context.Context, s *Span) context.Context { + return context.WithValue(parent, contextKey{}, s) +} + +// All available span kinds. Span kind must be either one of these values. +const ( + SpanKindUnspecified = iota + SpanKindServer + SpanKindClient +) + +// StartOptions contains options concerning how a span is started. +type StartOptions struct { + // Sampler to consult for this Span. If provided, it is always consulted. + // + // If not provided, then the behavior differs based on whether + // the parent of this Span is remote, local, or there is no parent. + // In the case of a remote parent or no parent, the + // default sampler (see SetDefaultSampler) will be consulted. Otherwise, + // when there is a non-remote parent, no new sampling decision will be made: + // we will preserve the sampling of the parent. + Sampler Sampler + + // SpanKind represents the kind of a span. If none is set, + // SpanKindUnspecified is used. + SpanKind int +} + +// StartSpan starts a new child span of the current span in the context. If +// there is no span in the context, creates a new trace and span. +// +// This is provided as a convenience for WithSpan(ctx, NewSpan(...)). Use it +// if you require custom spans in addition to the default spans provided by +// ocgrpc, ochttp or similar framework integration. +func StartSpan(ctx context.Context, name string) (context.Context, *Span) { + parentSpan, _ := ctx.Value(contextKey{}).(*Span) + span := NewSpan(name, parentSpan, StartOptions{}) + return WithSpan(ctx, span), span +} + +// NewSpan returns a new span. +// +// If parent is not nil, created span will be a child of the parent. +func NewSpan(name string, parent *Span, o StartOptions) *Span { + hasParent := false + var parentSpanContext SpanContext + if parent != nil { + hasParent = true + parentSpanContext = parent.SpanContext() + } + return startSpanInternal(name, hasParent, parentSpanContext, false, o) +} + +// NewSpanWithRemoteParent returns a new span with the given parent SpanContext. +func NewSpanWithRemoteParent(name string, parent SpanContext, o StartOptions) *Span { + return startSpanInternal(name, true, parent, true, o) +} + +func startSpanInternal(name string, hasParent bool, parent SpanContext, remoteParent bool, o StartOptions) *Span { + span := &Span{} + span.spanContext = parent + mu.Lock() + if !hasParent { + span.spanContext.TraceID = newTraceIDLocked() + } + span.spanContext.SpanID = newSpanIDLocked() + sampler := defaultSampler + mu.Unlock() + + if !hasParent || remoteParent || o.Sampler != nil { + // If this span is the child of a local span and no Sampler is set in the + // options, keep the parent's TraceOptions. + // + // Otherwise, consult the Sampler in the options if it is non-nil, otherwise + // the default sampler. + if o.Sampler != nil { + sampler = o.Sampler + } + span.spanContext.setIsSampled(sampler(SamplingParameters{ + ParentContext: parent, + TraceID: span.spanContext.TraceID, + SpanID: span.spanContext.SpanID, + Name: name, + HasRemoteParent: remoteParent}).Sample) + } + + if !internal.LocalSpanStoreEnabled && !span.spanContext.IsSampled() { + return span + } + + span.data = &SpanData{ + SpanContext: span.spanContext, + StartTime: time.Now(), + SpanKind: o.SpanKind, + Name: name, + HasRemoteParent: remoteParent, + } + if hasParent { + span.data.ParentSpanID = parent.SpanID + } + if internal.LocalSpanStoreEnabled { + var ss *spanStore + ss = spanStoreForNameCreateIfNew(name) + if ss != nil { + span.spanStore = ss + ss.add(span) + } + } + + return span +} + +// End ends the span. +func (s *Span) End() { + if !s.IsRecordingEvents() { + return + } + s.exportOnce.Do(func() { + // TODO: optimize to avoid this call if sd won't be used. + sd := s.makeSpanData() + sd.EndTime = internal.MonotonicEndTime(sd.StartTime) + if s.spanStore != nil { + s.spanStore.finished(s, sd) + } + if s.spanContext.IsSampled() { + // TODO: consider holding exportersMu for less time. + exportersMu.Lock() + for e := range exporters { + e.ExportSpan(sd) + } + exportersMu.Unlock() + } + }) +} + +// makeSpanData produces a SpanData representing the current state of the Span. +// It requires that s.data is non-nil. +func (s *Span) makeSpanData() *SpanData { + var sd SpanData + s.mu.Lock() + sd = *s.data + if s.data.Attributes != nil { + sd.Attributes = make(map[string]interface{}) + for k, v := range s.data.Attributes { + sd.Attributes[k] = v + } + } + s.mu.Unlock() + return &sd +} + +// SpanContext returns the SpanContext of the span. +func (s *Span) SpanContext() SpanContext { + if s == nil { + return SpanContext{} + } + return s.spanContext +} + +// SetStatus sets the status of the span, if it is recording events. +func (s *Span) SetStatus(status Status) { + if !s.IsRecordingEvents() { + return + } + s.mu.Lock() + s.data.Status = status + s.mu.Unlock() +} + +// AddAttributes sets attributes in the span. +// +// Existing attributes whose keys appear in the attributes parameter are overwritten. +func (s *Span) AddAttributes(attributes ...Attribute) { + if !s.IsRecordingEvents() { + return + } + s.mu.Lock() + if s.data.Attributes == nil { + s.data.Attributes = make(map[string]interface{}) + } + copyAttributes(s.data.Attributes, attributes) + s.mu.Unlock() +} + +// copyAttributes copies a slice of Attributes into a map. +func copyAttributes(m map[string]interface{}, attributes []Attribute) { + for _, a := range attributes { + m[a.key] = a.value + } +} + +func (s *Span) lazyPrintfInternal(attributes []Attribute, format string, a ...interface{}) { + now := time.Now() + msg := fmt.Sprintf(format, a...) + var m map[string]interface{} + s.mu.Lock() + if len(attributes) != 0 { + m = make(map[string]interface{}) + copyAttributes(m, attributes) + } + s.data.Annotations = append(s.data.Annotations, Annotation{ + Time: now, + Message: msg, + Attributes: m, + }) + s.mu.Unlock() +} + +func (s *Span) printStringInternal(attributes []Attribute, str string) { + now := time.Now() + var a map[string]interface{} + s.mu.Lock() + if len(attributes) != 0 { + a = make(map[string]interface{}) + copyAttributes(a, attributes) + } + s.data.Annotations = append(s.data.Annotations, Annotation{ + Time: now, + Message: str, + Attributes: a, + }) + s.mu.Unlock() +} + +// Annotate adds an annotation with attributes. +// Attributes can be nil. +func (s *Span) Annotate(attributes []Attribute, str string) { + if !s.IsRecordingEvents() { + return + } + s.printStringInternal(attributes, str) +} + +// Annotatef adds an annotation with attributes. +func (s *Span) Annotatef(attributes []Attribute, format string, a ...interface{}) { + if !s.IsRecordingEvents() { + return + } + s.lazyPrintfInternal(attributes, format, a...) +} + +// AddMessageSendEvent adds a message send event to the span. +// +// messageID is an identifier for the message, which is recommended to be +// unique in this span and the same between the send event and the receive +// event (this allows to identify a message between the sender and receiver). +// For example, this could be a sequence id. +func (s *Span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64) { + if !s.IsRecordingEvents() { + return + } + now := time.Now() + s.mu.Lock() + s.data.MessageEvents = append(s.data.MessageEvents, MessageEvent{ + Time: now, + EventType: MessageEventTypeSent, + MessageID: messageID, + UncompressedByteSize: uncompressedByteSize, + CompressedByteSize: compressedByteSize, + }) + s.mu.Unlock() +} + +// AddMessageReceiveEvent adds a message receive event to the span. +// +// messageID is an identifier for the message, which is recommended to be +// unique in this span and the same between the send event and the receive +// event (this allows to identify a message between the sender and receiver). +// For example, this could be a sequence id. +func (s *Span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64) { + if !s.IsRecordingEvents() { + return + } + now := time.Now() + s.mu.Lock() + s.data.MessageEvents = append(s.data.MessageEvents, MessageEvent{ + Time: now, + EventType: MessageEventTypeRecv, + MessageID: messageID, + UncompressedByteSize: uncompressedByteSize, + CompressedByteSize: compressedByteSize, + }) + s.mu.Unlock() +} + +// AddLink adds a link to the span. +func (s *Span) AddLink(l Link) { + if !s.IsRecordingEvents() { + return + } + s.mu.Lock() + s.data.Links = append(s.data.Links, l) + s.mu.Unlock() +} + +func (s *Span) String() string { + if s == nil { + return "" + } + if s.data == nil { + return fmt.Sprintf("span %s", s.spanContext.SpanID) + } + s.mu.Lock() + str := fmt.Sprintf("span %s %q", s.spanContext.SpanID, s.data.Name) + s.mu.Unlock() + return str +} + +var ( + mu sync.Mutex // protects the variables below + traceIDRand *rand.Rand + traceIDAdd [2]uint64 + nextSpanID uint64 + spanIDInc uint64 + defaultSampler Sampler +) + +func init() { + // initialize traceID and spanID generators. + var rngSeed int64 + for _, p := range []interface{}{ + &rngSeed, &traceIDAdd, &nextSpanID, &spanIDInc, + } { + binary.Read(crand.Reader, binary.LittleEndian, p) + } + traceIDRand = rand.New(rand.NewSource(rngSeed)) + spanIDInc |= 1 +} + +// newSpanIDLocked returns a non-zero SpanID from a randomly-chosen sequence. +// mu should be held while this function is called. +func newSpanIDLocked() SpanID { + id := nextSpanID + nextSpanID += spanIDInc + if nextSpanID == 0 { + nextSpanID += spanIDInc + } + var sid SpanID + binary.LittleEndian.PutUint64(sid[:], id) + return sid +} + +// newTraceIDLocked returns a non-zero TraceID from a randomly-chosen sequence. +// mu should be held while this function is called. +func newTraceIDLocked() TraceID { + var tid TraceID + // Construct the trace ID from two outputs of traceIDRand, with a constant + // added to each half for additional entropy. + binary.LittleEndian.PutUint64(tid[0:8], traceIDRand.Uint64()+traceIDAdd[0]) + binary.LittleEndian.PutUint64(tid[8:16], traceIDRand.Uint64()+traceIDAdd[1]) + return tid +} diff --git a/golang.org/x/crypto/ed25519/ed25519.go b/golang.org/x/crypto/ed25519/ed25519.go index 4f26b49b..a57771a1 100644 --- a/golang.org/x/crypto/ed25519/ed25519.go +++ b/golang.org/x/crypto/ed25519/ed25519.go @@ -171,9 +171,16 @@ func Verify(publicKey PublicKey, message, sig []byte) bool { edwards25519.ScReduce(&hReduced, &digest) var R edwards25519.ProjectiveGroupElement - var b [32]byte - copy(b[:], sig[32:]) - edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b) + var s [32]byte + copy(s[:], sig[32:]) + + // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in + // the range [0, order) in order to prevent signature malleability. + if !edwards25519.ScMinimal(&s) { + return false + } + + edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s) var checkR [32]byte R.ToBytes(&checkR) diff --git a/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go b/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go index 5f8b9947..fd03c252 100644 --- a/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go +++ b/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go @@ -4,6 +4,8 @@ package edwards25519 +import "encoding/binary" + // This code is a port of the public domain, “ref10” implementation of ed25519 // from SUPERCOP. @@ -1769,3 +1771,23 @@ func ScReduce(out *[32]byte, s *[64]byte) { out[30] = byte(s11 >> 9) out[31] = byte(s11 >> 17) } + +// order is the order of Curve25519 in little-endian form. +var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000} + +// ScMinimal returns true if the given scalar is less than the order of the +// curve. +func ScMinimal(scalar *[32]byte) bool { + for i := 3; ; i-- { + v := binary.LittleEndian.Uint64(scalar[i*8:]) + if v > order[i] { + return false + } else if v < order[i] { + break + } else if i == 0 { + return false + } + } + + return true +} diff --git a/golang.org/x/crypto/ssh/terminal/util.go b/golang.org/x/crypto/ssh/terminal/util.go index 02dad484..731c89a2 100644 --- a/golang.org/x/crypto/ssh/terminal/util.go +++ b/golang.org/x/crypto/ssh/terminal/util.go @@ -108,9 +108,7 @@ func ReadPassword(fd int) ([]byte, error) { return nil, err } - defer func() { - unix.IoctlSetTermios(fd, ioctlWriteTermios, termios) - }() + defer unix.IoctlSetTermios(fd, ioctlWriteTermios, termios) return readPasswordLine(passwordReader(fd)) } diff --git a/golang.org/x/crypto/ssh/terminal/util_solaris.go b/golang.org/x/crypto/ssh/terminal/util_solaris.go index a2e1b57d..9e41b9f4 100644 --- a/golang.org/x/crypto/ssh/terminal/util_solaris.go +++ b/golang.org/x/crypto/ssh/terminal/util_solaris.go @@ -14,7 +14,7 @@ import ( // State contains the state of a terminal. type State struct { - state *unix.Termios + termios unix.Termios } // IsTerminal returns true if the given file descriptor is a terminal. @@ -75,47 +75,43 @@ func ReadPassword(fd int) ([]byte, error) { // restored. // see http://cr.illumos.org/~webrev/andy_js/1060/ func MakeRaw(fd int) (*State, error) { - oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS) + termios, err := unix.IoctlGetTermios(fd, unix.TCGETS) if err != nil { return nil, err } - oldTermios := *oldTermiosPtr - - newTermios := oldTermios - newTermios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON - newTermios.Oflag &^= syscall.OPOST - newTermios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN - newTermios.Cflag &^= syscall.CSIZE | syscall.PARENB - newTermios.Cflag |= syscall.CS8 - newTermios.Cc[unix.VMIN] = 1 - newTermios.Cc[unix.VTIME] = 0 - - if err := unix.IoctlSetTermios(fd, unix.TCSETS, &newTermios); err != nil { + + 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 := unix.IoctlSetTermios(fd, unix.TCSETS, termios); err != nil { return nil, err } - return &State{ - state: oldTermiosPtr, - }, nil + return &oldState, nil } // Restore restores the terminal connected to the given file descriptor to a // previous state. func Restore(fd int, oldState *State) error { - return unix.IoctlSetTermios(fd, unix.TCSETS, oldState.state) + return unix.IoctlSetTermios(fd, unix.TCSETS, &oldState.termios) } // GetState returns the current state of a terminal which may be useful to // restore the terminal after a signal. func GetState(fd int) (*State, error) { - oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS) + termios, err := unix.IoctlGetTermios(fd, unix.TCGETS) if err != nil { return nil, err } - return &State{ - state: oldTermiosPtr, - }, nil + return &State{termios: *termios}, nil } // GetSize returns the dimensions of the given terminal. diff --git a/golang.org/x/crypto/ssh/terminal/util_windows.go b/golang.org/x/crypto/ssh/terminal/util_windows.go index 4933ac36..8618955d 100644 --- a/golang.org/x/crypto/ssh/terminal/util_windows.go +++ b/golang.org/x/crypto/ssh/terminal/util_windows.go @@ -89,9 +89,7 @@ func ReadPassword(fd int) ([]byte, error) { return nil, err } - defer func() { - windows.SetConsoleMode(windows.Handle(fd), old) - }() + defer windows.SetConsoleMode(windows.Handle(fd), old) var h windows.Handle p, _ := windows.GetCurrentProcess() diff --git a/golang.org/x/net/trace/trace.go b/golang.org/x/net/trace/trace.go index bb72a527..a46ee0ea 100644 --- a/golang.org/x/net/trace/trace.go +++ b/golang.org/x/net/trace/trace.go @@ -368,7 +368,11 @@ func New(family, title string) Trace { } func (tr *trace) Finish() { - tr.Elapsed = time.Now().Sub(tr.Start) + elapsed := time.Now().Sub(tr.Start) + tr.mu.Lock() + tr.Elapsed = elapsed + tr.mu.Unlock() + if DebugUseAfterFinish { buf := make([]byte, 4<<10) // 4 KB should be enough n := runtime.Stack(buf, false) @@ -381,14 +385,17 @@ func (tr *trace) Finish() { m.Remove(tr) f := getFamily(tr.Family, true) + tr.mu.RLock() // protects tr fields in Cond.match calls for _, b := range f.Buckets { if b.Cond.match(tr) { b.Add(tr) } } + tr.mu.RUnlock() + // Add a sample of elapsed time as microseconds to the family's timeseries h := new(histogram) - h.addMeasurement(tr.Elapsed.Nanoseconds() / 1e3) + h.addMeasurement(elapsed.Nanoseconds() / 1e3) f.LatencyMu.Lock() f.Latency.Add(h) f.LatencyMu.Unlock() @@ -684,25 +691,20 @@ type trace struct { // Title is the title of this trace. Title string - // Timing information. - Start time.Time - Elapsed time.Duration // zero while active - - // Trace information if non-zero. - traceID uint64 - spanID uint64 - - // Whether this trace resulted in an error. - IsError bool + // Start time of the this trace. + Start time.Time - // Append-only sequence of events (modulo discards). mu sync.RWMutex - events []event + events []event // Append-only sequence of events (modulo discards). maxEvents int + recycler func(interface{}) + IsError bool // Whether this trace resulted in an error. + Elapsed time.Duration // Elapsed time for this trace, zero while active. + traceID uint64 // Trace information if non-zero. + spanID uint64 - refs int32 // how many buckets this is in - recycler func(interface{}) - disc discarded // scratch space to avoid allocation + refs int32 // how many buckets this is in + disc discarded // scratch space to avoid allocation finishStack []byte // where finish was called, if DebugUseAfterFinish is set @@ -714,14 +716,18 @@ func (tr *trace) reset() { tr.Family = "" tr.Title = "" tr.Start = time.Time{} + + tr.mu.Lock() tr.Elapsed = 0 tr.traceID = 0 tr.spanID = 0 tr.IsError = false tr.maxEvents = 0 tr.events = nil - tr.refs = 0 tr.recycler = nil + tr.mu.Unlock() + + tr.refs = 0 tr.disc = 0 tr.finishStack = nil for i := range tr.eventsBuf { @@ -801,21 +807,31 @@ func (tr *trace) LazyPrintf(format string, a ...interface{}) { tr.addEvent(&lazySprintf{format, a}, false, false) } -func (tr *trace) SetError() { tr.IsError = true } +func (tr *trace) SetError() { + tr.mu.Lock() + tr.IsError = true + tr.mu.Unlock() +} func (tr *trace) SetRecycler(f func(interface{})) { + tr.mu.Lock() tr.recycler = f + tr.mu.Unlock() } func (tr *trace) SetTraceInfo(traceID, spanID uint64) { + tr.mu.Lock() tr.traceID, tr.spanID = traceID, spanID + tr.mu.Unlock() } func (tr *trace) SetMaxEvents(m int) { + tr.mu.Lock() // Always keep at least three events: first, discarded count, last. if len(tr.events) == 0 && m > 3 { tr.maxEvents = m } + tr.mu.Unlock() } func (tr *trace) ref() { @@ -824,6 +840,7 @@ func (tr *trace) ref() { func (tr *trace) unref() { if atomic.AddInt32(&tr.refs, -1) == 0 { + tr.mu.RLock() if tr.recycler != nil { // freeTrace clears tr, so we hold tr.recycler and tr.events here. go func(f func(interface{}), es []event) { @@ -834,6 +851,7 @@ func (tr *trace) unref() { } }(tr.recycler, tr.events) } + tr.mu.RUnlock() freeTrace(tr) } @@ -844,7 +862,10 @@ func (tr *trace) When() string { } func (tr *trace) ElapsedTime() string { + tr.mu.RLock() t := tr.Elapsed + tr.mu.RUnlock() + if t == 0 { // Active trace. t = time.Since(tr.Start) diff --git a/golang.org/x/oauth2/google/default.go b/golang.org/x/oauth2/google/default.go index b4b62745..a3160743 100644 --- a/golang.org/x/oauth2/google/default.go +++ b/golang.org/x/oauth2/google/default.go @@ -18,20 +18,6 @@ import ( "golang.org/x/oauth2" ) -// DefaultCredentials holds "Application Default Credentials". -// For more details, see: -// https://developers.google.com/accounts/docs/application-default-credentials -type DefaultCredentials struct { - ProjectID string // may be empty - TokenSource oauth2.TokenSource - - // JSON contains the raw bytes from a JSON credentials file. - // This field may be nil if authentication is provided by the - // environment and not with a credentials file, e.g. when code is - // running on Google Cloud Platform. - JSON []byte -} - // DefaultClient returns an HTTP Client that uses the // DefaultTokenSource to obtain authentication credentials. func DefaultClient(ctx context.Context, scope ...string) (*http.Client, error) { @@ -53,25 +39,12 @@ func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSourc return creds.TokenSource, nil } -// FindDefaultCredentials searches for "Application Default Credentials". -// -// It looks for credentials in the following places, -// preferring the first location found: -// -// 1. A JSON file whose path is specified by the -// GOOGLE_APPLICATION_CREDENTIALS environment variable. -// 2. A JSON file in a location known to the gcloud command-line tool. -// On Windows, this is %APPDATA%/gcloud/application_default_credentials.json. -// On other systems, $HOME/.config/gcloud/application_default_credentials.json. -// 3. On Google App Engine it uses the appengine.AccessToken function. -// 4. On Google Compute Engine and Google App Engine Managed VMs, it fetches -// credentials from the metadata server. -// (In this final case any provided scopes are ignored.) -func FindDefaultCredentials(ctx context.Context, scope ...string) (*DefaultCredentials, error) { +// Common implementation for FindDefaultCredentials. +func findDefaultCredentials(ctx context.Context, scopes []string) (*DefaultCredentials, error) { // First, try the environment variable. const envVar = "GOOGLE_APPLICATION_CREDENTIALS" if filename := os.Getenv(envVar); filename != "" { - creds, err := readCredentialsFile(ctx, filename, scope) + creds, err := readCredentialsFile(ctx, filename, scopes) if err != nil { return nil, fmt.Errorf("google: error getting credentials using %v environment variable: %v", envVar, err) } @@ -80,7 +53,7 @@ func FindDefaultCredentials(ctx context.Context, scope ...string) (*DefaultCrede // Second, try a well-known file. filename := wellKnownFile() - if creds, err := readCredentialsFile(ctx, filename, scope); err == nil { + if creds, err := readCredentialsFile(ctx, filename, scopes); err == nil { return creds, nil } else if !os.IsNotExist(err) { return nil, fmt.Errorf("google: error getting credentials using well-known file (%v): %v", filename, err) @@ -90,7 +63,7 @@ func FindDefaultCredentials(ctx context.Context, scope ...string) (*DefaultCrede if appengineTokenFunc != nil && !appengineFlex { return &DefaultCredentials{ ProjectID: appengineAppIDFunc(ctx), - TokenSource: AppEngineTokenSource(ctx, scope...), + TokenSource: AppEngineTokenSource(ctx, scopes...), }, nil } @@ -108,6 +81,23 @@ func FindDefaultCredentials(ctx context.Context, scope ...string) (*DefaultCrede return nil, fmt.Errorf("google: could not find default credentials. See %v for more information.", url) } +// Common implementation for CredentialsFromJSON. +func credentialsFromJSON(ctx context.Context, jsonData []byte, scopes []string) (*DefaultCredentials, error) { + var f credentialsFile + if err := json.Unmarshal(jsonData, &f); err != nil { + return nil, err + } + ts, err := f.tokenSource(ctx, append([]string(nil), scopes...)) + if err != nil { + return nil, err + } + return &DefaultCredentials{ + ProjectID: f.ProjectID, + TokenSource: ts, + JSON: jsonData, + }, nil +} + func wellKnownFile() string { const f = "application_default_credentials.json" if runtime.GOOS == "windows" { @@ -121,17 +111,5 @@ func readCredentialsFile(ctx context.Context, filename string, scopes []string) if err != nil { return nil, err } - var f credentialsFile - if err := json.Unmarshal(b, &f); err != nil { - return nil, err - } - ts, err := f.tokenSource(ctx, append([]string(nil), scopes...)) - if err != nil { - return nil, err - } - return &DefaultCredentials{ - ProjectID: f.ProjectID, - TokenSource: ts, - JSON: b, - }, nil + return CredentialsFromJSON(ctx, b, scopes...) } diff --git a/golang.org/x/oauth2/google/doc_go19.go b/golang.org/x/oauth2/google/doc_go19.go new file mode 100644 index 00000000..2a86325f --- /dev/null +++ b/golang.org/x/oauth2/google/doc_go19.go @@ -0,0 +1,42 @@ +// Copyright 2018 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. + +// +build go1.9 + +// Package google provides support for making OAuth2 authorized and authenticated +// HTTP requests to Google APIs. It supports the Web server flow, client-side +// credentials, service accounts, Google Compute Engine service accounts, and Google +// App Engine service accounts. +// +// A brief overview of the package follows. For more information, please read +// https://developers.google.com/accounts/docs/OAuth2 +// and +// https://developers.google.com/accounts/docs/application-default-credentials. +// +// OAuth2 Configs +// +// Two functions in this package return golang.org/x/oauth2.Config values from Google credential +// data. Google supports two JSON formats for OAuth2 credentials: one is handled by ConfigFromJSON, +// the other by JWTConfigFromJSON. The returned Config can be used to obtain a TokenSource or +// create an http.Client. +// +// +// Credentials +// +// The Credentials type represents Google credentials, including Application Default +// Credentials. +// +// Use FindDefaultCredentials to obtain Application Default Credentials. +// FindDefaultCredentials looks in some well-known places for a credentials file, and +// will call AppEngineTokenSource or ComputeTokenSource as needed. +// +// DefaultClient and DefaultTokenSource are convenience methods. They first call FindDefaultCredentials, +// then use the credentials to construct an http.Client or an oauth2.TokenSource. +// +// Use CredentialsFromJSON to obtain credentials from either of the two JSON formats +// described in OAuth2 Configs, above. The TokenSource in the returned value is the +// same as the one obtained from the oauth2.Config returned from ConfigFromJSON or +// JWTConfigFromJSON, but the Credentials may contain additional information +// that is useful is some circumstances. +package google // import "golang.org/x/oauth2/google" diff --git a/golang.org/x/oauth2/google/doc_not_go19.go b/golang.org/x/oauth2/google/doc_not_go19.go new file mode 100644 index 00000000..5c3c6e14 --- /dev/null +++ b/golang.org/x/oauth2/google/doc_not_go19.go @@ -0,0 +1,43 @@ +// Copyright 2018 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. + +// +build !go1.9 + +// Package google provides support for making OAuth2 authorized and authenticated +// HTTP requests to Google APIs. It supports the Web server flow, client-side +// credentials, service accounts, Google Compute Engine service accounts, and Google +// App Engine service accounts. +// +// A brief overview of the package follows. For more information, please read +// https://developers.google.com/accounts/docs/OAuth2 +// and +// https://developers.google.com/accounts/docs/application-default-credentials. +// +// OAuth2 Configs +// +// Two functions in this package return golang.org/x/oauth2.Config values from Google credential +// data. Google supports two JSON formats for OAuth2 credentials: one is handled by ConfigFromJSON, +// the other by JWTConfigFromJSON. The returned Config can be used to obtain a TokenSource or +// create an http.Client. +// +// +// Credentials +// +// The DefaultCredentials type represents Google Application Default Credentials, as +// well as other forms of credential. +// +// Use FindDefaultCredentials to obtain Application Default Credentials. +// FindDefaultCredentials looks in some well-known places for a credentials file, and +// will call AppEngineTokenSource or ComputeTokenSource as needed. +// +// DefaultClient and DefaultTokenSource are convenience methods. They first call FindDefaultCredentials, +// then use the credentials to construct an http.Client or an oauth2.TokenSource. +// +// Use CredentialsFromJSON to obtain credentials from either of the two JSON +// formats described in OAuth2 Configs, above. (The DefaultCredentials returned may +// not be "Application Default Credentials".) The TokenSource in the returned value +// is the same as the one obtained from the oauth2.Config returned from +// ConfigFromJSON or JWTConfigFromJSON, but the DefaultCredentials may contain +// additional information that is useful is some circumstances. +package google // import "golang.org/x/oauth2/google" diff --git a/golang.org/x/oauth2/google/go19.go b/golang.org/x/oauth2/google/go19.go new file mode 100644 index 00000000..4d0318b1 --- /dev/null +++ b/golang.org/x/oauth2/google/go19.go @@ -0,0 +1,57 @@ +// Copyright 2018 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. + +// +build go1.9 + +package google + +import ( + "golang.org/x/net/context" + "golang.org/x/oauth2" +) + +// Credentials holds Google credentials, including "Application Default Credentials". +// For more details, see: +// https://developers.google.com/accounts/docs/application-default-credentials +type Credentials struct { + ProjectID string // may be empty + TokenSource oauth2.TokenSource + + // JSON contains the raw bytes from a JSON credentials file. + // This field may be nil if authentication is provided by the + // environment and not with a credentials file, e.g. when code is + // running on Google Cloud Platform. + JSON []byte +} + +// DefaultCredentials is the old name of Credentials. +// +// Deprecated: use Credentials instead. +type DefaultCredentials = Credentials + +// FindDefaultCredentials searches for "Application Default Credentials". +// +// It looks for credentials in the following places, +// preferring the first location found: +// +// 1. A JSON file whose path is specified by the +// GOOGLE_APPLICATION_CREDENTIALS environment variable. +// 2. A JSON file in a location known to the gcloud command-line tool. +// On Windows, this is %APPDATA%/gcloud/application_default_credentials.json. +// On other systems, $HOME/.config/gcloud/application_default_credentials.json. +// 3. On Google App Engine it uses the appengine.AccessToken function. +// 4. On Google Compute Engine and Google App Engine Managed VMs, it fetches +// credentials from the metadata server. +// (In this final case any provided scopes are ignored.) +func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials, error) { + return findDefaultCredentials(ctx, scopes) +} + +// CredentialsFromJSON obtains Google credentials from a JSON value. The JSON can +// represent either a Google Developers Console client_credentials.json file (as in +// ConfigFromJSON) or a Google Developers service account key file (as in +// JWTConfigFromJSON). +func CredentialsFromJSON(ctx context.Context, jsonData []byte, scopes ...string) (*Credentials, error) { + return credentialsFromJSON(ctx, jsonData, scopes) +} diff --git a/golang.org/x/oauth2/google/google.go b/golang.org/x/oauth2/google/google.go index 66a8b0e1..f7481fbc 100644 --- a/golang.org/x/oauth2/google/google.go +++ b/golang.org/x/oauth2/google/google.go @@ -2,17 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package google provides support for making OAuth2 authorized and -// authenticated HTTP requests to Google APIs. -// It supports the Web server flow, client-side credentials, service accounts, -// Google Compute Engine service accounts, and Google App Engine service -// accounts. -// -// For more information, please read -// https://developers.google.com/accounts/docs/OAuth2 -// and -// https://developers.google.com/accounts/docs/application-default-credentials. -package google // import "golang.org/x/oauth2/google" +package google import ( "encoding/json" diff --git a/golang.org/x/oauth2/google/not_go19.go b/golang.org/x/oauth2/google/not_go19.go new file mode 100644 index 00000000..544e4062 --- /dev/null +++ b/golang.org/x/oauth2/google/not_go19.go @@ -0,0 +1,54 @@ +// Copyright 2018 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. + +// +build !go1.9 + +package google + +import ( + "golang.org/x/net/context" + "golang.org/x/oauth2" +) + +// DefaultCredentials holds Google credentials, including "Application Default Credentials". +// For more details, see: +// https://developers.google.com/accounts/docs/application-default-credentials +type DefaultCredentials struct { + ProjectID string // may be empty + TokenSource oauth2.TokenSource + + // JSON contains the raw bytes from a JSON credentials file. + // This field may be nil if authentication is provided by the + // environment and not with a credentials file, e.g. when code is + // running on Google Cloud Platform. + JSON []byte +} + +// FindDefaultCredentials searches for "Application Default Credentials". +// +// It looks for credentials in the following places, +// preferring the first location found: +// +// 1. A JSON file whose path is specified by the +// GOOGLE_APPLICATION_CREDENTIALS environment variable. +// 2. A JSON file in a location known to the gcloud command-line tool. +// On Windows, this is %APPDATA%/gcloud/application_default_credentials.json. +// On other systems, $HOME/.config/gcloud/application_default_credentials.json. +// 3. On Google App Engine it uses the appengine.AccessToken function. +// 4. On Google Compute Engine and Google App Engine Managed VMs, it fetches +// credentials from the metadata server. +// (In this final case any provided scopes are ignored.) +func FindDefaultCredentials(ctx context.Context, scopes ...string) (*DefaultCredentials, error) { + return findDefaultCredentials(ctx, scopes) +} + +// CredentialsFromJSON obtains Google credentials from a JSON value. The JSON can +// represent either a Google Developers Console client_credentials.json file (as in +// ConfigFromJSON) or a Google Developers service account key file (as in +// JWTConfigFromJSON). +// +// Note: despite the name, the returned credentials may not be Application Default Credentials. +func CredentialsFromJSON(ctx context.Context, jsonData []byte, scopes ...string) (*DefaultCredentials, error) { + return credentialsFromJSON(ctx, jsonData, scopes) +} diff --git a/golang.org/x/sys/unix/syscall.go b/golang.org/x/sys/unix/syscall.go index 857d2a42..ef35fce8 100644 --- a/golang.org/x/sys/unix/syscall.go +++ b/golang.org/x/sys/unix/syscall.go @@ -11,24 +11,27 @@ // system, set $GOOS and $GOARCH to the desired system. For example, if // you want to view documentation for freebsd/arm on linux/amd64, set $GOOS // to freebsd and $GOARCH to arm. +// // The primary use of this package is inside other packages that provide a more // portable interface to the system, such as "os", "time" and "net". Use // those packages rather than this one if you can. +// // For details of the functions and data types in this package consult // the manuals for the appropriate operating system. +// // These calls return err == nil to indicate success; otherwise // err represents an operating system error describing the failure and // holds a value of type syscall.Errno. package unix // import "golang.org/x/sys/unix" +import "strings" + // ByteSliceFromString returns a NUL-terminated slice of bytes // containing the text of s. If s contains a NUL byte at any // location, it returns (nil, EINVAL). func ByteSliceFromString(s string) ([]byte, error) { - for i := 0; i < len(s); i++ { - if s[i] == 0 { - return nil, EINVAL - } + if strings.IndexByte(s, 0) != -1 { + return nil, EINVAL } a := make([]byte, len(s)+1) copy(a, s) diff --git a/golang.org/x/sys/unix/syscall_darwin.go b/golang.org/x/sys/unix/syscall_darwin.go index b9598694..006e21f5 100644 --- a/golang.org/x/sys/unix/syscall_darwin.go +++ b/golang.org/x/sys/unix/syscall_darwin.go @@ -330,6 +330,7 @@ func Uname(uname *Utsname) error { //sys Flock(fd int, how int) (err error) //sys Fpathconf(fd int, name int) (val int, err error) //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 +//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64 //sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64 //sys Fsync(fd int) (err error) //sys Ftruncate(fd int, length int64) (err error) diff --git a/golang.org/x/sys/unix/syscall_dragonfly.go b/golang.org/x/sys/unix/syscall_dragonfly.go index 777860bf..b5072de2 100644 --- a/golang.org/x/sys/unix/syscall_dragonfly.go +++ b/golang.org/x/sys/unix/syscall_dragonfly.go @@ -251,10 +251,12 @@ func Uname(uname *Utsname) error { //sys Fchdir(fd int) (err error) //sys Fchflags(fd int, flags int) (err error) //sys Fchmod(fd int, mode uint32) (err error) +//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) //sys Fchown(fd int, uid int, gid int) (err error) //sys Flock(fd int, how int) (err error) //sys Fpathconf(fd int, name int) (val int, err error) //sys Fstat(fd int, stat *Stat_t) (err error) +//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) //sys Fstatfs(fd int, stat *Statfs_t) (err error) //sys Fsync(fd int) (err error) //sys Ftruncate(fd int, length int64) (err error) diff --git a/golang.org/x/sys/unix/syscall_freebsd.go b/golang.org/x/sys/unix/syscall_freebsd.go index 89f2c3fc..ba9df4ac 100644 --- a/golang.org/x/sys/unix/syscall_freebsd.go +++ b/golang.org/x/sys/unix/syscall_freebsd.go @@ -12,7 +12,10 @@ package unix -import "unsafe" +import ( + "strings" + "unsafe" +) // SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets. type SockaddrDatalink struct { @@ -134,14 +137,7 @@ func setattrlistTimes(path string, times []Timespec, flags int) error { // Derive extattr namespace and attribute name func xattrnamespace(fullattr string) (ns int, attr string, err error) { - s := -1 - for idx, val := range fullattr { - if val == '.' { - s = idx - break - } - } - + s := strings.IndexByte(fullattr, '.') if s == -1 { return -1, "", ENOATTR } @@ -482,6 +478,7 @@ func Uname(uname *Utsname) error { //sys Flock(fd int, how int) (err error) //sys Fpathconf(fd int, name int) (val int, err error) //sys Fstat(fd int, stat *Stat_t) (err error) +//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) //sys Fstatfs(fd int, stat *Statfs_t) (err error) //sys Fsync(fd int) (err error) //sys Ftruncate(fd int, length int64) (err error) diff --git a/golang.org/x/sys/unix/syscall_linux_arm64.go b/golang.org/x/sys/unix/syscall_linux_arm64.go index 9a8e6e41..a1e8a609 100644 --- a/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -7,6 +7,7 @@ package unix //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT +//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) //sys Fstat(fd int, stat *Stat_t) (err error) //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) @@ -23,8 +24,11 @@ package unix //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { - ts := Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000} - return Pselect(nfd, r, w, e, &ts, nil) + var ts *Timespec + if timeout != nil { + ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000} + } + return Pselect(nfd, r, w, e, ts, nil) } //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) diff --git a/golang.org/x/sys/unix/syscall_linux_gccgo.go b/golang.org/x/sys/unix/syscall_linux_gccgo.go new file mode 100644 index 00000000..df9c1237 --- /dev/null +++ b/golang.org/x/sys/unix/syscall_linux_gccgo.go @@ -0,0 +1,21 @@ +// Copyright 2018 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. + +// +build linux +// +build gccgo +// +build 386 arm + +package unix + +import ( + "syscall" + "unsafe" +) + +func seek(fd int, offset int64, whence int) (newoffset int64, err syscall.Errno) { + offsetLow := uint32(offset & 0xffffffff) + offsetHigh := uint32((offset >> 32) & 0xffffffff) + _, _, err = Syscall6(SYS__LLSEEK, uintptr(fd), uintptr(offsetHigh), uintptr(offsetLow), uintptr(unsafe.Pointer(&newoffset)), uintptr(whence), 0) + return newoffset, err +} diff --git a/golang.org/x/sys/unix/syscall_linux_mips64x.go b/golang.org/x/sys/unix/syscall_linux_mips64x.go index 46aa4ff9..090ed404 100644 --- a/golang.org/x/sys/unix/syscall_linux_mips64x.go +++ b/golang.org/x/sys/unix/syscall_linux_mips64x.go @@ -9,6 +9,7 @@ package unix //sys Dup2(oldfd int, newfd int) (err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) +//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) //sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT //sys Fstatfs(fd int, buf *Statfs_t) (err error) @@ -26,8 +27,11 @@ package unix //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) { - ts := Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000} - return Pselect(nfd, r, w, e, &ts, nil) + var ts *Timespec + if timeout != nil { + ts = &Timespec{Sec: timeout.Sec, Nsec: timeout.Usec * 1000} + } + return Pselect(nfd, r, w, e, ts, nil) } //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) diff --git a/golang.org/x/sys/unix/syscall_linux_mipsx.go b/golang.org/x/sys/unix/syscall_linux_mipsx.go index 40b8e4f0..3d5817f6 100644 --- a/golang.org/x/sys/unix/syscall_linux_mipsx.go +++ b/golang.org/x/sys/unix/syscall_linux_mipsx.go @@ -15,6 +15,7 @@ import ( func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) //sys Dup2(oldfd int, newfd int) (err error) +//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) //sys Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64 //sysnb Getegid() (egid int) diff --git a/golang.org/x/sys/unix/syscall_linux_ppc64x.go b/golang.org/x/sys/unix/syscall_linux_ppc64x.go index 17c9116e..6fb8733d 100644 --- a/golang.org/x/sys/unix/syscall_linux_ppc64x.go +++ b/golang.org/x/sys/unix/syscall_linux_ppc64x.go @@ -9,6 +9,7 @@ package unix //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Dup2(oldfd int, newfd int) (err error) +//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) //sys Fstat(fd int, stat *Stat_t) (err error) //sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT diff --git a/golang.org/x/sys/unix/syscall_linux_sparc64.go b/golang.org/x/sys/unix/syscall_linux_sparc64.go index a00f9927..78c1e0df 100644 --- a/golang.org/x/sys/unix/syscall_linux_sparc64.go +++ b/golang.org/x/sys/unix/syscall_linux_sparc64.go @@ -7,6 +7,7 @@ package unix //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) +//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Dup2(oldfd int, newfd int) (err error) //sys Fchown(fd int, uid int, gid int) (err error) //sys Fstat(fd int, stat *Stat_t) (err error) diff --git a/golang.org/x/sys/unix/syscall_netbsd.go b/golang.org/x/sys/unix/syscall_netbsd.go index 71b70783..e1a3baa2 100644 --- a/golang.org/x/sys/unix/syscall_netbsd.go +++ b/golang.org/x/sys/unix/syscall_netbsd.go @@ -233,13 +233,16 @@ func Uname(uname *Utsname) error { //sys Dup(fd int) (nfd int, err error) //sys Dup2(from int, to int) (err error) //sys Exit(code int) +//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_POSIX_FADVISE //sys Fchdir(fd int) (err error) //sys Fchflags(fd int, flags int) (err error) //sys Fchmod(fd int, mode uint32) (err error) +//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) //sys Fchown(fd int, uid int, gid int) (err error) //sys Flock(fd int, how int) (err error) //sys Fpathconf(fd int, name int) (val int, err error) //sys Fstat(fd int, stat *Stat_t) (err error) +//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) //sys Fsync(fd int) (err error) //sys Ftruncate(fd int, length int64) (err error) //sysnb Getegid() (egid int) @@ -320,7 +323,6 @@ func Uname(uname *Utsname) error { // __msync13 // __ntp_gettime30 // __posix_chown -// __posix_fadvise50 // __posix_fchown // __posix_lchown // __posix_rename diff --git a/golang.org/x/sys/unix/syscall_openbsd.go b/golang.org/x/sys/unix/syscall_openbsd.go index 37556e77..387e1cfc 100644 --- a/golang.org/x/sys/unix/syscall_openbsd.go +++ b/golang.org/x/sys/unix/syscall_openbsd.go @@ -204,10 +204,12 @@ func Uname(uname *Utsname) error { //sys Fchdir(fd int) (err error) //sys Fchflags(fd int, flags int) (err error) //sys Fchmod(fd int, mode uint32) (err error) +//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) //sys Fchown(fd int, uid int, gid int) (err error) //sys Flock(fd int, how int) (err error) //sys Fpathconf(fd int, name int) (val int, err error) //sys Fstat(fd int, stat *Stat_t) (err error) +//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) //sys Fstatfs(fd int, stat *Statfs_t) (err error) //sys Fsync(fd int) (err error) //sys Ftruncate(fd int, length int64) (err error) diff --git a/golang.org/x/sys/unix/syscall_solaris.go b/golang.org/x/sys/unix/syscall_solaris.go index eca8d1d0..76fe8e77 100644 --- a/golang.org/x/sys/unix/syscall_solaris.go +++ b/golang.org/x/sys/unix/syscall_solaris.go @@ -595,9 +595,10 @@ func Poll(fds []PollFd, timeout int) (n int, err error) { //sys Fchown(fd int, uid int, gid int) (err error) //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) //sys Fdatasync(fd int) (err error) -//sys Flock(fd int, how int) (err error) +//sys Flock(fd int, how int) (err error) //sys Fpathconf(fd int, name int) (val int, err error) //sys Fstat(fd int, stat *Stat_t) (err error) +//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) //sys Fstatvfs(fd int, vfsstat *Statvfs_t) (err error) //sys Getdents(fd int, buf []byte, basep *uintptr) (n int, err error) //sysnb Getgid() (gid int) @@ -675,6 +676,7 @@ func Poll(fds []PollFd, timeout int) (n int, err error) { //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) //sys munmap(addr uintptr, length uintptr) (err error) +//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile //sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto //sys socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket //sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair diff --git a/golang.org/x/sys/unix/syscall_solaris_amd64.go b/golang.org/x/sys/unix/syscall_solaris_amd64.go index 9d4e7a67..91c32ddf 100644 --- a/golang.org/x/sys/unix/syscall_solaris_amd64.go +++ b/golang.org/x/sys/unix/syscall_solaris_amd64.go @@ -21,8 +21,3 @@ func (iov *Iovec) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } - -func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { - // TODO(aram): implement this, see issue 5847. - panic("unimplemented") -} diff --git a/golang.org/x/sys/unix/syscall_unix.go b/golang.org/x/sys/unix/syscall_unix.go index cd8f3a9c..8c66ae51 100644 --- a/golang.org/x/sys/unix/syscall_unix.go +++ b/golang.org/x/sys/unix/syscall_unix.go @@ -7,6 +7,7 @@ package unix import ( + "bytes" "runtime" "sync" "syscall" @@ -52,12 +53,11 @@ func errnoErr(e syscall.Errno) error { // clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte. func clen(n []byte) int { - for i := 0; i < len(n); i++ { - if n[i] == 0 { - return i - } + i := bytes.IndexByte(n, 0) + if i == -1 { + i = len(n) } - return len(n) + return i } // Mmap manager, for use by operating system-specific implementations. @@ -206,6 +206,20 @@ func GetsockoptInt(fd, level, opt int) (value int, err error) { return int(n), err } +func GetsockoptLinger(fd, level, opt int) (*Linger, error) { + var linger Linger + vallen := _Socklen(SizeofLinger) + err := getsockopt(fd, level, opt, unsafe.Pointer(&linger), &vallen) + return &linger, err +} + +func GetsockoptTimeval(fd, level, opt int) (*Timeval, error) { + var tv Timeval + vallen := _Socklen(unsafe.Sizeof(tv)) + err := getsockopt(fd, level, opt, unsafe.Pointer(&tv), &vallen) + return &tv, err +} + func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { var rsa RawSockaddrAny var len _Socklen = SizeofSockaddrAny @@ -305,3 +319,12 @@ func SetNonblock(fd int, nonblocking bool) (err error) { _, err = fcntl(fd, F_SETFL, flag) return err } + +// Exec calls execve(2), which replaces the calling executable in the process +// tree. argv0 should be the full path to an executable ("/bin/ls") and the +// executable name should also be the first argument in argv (["ls", "-l"]). +// envv are the environment variables that should be passed to the new +// process (["USER=go", "PWD=/tmp"]). +func Exec(argv0 string, argv []string, envv []string) error { + return syscall.Exec(argv0, argv, envv) +} diff --git a/golang.org/x/sys/unix/types_netbsd.go b/golang.org/x/sys/unix/types_netbsd.go index 10aa9b3a..1494aafc 100644 --- a/golang.org/x/sys/unix/types_netbsd.go +++ b/golang.org/x/sys/unix/types_netbsd.go @@ -118,6 +118,17 @@ const ( PathMax = C.PATH_MAX ) +// Advice to Fadvise + +const ( + FADV_NORMAL = C.POSIX_FADV_NORMAL + FADV_RANDOM = C.POSIX_FADV_RANDOM + FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL + FADV_WILLNEED = C.POSIX_FADV_WILLNEED + FADV_DONTNEED = C.POSIX_FADV_DONTNEED + FADV_NOREUSE = C.POSIX_FADV_NOREUSE +) + // Sockets type RawSockaddrInet4 C.struct_sockaddr_in diff --git a/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go b/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go index d9601550..474441b8 100644 --- a/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go +++ b/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go @@ -980,7 +980,10 @@ const ( RLIMIT_CPU = 0x0 RLIMIT_DATA = 0x2 RLIMIT_FSIZE = 0x1 + RLIMIT_MEMLOCK = 0x6 RLIMIT_NOFILE = 0x8 + RLIMIT_NPROC = 0x7 + RLIMIT_RSS = 0x5 RLIMIT_STACK = 0x3 RLIM_INFINITY = 0x7fffffffffffffff RTAX_AUTHOR = 0x6 diff --git a/golang.org/x/sys/unix/zerrors_netbsd_386.go b/golang.org/x/sys/unix/zerrors_netbsd_386.go index 1612b660..3eef63f5 100644 --- a/golang.org/x/sys/unix/zerrors_netbsd_386.go +++ b/golang.org/x/sys/unix/zerrors_netbsd_386.go @@ -159,6 +159,7 @@ const ( CLONE_VFORK = 0x4000 CLONE_VM = 0x100 CREAD = 0x800 + CRTSCTS = 0x10000 CS5 = 0x0 CS6 = 0x100 CS7 = 0x200 diff --git a/golang.org/x/sys/unix/zerrors_netbsd_amd64.go b/golang.org/x/sys/unix/zerrors_netbsd_amd64.go index c994ab61..40c870be 100644 --- a/golang.org/x/sys/unix/zerrors_netbsd_amd64.go +++ b/golang.org/x/sys/unix/zerrors_netbsd_amd64.go @@ -159,6 +159,7 @@ const ( CLONE_VFORK = 0x4000 CLONE_VM = 0x100 CREAD = 0x800 + CRTSCTS = 0x10000 CS5 = 0x0 CS6 = 0x100 CS7 = 0x200 diff --git a/golang.org/x/sys/unix/zerrors_netbsd_arm.go b/golang.org/x/sys/unix/zerrors_netbsd_arm.go index a8f9efed..43c4add5 100644 --- a/golang.org/x/sys/unix/zerrors_netbsd_arm.go +++ b/golang.org/x/sys/unix/zerrors_netbsd_arm.go @@ -151,6 +151,7 @@ const ( CFLUSH = 0xf CLOCAL = 0x8000 CREAD = 0x800 + CRTSCTS = 0x10000 CS5 = 0x0 CS6 = 0x100 CS7 = 0x200 diff --git a/golang.org/x/sys/unix/zerrors_openbsd_386.go b/golang.org/x/sys/unix/zerrors_openbsd_386.go index 04e4f331..f47536dc 100644 --- a/golang.org/x/sys/unix/zerrors_openbsd_386.go +++ b/golang.org/x/sys/unix/zerrors_openbsd_386.go @@ -147,6 +147,7 @@ const ( CFLUSH = 0xf CLOCAL = 0x8000 CREAD = 0x800 + CRTSCTS = 0x10000 CS5 = 0x0 CS6 = 0x100 CS7 = 0x200 diff --git a/golang.org/x/sys/unix/zerrors_openbsd_amd64.go b/golang.org/x/sys/unix/zerrors_openbsd_amd64.go index c80ff981..c96ca653 100644 --- a/golang.org/x/sys/unix/zerrors_openbsd_amd64.go +++ b/golang.org/x/sys/unix/zerrors_openbsd_amd64.go @@ -147,6 +147,7 @@ const ( CFLUSH = 0xf CLOCAL = 0x8000 CREAD = 0x800 + CRTSCTS = 0x10000 CS5 = 0x0 CS6 = 0x100 CS7 = 0x200 diff --git a/golang.org/x/sys/unix/zerrors_openbsd_arm.go b/golang.org/x/sys/unix/zerrors_openbsd_arm.go index 4c320495..4c027352 100644 --- a/golang.org/x/sys/unix/zerrors_openbsd_arm.go +++ b/golang.org/x/sys/unix/zerrors_openbsd_arm.go @@ -147,6 +147,7 @@ const ( CFLUSH = 0xf CLOCAL = 0x8000 CREAD = 0x800 + CRTSCTS = 0x10000 CS5 = 0x0 CS6 = 0x100 CS7 = 0x200 diff --git a/golang.org/x/sys/unix/zsyscall_darwin_386.go b/golang.org/x/sys/unix/zsyscall_darwin_386.go index 763ae4fb..4c9f7275 100644 --- a/golang.org/x/sys/unix/zsyscall_darwin_386.go +++ b/golang.org/x/sys/unix/zsyscall_darwin_386.go @@ -693,6 +693,21 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT64, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index d6808e07..25623777 100644 --- a/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -693,6 +693,21 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT64, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_darwin_arm.go b/golang.org/x/sys/unix/zsyscall_darwin_arm.go index 6ae95e6b..4ae787e4 100644 --- a/golang.org/x/sys/unix/zsyscall_darwin_arm.go +++ b/golang.org/x/sys/unix/zsyscall_darwin_arm.go @@ -693,6 +693,21 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT64, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index ca6a7ea8..14ed6886 100644 --- a/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -693,6 +693,21 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT64, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go b/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go index a0241de1..91f36e9e 100644 --- a/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go +++ b/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go @@ -618,6 +618,21 @@ func Fchmod(fd int, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { @@ -659,6 +674,21 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_freebsd_386.go b/golang.org/x/sys/unix/zsyscall_freebsd_386.go index fd9ca5a4..a86434a7 100644 --- a/golang.org/x/sys/unix/zsyscall_freebsd_386.go +++ b/golang.org/x/sys/unix/zsyscall_freebsd_386.go @@ -924,6 +924,21 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go b/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go index a9f18b22..040e2f76 100644 --- a/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go +++ b/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go @@ -924,6 +924,21 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_freebsd_arm.go b/golang.org/x/sys/unix/zsyscall_freebsd_arm.go index 9823e18a..cddc5e86 100644 --- a/golang.org/x/sys/unix/zsyscall_freebsd_arm.go +++ b/golang.org/x/sys/unix/zsyscall_freebsd_arm.go @@ -924,6 +924,21 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_linux_arm64.go b/golang.org/x/sys/unix/zsyscall_linux_arm64.go index 8f276d65..8c9e26a0 100644 --- a/golang.org/x/sys/unix/zsyscall_linux_arm64.go +++ b/golang.org/x/sys/unix/zsyscall_linux_arm64.go @@ -1541,6 +1541,16 @@ func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_linux_mips.go b/golang.org/x/sys/unix/zsyscall_linux_mips.go index 61169b33..8dc2b58f 100644 --- a/golang.org/x/sys/unix/zsyscall_linux_mips.go +++ b/golang.org/x/sys/unix/zsyscall_linux_mips.go @@ -1534,6 +1534,16 @@ func Dup2(oldfd int, newfd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall9(SYS_FADVISE64, uintptr(fd), 0, uintptr(offset>>32), uintptr(offset), uintptr(length>>32), uintptr(length), uintptr(advice), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_linux_mips64.go b/golang.org/x/sys/unix/zsyscall_linux_mips64.go index 4cb59b4a..e8beef85 100644 --- a/golang.org/x/sys/unix/zsyscall_linux_mips64.go +++ b/golang.org/x/sys/unix/zsyscall_linux_mips64.go @@ -1551,6 +1551,16 @@ func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_linux_mips64le.go b/golang.org/x/sys/unix/zsyscall_linux_mips64le.go index 0b547ae3..899e4403 100644 --- a/golang.org/x/sys/unix/zsyscall_linux_mips64le.go +++ b/golang.org/x/sys/unix/zsyscall_linux_mips64le.go @@ -1551,6 +1551,16 @@ func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_linux_mipsle.go b/golang.org/x/sys/unix/zsyscall_linux_mipsle.go index cd94d3a8..7a477cbd 100644 --- a/golang.org/x/sys/unix/zsyscall_linux_mipsle.go +++ b/golang.org/x/sys/unix/zsyscall_linux_mipsle.go @@ -1534,6 +1534,16 @@ func Dup2(oldfd int, newfd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall9(SYS_FADVISE64, uintptr(fd), 0, uintptr(offset), uintptr(offset>>32), uintptr(length), uintptr(length>>32), uintptr(advice), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_linux_ppc64.go b/golang.org/x/sys/unix/zsyscall_linux_ppc64.go index cdad555a..9dc4c7d6 100644 --- a/golang.org/x/sys/unix/zsyscall_linux_ppc64.go +++ b/golang.org/x/sys/unix/zsyscall_linux_ppc64.go @@ -1551,6 +1551,16 @@ func Dup2(oldfd int, newfd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go b/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go index 38f4e44b..f0d1ee12 100644 --- a/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go +++ b/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go @@ -1551,6 +1551,16 @@ func Dup2(oldfd int, newfd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_linux_sparc64.go b/golang.org/x/sys/unix/zsyscall_linux_sparc64.go index 2dd98434..c01b3b6b 100644 --- a/golang.org/x/sys/unix/zsyscall_linux_sparc64.go +++ b/golang.org/x/sys/unix/zsyscall_linux_sparc64.go @@ -1222,6 +1222,16 @@ func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall6(SYS_FADVISE64, uintptr(fd), uintptr(offset), uintptr(length), uintptr(advice), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Dup2(oldfd int, newfd int) (err error) { _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_netbsd_386.go b/golang.org/x/sys/unix/zsyscall_netbsd_386.go index 62eadff1..fb4b9627 100644 --- a/golang.org/x/sys/unix/zsyscall_netbsd_386.go +++ b/golang.org/x/sys/unix/zsyscall_netbsd_386.go @@ -571,6 +571,16 @@ func Exit(code int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall9(SYS_POSIX_FADVISE, uintptr(fd), 0, uintptr(offset), uintptr(offset>>32), 0, uintptr(length), uintptr(length>>32), uintptr(advice), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchdir(fd int) (err error) { _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0) if e1 != 0 { @@ -601,6 +611,21 @@ func Fchmod(fd int, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { @@ -642,6 +667,21 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go b/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go index 307f4e99..beac82ef 100644 --- a/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go +++ b/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go @@ -571,6 +571,16 @@ func Exit(code int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall6(SYS_POSIX_FADVISE, uintptr(fd), 0, uintptr(offset), 0, uintptr(length), uintptr(advice)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchdir(fd int) (err error) { _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0) if e1 != 0 { @@ -601,6 +611,21 @@ func Fchmod(fd int, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { @@ -642,6 +667,21 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_netbsd_arm.go b/golang.org/x/sys/unix/zsyscall_netbsd_arm.go index 61109313..7bd5f60b 100644 --- a/golang.org/x/sys/unix/zsyscall_netbsd_arm.go +++ b/golang.org/x/sys/unix/zsyscall_netbsd_arm.go @@ -571,6 +571,16 @@ func Exit(code int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall9(SYS_POSIX_FADVISE, uintptr(fd), 0, uintptr(offset), uintptr(offset>>32), 0, uintptr(length), uintptr(length>>32), uintptr(advice), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchdir(fd int) (err error) { _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0) if e1 != 0 { @@ -601,6 +611,21 @@ func Fchmod(fd int, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { @@ -642,6 +667,21 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_openbsd_386.go b/golang.org/x/sys/unix/zsyscall_openbsd_386.go index 003f820e..5c09c075 100644 --- a/golang.org/x/sys/unix/zsyscall_openbsd_386.go +++ b/golang.org/x/sys/unix/zsyscall_openbsd_386.go @@ -599,6 +599,21 @@ func Fchmod(fd int, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { @@ -640,6 +655,21 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go b/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go index ba0e8f32..54ccc935 100644 --- a/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go +++ b/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go @@ -599,6 +599,21 @@ func Fchmod(fd int, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { @@ -640,6 +655,21 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_openbsd_arm.go b/golang.org/x/sys/unix/zsyscall_openbsd_arm.go index 2ce02c7c..59258b0a 100644 --- a/golang.org/x/sys/unix/zsyscall_openbsd_arm.go +++ b/golang.org/x/sys/unix/zsyscall_openbsd_arm.go @@ -599,6 +599,21 @@ func Fchmod(fd int, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { @@ -640,6 +655,21 @@ func Fstat(fd int, stat *Stat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstatfs(fd int, stat *Statfs_t) (err error) { _, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/golang.org/x/sys/unix/zsyscall_solaris_amd64.go b/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index f5d01b3a..39789630 100644 --- a/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +++ b/golang.org/x/sys/unix/zsyscall_solaris_amd64.go @@ -50,6 +50,7 @@ import ( //go:cgo_import_dynamic libc_flock flock "libc.so" //go:cgo_import_dynamic libc_fpathconf fpathconf "libc.so" //go:cgo_import_dynamic libc_fstat fstat "libc.so" +//go:cgo_import_dynamic libc_fstatat fstatat "libc.so" //go:cgo_import_dynamic libc_fstatvfs fstatvfs "libc.so" //go:cgo_import_dynamic libc_getdents getdents "libc.so" //go:cgo_import_dynamic libc_getgid getgid "libc.so" @@ -127,6 +128,7 @@ import ( //go:cgo_import_dynamic libc___xnet_connect __xnet_connect "libsocket.so" //go:cgo_import_dynamic libc_mmap mmap "libc.so" //go:cgo_import_dynamic libc_munmap munmap "libc.so" +//go:cgo_import_dynamic libc_sendfile sendfile "libsendfile.so" //go:cgo_import_dynamic libc___xnet_sendto __xnet_sendto "libsocket.so" //go:cgo_import_dynamic libc___xnet_socket __xnet_socket "libsocket.so" //go:cgo_import_dynamic libc___xnet_socketpair __xnet_socketpair "libsocket.so" @@ -176,6 +178,7 @@ import ( //go:linkname procFlock libc_flock //go:linkname procFpathconf libc_fpathconf //go:linkname procFstat libc_fstat +//go:linkname procFstatat libc_fstatat //go:linkname procFstatvfs libc_fstatvfs //go:linkname procGetdents libc_getdents //go:linkname procGetgid libc_getgid @@ -253,6 +256,7 @@ import ( //go:linkname proc__xnet_connect libc___xnet_connect //go:linkname procmmap libc_mmap //go:linkname procmunmap libc_munmap +//go:linkname procsendfile libc_sendfile //go:linkname proc__xnet_sendto libc___xnet_sendto //go:linkname proc__xnet_socket libc___xnet_socket //go:linkname proc__xnet_socketpair libc___xnet_socketpair @@ -303,6 +307,7 @@ var ( procFlock, procFpathconf, procFstat, + procFstatat, procFstatvfs, procGetdents, procGetgid, @@ -380,6 +385,7 @@ var ( proc__xnet_connect, procmmap, procmunmap, + procsendfile, proc__xnet_sendto, proc__xnet_socket, proc__xnet_socketpair, @@ -772,6 +778,19 @@ func Fstat(fd int, stat *Stat_t) (err error) { return } +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFstatat)), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = e1 + } + return +} + func Fstatvfs(fd int, vfsstat *Statvfs_t) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procFstatvfs)), 2, uintptr(fd), uintptr(unsafe.Pointer(vfsstat)), 0, 0, 0, 0) if e1 != 0 { @@ -1573,6 +1592,15 @@ func munmap(addr uintptr, length uintptr) (err error) { return } +func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procsendfile)), 4, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0) + written = int(r0) + if e1 != 0 { + err = e1 + } + return +} + func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { var _p0 *byte if len(buf) > 0 { diff --git a/golang.org/x/sys/unix/ztypes_darwin_386.go b/golang.org/x/sys/unix/ztypes_darwin_386.go index bc4bc89f..327af5fb 100644 --- a/golang.org/x/sys/unix/ztypes_darwin_386.go +++ b/golang.org/x/sys/unix/ztypes_darwin_386.go @@ -136,13 +136,13 @@ type Fsid struct { } type Dirent struct { - Ino uint64 - Seekoff uint64 - Reclen uint16 - Namlen uint16 - Type uint8 - Name [1024]int8 - Pad_cgo_0 [3]byte + Ino uint64 + Seekoff uint64 + Reclen uint16 + Namlen uint16 + Type uint8 + Name [1024]int8 + _ [3]byte } type RawSockaddrInet4 struct { @@ -295,14 +295,14 @@ const ( ) type IfMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Data IfData + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Data IfData } type IfData struct { @@ -338,51 +338,51 @@ type IfData struct { } type IfaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Metric int32 + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Metric int32 } type IfmaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte } type IfmaMsghdr2 struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Refcount int32 + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Refcount int32 } type RtMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Index uint16 - Pad_cgo_0 [2]byte - Flags int32 - Addrs int32 - Pid int32 - Seq int32 - Errno int32 - Use int32 - Inits uint32 - Rmx RtMetrics + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + _ [2]byte + Flags int32 + Addrs int32 + Pid int32 + Seq int32 + Errno int32 + Use int32 + Inits uint32 + Rmx RtMetrics } type RtMetrics struct { @@ -430,11 +430,11 @@ type BpfInsn struct { } type BpfHdr struct { - Tstamp Timeval - Caplen uint32 - Datalen uint32 - Hdrlen uint16 - Pad_cgo_0 [2]byte + Tstamp Timeval + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + _ [2]byte } type Termios struct { diff --git a/golang.org/x/sys/unix/ztypes_darwin_amd64.go b/golang.org/x/sys/unix/ztypes_darwin_amd64.go index d8abcab1..116e6e07 100644 --- a/golang.org/x/sys/unix/ztypes_darwin_amd64.go +++ b/golang.org/x/sys/unix/ztypes_darwin_amd64.go @@ -26,9 +26,9 @@ type Timespec struct { } type Timeval struct { - Sec int64 - Usec int32 - Pad_cgo_0 [4]byte + Sec int64 + Usec int32 + _ [4]byte } type Timeval32 struct { @@ -70,7 +70,7 @@ type Stat_t struct { Uid uint32 Gid uint32 Rdev int32 - Pad_cgo_0 [4]byte + _ [4]byte Atimespec Timespec Mtimespec Timespec Ctimespec Timespec @@ -120,9 +120,9 @@ type Fstore_t struct { } type Radvisory_t struct { - Offset int64 - Count int32 - Pad_cgo_0 [4]byte + Offset int64 + Count int32 + _ [4]byte } type Fbootstraptransfer_t struct { @@ -132,9 +132,9 @@ type Fbootstraptransfer_t struct { } type Log2phys_t struct { - Flags uint32 - Pad_cgo_0 [8]byte - Pad_cgo_1 [8]byte + Flags uint32 + _ [8]byte + _ [8]byte } type Fsid struct { @@ -142,13 +142,13 @@ type Fsid struct { } type Dirent struct { - Ino uint64 - Seekoff uint64 - Reclen uint16 - Namlen uint16 - Type uint8 - Name [1024]int8 - Pad_cgo_0 [3]byte + Ino uint64 + Seekoff uint64 + Reclen uint16 + Namlen uint16 + Type uint8 + Name [1024]int8 + _ [3]byte } type RawSockaddrInet4 struct { @@ -221,10 +221,10 @@ type IPv6Mreq struct { type Msghdr struct { Name *byte Namelen uint32 - Pad_cgo_0 [4]byte + _ [4]byte Iov *Iovec Iovlen int32 - Pad_cgo_1 [4]byte + _ [4]byte Control *byte Controllen uint32 Flags int32 @@ -303,14 +303,14 @@ const ( ) type IfMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Data IfData + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Data IfData } type IfData struct { @@ -346,51 +346,51 @@ type IfData struct { } type IfaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Metric int32 + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Metric int32 } type IfmaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte } type IfmaMsghdr2 struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Refcount int32 + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Refcount int32 } type RtMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Index uint16 - Pad_cgo_0 [2]byte - Flags int32 - Addrs int32 - Pid int32 - Seq int32 - Errno int32 - Use int32 - Inits uint32 - Rmx RtMetrics + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + _ [2]byte + Flags int32 + Addrs int32 + Pid int32 + Seq int32 + Errno int32 + Use int32 + Inits uint32 + Rmx RtMetrics } type RtMetrics struct { @@ -426,9 +426,9 @@ type BpfStat struct { } type BpfProgram struct { - Len uint32 - Pad_cgo_0 [4]byte - Insns *BpfInsn + Len uint32 + _ [4]byte + Insns *BpfInsn } type BpfInsn struct { @@ -439,22 +439,22 @@ type BpfInsn struct { } type BpfHdr struct { - Tstamp Timeval32 - Caplen uint32 - Datalen uint32 - Hdrlen uint16 - Pad_cgo_0 [2]byte + Tstamp Timeval32 + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + _ [2]byte } type Termios struct { - Iflag uint64 - Oflag uint64 - Cflag uint64 - Lflag uint64 - Cc [20]uint8 - Pad_cgo_0 [4]byte - Ispeed uint64 - Ospeed uint64 + Iflag uint64 + Oflag uint64 + Cflag uint64 + Lflag uint64 + Cc [20]uint8 + _ [4]byte + Ispeed uint64 + Ospeed uint64 } type Winsize struct { diff --git a/golang.org/x/sys/unix/ztypes_darwin_arm.go b/golang.org/x/sys/unix/ztypes_darwin_arm.go index 9749c9f7..2750ad76 100644 --- a/golang.org/x/sys/unix/ztypes_darwin_arm.go +++ b/golang.org/x/sys/unix/ztypes_darwin_arm.go @@ -137,13 +137,13 @@ type Fsid struct { } type Dirent struct { - Ino uint64 - Seekoff uint64 - Reclen uint16 - Namlen uint16 - Type uint8 - Name [1024]int8 - Pad_cgo_0 [3]byte + Ino uint64 + Seekoff uint64 + Reclen uint16 + Namlen uint16 + Type uint8 + Name [1024]int8 + _ [3]byte } type RawSockaddrInet4 struct { @@ -296,14 +296,14 @@ const ( ) type IfMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Data IfData + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Data IfData } type IfData struct { @@ -339,51 +339,51 @@ type IfData struct { } type IfaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Metric int32 + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Metric int32 } type IfmaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte } type IfmaMsghdr2 struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Refcount int32 + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Refcount int32 } type RtMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Index uint16 - Pad_cgo_0 [2]byte - Flags int32 - Addrs int32 - Pid int32 - Seq int32 - Errno int32 - Use int32 - Inits uint32 - Rmx RtMetrics + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + _ [2]byte + Flags int32 + Addrs int32 + Pid int32 + Seq int32 + Errno int32 + Use int32 + Inits uint32 + Rmx RtMetrics } type RtMetrics struct { @@ -431,11 +431,11 @@ type BpfInsn struct { } type BpfHdr struct { - Tstamp Timeval - Caplen uint32 - Datalen uint32 - Hdrlen uint16 - Pad_cgo_0 [2]byte + Tstamp Timeval + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + _ [2]byte } type Termios struct { diff --git a/golang.org/x/sys/unix/ztypes_darwin_arm64.go b/golang.org/x/sys/unix/ztypes_darwin_arm64.go index 810b0bd4..8cead099 100644 --- a/golang.org/x/sys/unix/ztypes_darwin_arm64.go +++ b/golang.org/x/sys/unix/ztypes_darwin_arm64.go @@ -26,9 +26,9 @@ type Timespec struct { } type Timeval struct { - Sec int64 - Usec int32 - Pad_cgo_0 [4]byte + Sec int64 + Usec int32 + _ [4]byte } type Timeval32 struct { @@ -70,7 +70,7 @@ type Stat_t struct { Uid uint32 Gid uint32 Rdev int32 - Pad_cgo_0 [4]byte + _ [4]byte Atimespec Timespec Mtimespec Timespec Ctimespec Timespec @@ -120,9 +120,9 @@ type Fstore_t struct { } type Radvisory_t struct { - Offset int64 - Count int32 - Pad_cgo_0 [4]byte + Offset int64 + Count int32 + _ [4]byte } type Fbootstraptransfer_t struct { @@ -132,9 +132,9 @@ type Fbootstraptransfer_t struct { } type Log2phys_t struct { - Flags uint32 - Pad_cgo_0 [8]byte - Pad_cgo_1 [8]byte + Flags uint32 + _ [8]byte + _ [8]byte } type Fsid struct { @@ -142,13 +142,13 @@ type Fsid struct { } type Dirent struct { - Ino uint64 - Seekoff uint64 - Reclen uint16 - Namlen uint16 - Type uint8 - Name [1024]int8 - Pad_cgo_0 [3]byte + Ino uint64 + Seekoff uint64 + Reclen uint16 + Namlen uint16 + Type uint8 + Name [1024]int8 + _ [3]byte } type RawSockaddrInet4 struct { @@ -221,10 +221,10 @@ type IPv6Mreq struct { type Msghdr struct { Name *byte Namelen uint32 - Pad_cgo_0 [4]byte + _ [4]byte Iov *Iovec Iovlen int32 - Pad_cgo_1 [4]byte + _ [4]byte Control *byte Controllen uint32 Flags int32 @@ -303,14 +303,14 @@ const ( ) type IfMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Data IfData + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Data IfData } type IfData struct { @@ -346,51 +346,51 @@ type IfData struct { } type IfaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Metric int32 + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Metric int32 } type IfmaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte } type IfmaMsghdr2 struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Refcount int32 + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Refcount int32 } type RtMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Index uint16 - Pad_cgo_0 [2]byte - Flags int32 - Addrs int32 - Pid int32 - Seq int32 - Errno int32 - Use int32 - Inits uint32 - Rmx RtMetrics + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + _ [2]byte + Flags int32 + Addrs int32 + Pid int32 + Seq int32 + Errno int32 + Use int32 + Inits uint32 + Rmx RtMetrics } type RtMetrics struct { @@ -426,9 +426,9 @@ type BpfStat struct { } type BpfProgram struct { - Len uint32 - Pad_cgo_0 [4]byte - Insns *BpfInsn + Len uint32 + _ [4]byte + Insns *BpfInsn } type BpfInsn struct { @@ -439,22 +439,22 @@ type BpfInsn struct { } type BpfHdr struct { - Tstamp Timeval32 - Caplen uint32 - Datalen uint32 - Hdrlen uint16 - Pad_cgo_0 [2]byte + Tstamp Timeval32 + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + _ [2]byte } type Termios struct { - Iflag uint64 - Oflag uint64 - Cflag uint64 - Lflag uint64 - Cc [20]uint8 - Pad_cgo_0 [4]byte - Ispeed uint64 - Ospeed uint64 + Iflag uint64 + Oflag uint64 + Cflag uint64 + Lflag uint64 + Cc [20]uint8 + _ [4]byte + Ispeed uint64 + Ospeed uint64 } type Winsize struct { diff --git a/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go b/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go index e3b8ebb0..315a553b 100644 --- a/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go +++ b/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go @@ -108,7 +108,7 @@ type Statfs_t struct { Owner uint32 Type int32 Flags int32 - Pad_cgo_0 [4]byte + _ [4]byte Syncwrites int64 Asyncwrites int64 Fstypename [16]int8 @@ -118,7 +118,7 @@ type Statfs_t struct { Spares1 int16 Mntfromname [80]int8 Spares2 int16 - Pad_cgo_1 [4]byte + _ [4]byte Spare [2]int64 } @@ -219,10 +219,10 @@ type IPv6Mreq struct { type Msghdr struct { Name *byte Namelen uint32 - Pad_cgo_0 [4]byte + _ [4]byte Iov *Iovec Iovlen int32 - Pad_cgo_1 [4]byte + _ [4]byte Control *byte Controllen uint32 Flags int32 @@ -294,14 +294,14 @@ const ( ) type IfMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Data IfData + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Data IfData } type IfData struct { @@ -311,7 +311,7 @@ type IfData struct { Hdrlen uint8 Recvquota uint8 Xmitquota uint8 - Pad_cgo_0 [2]byte + _ [2]byte Mtu uint64 Metric uint64 Link_state uint64 @@ -333,24 +333,24 @@ type IfData struct { } type IfaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Metric int32 + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Metric int32 } type IfmaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte } type IfAnnounceMsghdr struct { @@ -363,19 +363,19 @@ type IfAnnounceMsghdr struct { } type RtMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Index uint16 - Pad_cgo_0 [2]byte - Flags int32 - Addrs int32 - Pid int32 - Seq int32 - Errno int32 - Use int32 - Inits uint64 - Rmx RtMetrics + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + _ [2]byte + Flags int32 + Addrs int32 + Pid int32 + Seq int32 + Errno int32 + Use int32 + Inits uint64 + Rmx RtMetrics } type RtMetrics struct { @@ -391,7 +391,7 @@ type RtMetrics struct { Hopcount uint64 Mssopt uint16 Pad uint16 - Pad_cgo_0 [4]byte + _ [4]byte Msl uint64 Iwmaxsegs uint64 Iwcapsegs uint64 @@ -416,9 +416,9 @@ type BpfStat struct { } type BpfProgram struct { - Len uint32 - Pad_cgo_0 [4]byte - Insns *BpfInsn + Len uint32 + _ [4]byte + Insns *BpfInsn } type BpfInsn struct { @@ -429,11 +429,11 @@ type BpfInsn struct { } type BpfHdr struct { - Tstamp Timeval - Caplen uint32 - Datalen uint32 - Hdrlen uint16 - Pad_cgo_0 [6]byte + Tstamp Timeval + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + _ [6]byte } type Termios struct { diff --git a/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 9dbbb1ce..8e7384b8 100644 --- a/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -376,97 +376,123 @@ const ( ) const ( - IFA_UNSPEC = 0x0 - IFA_ADDRESS = 0x1 - IFA_LOCAL = 0x2 - IFA_LABEL = 0x3 - IFA_BROADCAST = 0x4 - IFA_ANYCAST = 0x5 - IFA_CACHEINFO = 0x6 - IFA_MULTICAST = 0x7 - IFLA_UNSPEC = 0x0 - IFLA_ADDRESS = 0x1 - IFLA_BROADCAST = 0x2 - IFLA_IFNAME = 0x3 - IFLA_MTU = 0x4 - IFLA_LINK = 0x5 - IFLA_QDISC = 0x6 - IFLA_STATS = 0x7 - IFLA_COST = 0x8 - IFLA_PRIORITY = 0x9 - IFLA_MASTER = 0xa - IFLA_WIRELESS = 0xb - IFLA_PROTINFO = 0xc - IFLA_TXQLEN = 0xd - IFLA_MAP = 0xe - IFLA_WEIGHT = 0xf - IFLA_OPERSTATE = 0x10 - IFLA_LINKMODE = 0x11 - IFLA_LINKINFO = 0x12 - IFLA_NET_NS_PID = 0x13 - IFLA_IFALIAS = 0x14 - IFLA_MAX = 0x2a - RT_SCOPE_UNIVERSE = 0x0 - RT_SCOPE_SITE = 0xc8 - RT_SCOPE_LINK = 0xfd - RT_SCOPE_HOST = 0xfe - RT_SCOPE_NOWHERE = 0xff - RT_TABLE_UNSPEC = 0x0 - RT_TABLE_COMPAT = 0xfc - RT_TABLE_DEFAULT = 0xfd - RT_TABLE_MAIN = 0xfe - RT_TABLE_LOCAL = 0xff - RT_TABLE_MAX = 0xffffffff - RTA_UNSPEC = 0x0 - RTA_DST = 0x1 - RTA_SRC = 0x2 - RTA_IIF = 0x3 - RTA_OIF = 0x4 - RTA_GATEWAY = 0x5 - RTA_PRIORITY = 0x6 - RTA_PREFSRC = 0x7 - RTA_METRICS = 0x8 - RTA_MULTIPATH = 0x9 - RTA_FLOW = 0xb - RTA_CACHEINFO = 0xc - RTA_TABLE = 0xf - RTN_UNSPEC = 0x0 - RTN_UNICAST = 0x1 - RTN_LOCAL = 0x2 - RTN_BROADCAST = 0x3 - RTN_ANYCAST = 0x4 - RTN_MULTICAST = 0x5 - RTN_BLACKHOLE = 0x6 - RTN_UNREACHABLE = 0x7 - RTN_PROHIBIT = 0x8 - RTN_THROW = 0x9 - RTN_NAT = 0xa - RTN_XRESOLVE = 0xb - RTNLGRP_NONE = 0x0 - RTNLGRP_LINK = 0x1 - RTNLGRP_NOTIFY = 0x2 - RTNLGRP_NEIGH = 0x3 - RTNLGRP_TC = 0x4 - RTNLGRP_IPV4_IFADDR = 0x5 - RTNLGRP_IPV4_MROUTE = 0x6 - RTNLGRP_IPV4_ROUTE = 0x7 - RTNLGRP_IPV4_RULE = 0x8 - RTNLGRP_IPV6_IFADDR = 0x9 - RTNLGRP_IPV6_MROUTE = 0xa - RTNLGRP_IPV6_ROUTE = 0xb - RTNLGRP_IPV6_IFINFO = 0xc - RTNLGRP_IPV6_PREFIX = 0x12 - RTNLGRP_IPV6_RULE = 0x13 - RTNLGRP_ND_USEROPT = 0x14 - SizeofNlMsghdr = 0x10 - SizeofNlMsgerr = 0x14 - SizeofRtGenmsg = 0x1 - SizeofNlAttr = 0x4 - SizeofRtAttr = 0x4 - SizeofIfInfomsg = 0x10 - SizeofIfAddrmsg = 0x8 - SizeofRtMsg = 0xc - SizeofRtNexthop = 0x8 + IFA_UNSPEC = 0x0 + IFA_ADDRESS = 0x1 + IFA_LOCAL = 0x2 + IFA_LABEL = 0x3 + IFA_BROADCAST = 0x4 + IFA_ANYCAST = 0x5 + IFA_CACHEINFO = 0x6 + IFA_MULTICAST = 0x7 + IFLA_UNSPEC = 0x0 + IFLA_ADDRESS = 0x1 + IFLA_BROADCAST = 0x2 + IFLA_IFNAME = 0x3 + IFLA_MTU = 0x4 + IFLA_LINK = 0x5 + IFLA_QDISC = 0x6 + IFLA_STATS = 0x7 + IFLA_COST = 0x8 + IFLA_PRIORITY = 0x9 + IFLA_MASTER = 0xa + IFLA_WIRELESS = 0xb + IFLA_PROTINFO = 0xc + IFLA_TXQLEN = 0xd + IFLA_MAP = 0xe + IFLA_WEIGHT = 0xf + IFLA_OPERSTATE = 0x10 + IFLA_LINKMODE = 0x11 + IFLA_LINKINFO = 0x12 + IFLA_NET_NS_PID = 0x13 + IFLA_IFALIAS = 0x14 + IFLA_NUM_VF = 0x15 + IFLA_VFINFO_LIST = 0x16 + IFLA_STATS64 = 0x17 + IFLA_VF_PORTS = 0x18 + IFLA_PORT_SELF = 0x19 + IFLA_AF_SPEC = 0x1a + IFLA_GROUP = 0x1b + IFLA_NET_NS_FD = 0x1c + IFLA_EXT_MASK = 0x1d + IFLA_PROMISCUITY = 0x1e + IFLA_NUM_TX_QUEUES = 0x1f + IFLA_NUM_RX_QUEUES = 0x20 + IFLA_CARRIER = 0x21 + IFLA_PHYS_PORT_ID = 0x22 + IFLA_CARRIER_CHANGES = 0x23 + IFLA_PHYS_SWITCH_ID = 0x24 + IFLA_LINK_NETNSID = 0x25 + IFLA_PHYS_PORT_NAME = 0x26 + IFLA_PROTO_DOWN = 0x27 + IFLA_GSO_MAX_SEGS = 0x28 + IFLA_GSO_MAX_SIZE = 0x29 + IFLA_PAD = 0x2a + IFLA_XDP = 0x2b + IFLA_EVENT = 0x2c + IFLA_NEW_NETNSID = 0x2d + IFLA_IF_NETNSID = 0x2e + IFLA_MAX = 0x2e + RT_SCOPE_UNIVERSE = 0x0 + RT_SCOPE_SITE = 0xc8 + RT_SCOPE_LINK = 0xfd + RT_SCOPE_HOST = 0xfe + RT_SCOPE_NOWHERE = 0xff + RT_TABLE_UNSPEC = 0x0 + RT_TABLE_COMPAT = 0xfc + RT_TABLE_DEFAULT = 0xfd + RT_TABLE_MAIN = 0xfe + RT_TABLE_LOCAL = 0xff + RT_TABLE_MAX = 0xffffffff + RTA_UNSPEC = 0x0 + RTA_DST = 0x1 + RTA_SRC = 0x2 + RTA_IIF = 0x3 + RTA_OIF = 0x4 + RTA_GATEWAY = 0x5 + RTA_PRIORITY = 0x6 + RTA_PREFSRC = 0x7 + RTA_METRICS = 0x8 + RTA_MULTIPATH = 0x9 + RTA_FLOW = 0xb + RTA_CACHEINFO = 0xc + RTA_TABLE = 0xf + RTN_UNSPEC = 0x0 + RTN_UNICAST = 0x1 + RTN_LOCAL = 0x2 + RTN_BROADCAST = 0x3 + RTN_ANYCAST = 0x4 + RTN_MULTICAST = 0x5 + RTN_BLACKHOLE = 0x6 + RTN_UNREACHABLE = 0x7 + RTN_PROHIBIT = 0x8 + RTN_THROW = 0x9 + RTN_NAT = 0xa + RTN_XRESOLVE = 0xb + RTNLGRP_NONE = 0x0 + RTNLGRP_LINK = 0x1 + RTNLGRP_NOTIFY = 0x2 + RTNLGRP_NEIGH = 0x3 + RTNLGRP_TC = 0x4 + RTNLGRP_IPV4_IFADDR = 0x5 + RTNLGRP_IPV4_MROUTE = 0x6 + RTNLGRP_IPV4_ROUTE = 0x7 + RTNLGRP_IPV4_RULE = 0x8 + RTNLGRP_IPV6_IFADDR = 0x9 + RTNLGRP_IPV6_MROUTE = 0xa + RTNLGRP_IPV6_ROUTE = 0xb + RTNLGRP_IPV6_IFINFO = 0xc + RTNLGRP_IPV6_PREFIX = 0x12 + RTNLGRP_IPV6_RULE = 0x13 + RTNLGRP_ND_USEROPT = 0x14 + SizeofNlMsghdr = 0x10 + SizeofNlMsgerr = 0x14 + SizeofRtGenmsg = 0x1 + SizeofNlAttr = 0x4 + SizeofRtAttr = 0x4 + SizeofIfInfomsg = 0x10 + SizeofIfAddrmsg = 0x8 + SizeofRtMsg = 0xc + SizeofRtNexthop = 0x8 ) type NlMsghdr struct { diff --git a/golang.org/x/sys/unix/ztypes_netbsd_386.go b/golang.org/x/sys/unix/ztypes_netbsd_386.go index da70faa8..4b86fb2b 100644 --- a/golang.org/x/sys/unix/ztypes_netbsd_386.go +++ b/golang.org/x/sys/unix/ztypes_netbsd_386.go @@ -103,6 +103,15 @@ const ( PathMax = 0x400 ) +const ( + FADV_NORMAL = 0x0 + FADV_RANDOM = 0x1 + FADV_SEQUENTIAL = 0x2 + FADV_WILLNEED = 0x3 + FADV_DONTNEED = 0x4 + FADV_NOREUSE = 0x5 +) + type RawSockaddrInet4 struct { Len uint8 Family uint8 diff --git a/golang.org/x/sys/unix/ztypes_netbsd_amd64.go b/golang.org/x/sys/unix/ztypes_netbsd_amd64.go index 0963ab8c..9048a509 100644 --- a/golang.org/x/sys/unix/ztypes_netbsd_amd64.go +++ b/golang.org/x/sys/unix/ztypes_netbsd_amd64.go @@ -107,6 +107,15 @@ const ( PathMax = 0x400 ) +const ( + FADV_NORMAL = 0x0 + FADV_RANDOM = 0x1 + FADV_SEQUENTIAL = 0x2 + FADV_WILLNEED = 0x3 + FADV_DONTNEED = 0x4 + FADV_NOREUSE = 0x5 +) + type RawSockaddrInet4 struct { Len uint8 Family uint8 diff --git a/golang.org/x/sys/unix/ztypes_netbsd_arm.go b/golang.org/x/sys/unix/ztypes_netbsd_arm.go index 211f6419..00525e7b 100644 --- a/golang.org/x/sys/unix/ztypes_netbsd_arm.go +++ b/golang.org/x/sys/unix/ztypes_netbsd_arm.go @@ -108,6 +108,15 @@ const ( PathMax = 0x400 ) +const ( + FADV_NORMAL = 0x0 + FADV_RANDOM = 0x1 + FADV_SEQUENTIAL = 0x2 + FADV_WILLNEED = 0x3 + FADV_DONTNEED = 0x4 + FADV_NOREUSE = 0x5 +) + type RawSockaddrInet4 struct { Len uint8 Family uint8 diff --git a/golang.org/x/sys/unix/ztypes_solaris_amd64.go b/golang.org/x/sys/unix/ztypes_solaris_amd64.go index d4454524..2248598d 100644 --- a/golang.org/x/sys/unix/ztypes_solaris_amd64.go +++ b/golang.org/x/sys/unix/ztypes_solaris_amd64.go @@ -93,40 +93,40 @@ const ( ) type Stat_t struct { - Dev uint64 - Ino uint64 - Mode uint32 - Nlink uint32 - Uid uint32 - Gid uint32 - Rdev uint64 - Size int64 - Atim Timespec - Mtim Timespec - Ctim Timespec - Blksize int32 - Pad_cgo_0 [4]byte - Blocks int64 - Fstype [16]int8 + Dev uint64 + Ino uint64 + Mode uint32 + Nlink uint32 + Uid uint32 + Gid uint32 + Rdev uint64 + Size int64 + Atim Timespec + Mtim Timespec + Ctim Timespec + Blksize int32 + _ [4]byte + Blocks int64 + Fstype [16]int8 } type Flock_t struct { - Type int16 - Whence int16 - Pad_cgo_0 [4]byte - Start int64 - Len int64 - Sysid int32 - Pid int32 - Pad [4]int64 + Type int16 + Whence int16 + _ [4]byte + Start int64 + Len int64 + Sysid int32 + Pid int32 + Pad [4]int64 } type Dirent struct { - Ino uint64 - Off int64 - Reclen uint16 - Name [1]int8 - Pad_cgo_0 [5]byte + Ino uint64 + Off int64 + Reclen uint16 + Name [1]int8 + _ [5]byte } type _Fsblkcnt_t uint64 @@ -213,13 +213,13 @@ type IPv6Mreq struct { type Msghdr struct { Name *byte Namelen uint32 - Pad_cgo_0 [4]byte + _ [4]byte Iov *Iovec Iovlen int32 - Pad_cgo_1 [4]byte + _ [4]byte Accrights *int8 Accrightslen int32 - Pad_cgo_2 [4]byte + _ [4]byte } type Cmsghdr struct { @@ -271,11 +271,11 @@ type Utsname struct { } type Ustat_t struct { - Tfree int64 - Tinode uint64 - Fname [6]int8 - Fpack [6]int8 - Pad_cgo_0 [4]byte + Tfree int64 + Tinode uint64 + Fname [6]int8 + Fpack [6]int8 + _ [4]byte } const ( @@ -295,21 +295,21 @@ const ( ) type IfMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Data IfData + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Data IfData } type IfData struct { Type uint8 Addrlen uint8 Hdrlen uint8 - Pad_cgo_0 [1]byte + _ [1]byte Mtu uint32 Metric uint32 Baudrate uint32 @@ -328,30 +328,30 @@ type IfData struct { } type IfaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - Pad_cgo_0 [2]byte - Metric int32 + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + _ [2]byte + Metric int32 } type RtMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Index uint16 - Pad_cgo_0 [2]byte - Flags int32 - Addrs int32 - Pid int32 - Seq int32 - Errno int32 - Use int32 - Inits uint32 - Rmx RtMetrics + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + _ [2]byte + Flags int32 + Addrs int32 + Pid int32 + Seq int32 + Errno int32 + Use int32 + Inits uint32 + Rmx RtMetrics } type RtMetrics struct { @@ -388,9 +388,9 @@ type BpfStat struct { } type BpfProgram struct { - Len uint32 - Pad_cgo_0 [4]byte - Insns *BpfInsn + Len uint32 + _ [4]byte + Insns *BpfInsn } type BpfInsn struct { @@ -406,30 +406,30 @@ type BpfTimeval struct { } type BpfHdr struct { - Tstamp BpfTimeval - Caplen uint32 - Datalen uint32 - Hdrlen uint16 - Pad_cgo_0 [2]byte + Tstamp BpfTimeval + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + _ [2]byte } type Termios struct { - Iflag uint32 - Oflag uint32 - Cflag uint32 - Lflag uint32 - Cc [19]uint8 - Pad_cgo_0 [1]byte + Iflag uint32 + Oflag uint32 + Cflag uint32 + Lflag uint32 + Cc [19]uint8 + _ [1]byte } type Termio struct { - Iflag uint16 - Oflag uint16 - Cflag uint16 - Lflag uint16 - Line int8 - Cc [8]uint8 - Pad_cgo_0 [1]byte + Iflag uint16 + Oflag uint16 + Cflag uint16 + Lflag uint16 + Line int8 + Cc [8]uint8 + _ [1]byte } type Winsize struct { diff --git a/golang.org/x/sys/windows/syscall.go b/golang.org/x/sys/windows/syscall.go index b07bc230..af828a91 100644 --- a/golang.org/x/sys/windows/syscall.go +++ b/golang.org/x/sys/windows/syscall.go @@ -11,11 +11,14 @@ // system, set $GOOS and $GOARCH to the desired system. For example, if // you want to view documentation for freebsd/arm on linux/amd64, set $GOOS // to freebsd and $GOARCH to arm. +// // The primary use of this package is inside other packages that provide a more // portable interface to the system, such as "os", "time" and "net". Use // those packages rather than this one if you can. +// // For details of the functions and data types in this package consult // the manuals for the appropriate operating system. +// // These calls return err == nil to indicate success; otherwise // err represents an operating system error describing the failure and // holds a value of type syscall.Errno. diff --git a/golang.org/x/tools/imports/fix.go b/golang.org/x/tools/imports/fix.go index de660879..68961ba6 100644 --- a/golang.org/x/tools/imports/fix.go +++ b/golang.org/x/tools/imports/fix.go @@ -32,16 +32,26 @@ var ( testMu sync.RWMutex // guards globals reset by tests; used only if inTests ) -// LocalPrefix, if set, instructs Process to sort import paths with the given -// prefix into another group after 3rd-party packages. +// LocalPrefix is a comma-separated string of import path prefixes, which, if +// set, instructs Process to sort the import paths with the given prefixes +// into another group after 3rd-party packages. var LocalPrefix string +func localPrefixes() []string { + if LocalPrefix != "" { + return strings.Split(LocalPrefix, ",") + } + return nil +} + // importToGroup is a list of functions which map from an import path to // a group number. var importToGroup = []func(importPath string) (num int, ok bool){ func(importPath string) (num int, ok bool) { - if LocalPrefix != "" && strings.HasPrefix(importPath, LocalPrefix) { - return 3, true + for _, p := range localPrefixes() { + if strings.HasPrefix(importPath, p) || strings.TrimSuffix(p, "/") == importPath { + return 3, true + } } return }, diff --git a/google.golang.org/api/internal/creds.go b/google.golang.org/api/internal/creds.go index b546b63b..c16b7b62 100644 --- a/google.golang.org/api/internal/creds.go +++ b/google.golang.org/api/internal/creds.go @@ -15,90 +15,28 @@ package internal import ( - "encoding/json" "fmt" "io/ioutil" - "time" "golang.org/x/net/context" - "golang.org/x/oauth2" "golang.org/x/oauth2/google" ) // Creds returns credential information obtained from DialSettings, or if none, then // it returns default credential information. func Creds(ctx context.Context, ds *DialSettings) (*google.DefaultCredentials, error) { + if ds.Credentials != nil { + return ds.Credentials, nil + } if ds.CredentialsFile != "" { - return credFileTokenSource(ctx, ds.CredentialsFile, ds.Scopes...) + data, err := ioutil.ReadFile(ds.CredentialsFile) + if err != nil { + return nil, fmt.Errorf("cannot read credentials file: %v", err) + } + return google.CredentialsFromJSON(ctx, data, ds.Scopes...) } if ds.TokenSource != nil { return &google.DefaultCredentials{TokenSource: ds.TokenSource}, nil } return google.FindDefaultCredentials(ctx, ds.Scopes...) } - -// credFileTokenSource reads a refresh token file or a service account and returns -// a TokenSource constructed from the config. -func credFileTokenSource(ctx context.Context, filename string, scope ...string) (*google.DefaultCredentials, error) { - data, err := ioutil.ReadFile(filename) - if err != nil { - return nil, fmt.Errorf("cannot read credentials file: %v", err) - } - // See if it is a refresh token credentials file first. - ts, ok, err := refreshTokenTokenSource(ctx, data, scope...) - if err != nil { - return nil, err - } - if ok { - return &google.DefaultCredentials{ - TokenSource: ts, - JSON: data, - }, nil - } - - // If not, it should be a service account. - cfg, err := google.JWTConfigFromJSON(data, scope...) - if err != nil { - return nil, fmt.Errorf("google.JWTConfigFromJSON: %v", err) - } - // jwt.Config does not expose the project ID, so re-unmarshal to get it. - var pid struct { - ProjectID string `json:"project_id"` - } - if err := json.Unmarshal(data, &pid); err != nil { - return nil, err - } - return &google.DefaultCredentials{ - ProjectID: pid.ProjectID, - TokenSource: cfg.TokenSource(ctx), - JSON: data, - }, nil -} - -func refreshTokenTokenSource(ctx context.Context, data []byte, scope ...string) (oauth2.TokenSource, bool, error) { - var c cred - if err := json.Unmarshal(data, &c); err != nil { - return nil, false, fmt.Errorf("cannot unmarshal credentials file: %v", err) - } - if c.ClientID == "" || c.ClientSecret == "" || c.RefreshToken == "" || c.Type != "authorized_user" { - return nil, false, nil - } - cfg := &oauth2.Config{ - ClientID: c.ClientID, - ClientSecret: c.ClientSecret, - Endpoint: google.Endpoint, - RedirectURL: "urn:ietf:wg:oauth:2.0:oob", - Scopes: scope, - } - return cfg.TokenSource(ctx, &oauth2.Token{ - RefreshToken: c.RefreshToken, - Expiry: time.Now(), - }), true, nil -} - -type cred struct { - ClientID string `json:"client_id"` - ClientSecret string `json:"client_secret"` - RefreshToken string `json:"refresh_token"` - Type string `json:"type"` -} diff --git a/google.golang.org/api/internal/settings.go b/google.golang.org/api/internal/settings.go index dde7a624..34dfa5a8 100644 --- a/google.golang.org/api/internal/settings.go +++ b/google.golang.org/api/internal/settings.go @@ -20,6 +20,7 @@ import ( "net/http" "golang.org/x/oauth2" + "golang.org/x/oauth2/google" "google.golang.org/grpc" ) @@ -29,6 +30,7 @@ type DialSettings struct { Endpoint string Scopes []string TokenSource oauth2.TokenSource + Credentials *google.DefaultCredentials CredentialsFile string // if set, Token Source is ignored. UserAgent string APIKey string @@ -40,10 +42,16 @@ type DialSettings struct { // Validate reports an error if ds is invalid. func (ds *DialSettings) Validate() error { - hasCreds := ds.APIKey != "" || ds.TokenSource != nil || ds.CredentialsFile != "" + hasCreds := ds.APIKey != "" || ds.TokenSource != nil || ds.CredentialsFile != "" || ds.Credentials != nil if ds.NoAuth && hasCreds { return errors.New("options.WithoutAuthentication is incompatible with any option that provides credentials") } + // Credentials should not appear with other options. + // We currently allow TokenSource and CredentialsFile to coexist. + // TODO(jba): make TokenSource & CredentialsFile an error (breaking change). + if ds.Credentials != nil && (ds.APIKey != "" || ds.TokenSource != nil || ds.CredentialsFile != "") { + return errors.New("multiple credential options provided") + } if ds.HTTPClient != nil && ds.GRPCConn != nil { return errors.New("WithHTTPClient is incompatible with WithGRPCConn") } diff --git a/google.golang.org/api/option/credentials_go19.go b/google.golang.org/api/option/credentials_go19.go new file mode 100644 index 00000000..c08c1149 --- /dev/null +++ b/google.golang.org/api/option/credentials_go19.go @@ -0,0 +1,32 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// +build go1.9 + +package option + +import ( + "golang.org/x/oauth2/google" + "google.golang.org/api/internal" +) + +type withCreds google.Credentials + +func (w *withCreds) Apply(o *internal.DialSettings) { + o.Credentials = (*google.Credentials)(w) +} + +func WithCredentials(creds *google.Credentials) ClientOption { + return (*withCreds)(creds) +} diff --git a/google.golang.org/api/option/credentials_notgo19.go b/google.golang.org/api/option/credentials_notgo19.go new file mode 100644 index 00000000..90d22900 --- /dev/null +++ b/google.golang.org/api/option/credentials_notgo19.go @@ -0,0 +1,32 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// +build !go1.9 + +package option + +import ( + "golang.org/x/oauth2/google" + "google.golang.org/api/internal" +) + +type withCreds google.DefaultCredentials + +func (w *withCreds) Apply(o *internal.DialSettings) { + o.Credentials = (*google.DefaultCredentials)(w) +} + +func WithCredentials(creds *google.DefaultCredentials) ClientOption { + return (*withCreds)(creds) +} diff --git a/google.golang.org/api/servicecontrol/v1/servicecontrol-gen.go b/google.golang.org/api/servicecontrol/v1/servicecontrol-gen.go index 63f4327c..eb5788dd 100644 --- a/google.golang.org/api/servicecontrol/v1/servicecontrol-gen.go +++ b/google.golang.org/api/servicecontrol/v1/servicecontrol-gen.go @@ -470,6 +470,8 @@ type CheckError struct { // `ACTIVE` in LoquatV2. // "SECURITY_POLICY_VIOLATED" - Request is not allowed as per security // policies defined in Org Policy. + // "INVALID_CREDENTIAL" - The credential in the request can not be + // verified. // "NAMESPACE_LOOKUP_UNAVAILABLE" - The backend server for looking up // project id/number is unavailable. // "SERVICE_STATUS_UNAVAILABLE" - The backend server for checking @@ -1365,7 +1367,9 @@ type Operation struct { // used to handle the API request (e.g. ESP), // - `servicecontrol.googleapis.com/platform` describing the // platform - // where the API is served (e.g. GAE, GCE, GKE). + // where the API is served, such as App Engine, Compute Engine, + // or + // Kubernetes Engine. Labels map[string]string `json:"labels,omitempty"` // LogEntries: Represents information to be logged. @@ -2529,24 +2533,29 @@ type ServicesCheckCall struct { header_ http.Header } -// Check: Checks an operation with Google Service Control to decide -// whether -// the given operation should proceed. It should be called before -// the -// operation is executed. +// Check: Checks whether an operation on a service should be allowed to +// proceed +// based on the configuration of the service and related policies. It +// must be +// called before the operation is executed. // // If feasible, the client should cache the check results and reuse them // for -// 60 seconds. In case of server errors, the client can rely on the -// cached -// results for longer time. +// 60 seconds. In case of any server errors, the client should rely on +// the +// cached results for much longer time to avoid outage. +// WARNING: There is general 60s delay for the configuration and +// policy +// propagation, therefore callers MUST NOT depend on the `Check` method +// having +// the latest policy information. // // NOTE: the CheckRequest has the size limit of 64KB. // // This method requires the `servicemanagement.services.check` // permission // on the specified service. For more information, see -// [Google Cloud IAM](https://cloud.google.com/iam). +// [Cloud IAM](https://cloud.google.com/iam). func (r *ServicesService) Check(serviceName string, checkrequest *CheckRequest) *ServicesCheckCall { c := &ServicesCheckCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.serviceName = serviceName @@ -2640,7 +2649,7 @@ func (c *ServicesCheckCall) Do(opts ...googleapi.CallOption) (*CheckResponse, er } return ret, nil // { - // "description": "Checks an operation with Google Service Control to decide whether\nthe given operation should proceed. It should be called before the\noperation is executed.\n\nIf feasible, the client should cache the check results and reuse them for\n60 seconds. In case of server errors, the client can rely on the cached\nresults for longer time.\n\nNOTE: the CheckRequest has the size limit of 64KB.\n\nThis method requires the `servicemanagement.services.check` permission\non the specified service. For more information, see\n[Google Cloud IAM](https://cloud.google.com/iam).", + // "description": "Checks whether an operation on a service should be allowed to proceed\nbased on the configuration of the service and related policies. It must be\ncalled before the operation is executed.\n\nIf feasible, the client should cache the check results and reuse them for\n60 seconds. In case of any server errors, the client should rely on the\ncached results for much longer time to avoid outage.\nWARNING: There is general 60s delay for the configuration and policy\npropagation, therefore callers MUST NOT depend on the `Check` method having\nthe latest policy information.\n\nNOTE: the CheckRequest has the size limit of 64KB.\n\nThis method requires the `servicemanagement.services.check` permission\non the specified service. For more information, see\n[Cloud IAM](https://cloud.google.com/iam).", // "flatPath": "v1/services/{serviceName}:check", // "httpMethod": "POST", // "id": "servicecontrol.services.check", diff --git a/google.golang.org/api/transport/dial.go b/google.golang.org/api/transport/dial.go index 91d83257..c4c37191 100644 --- a/google.golang.org/api/transport/dial.go +++ b/google.golang.org/api/transport/dial.go @@ -21,10 +21,8 @@ import ( "net/http" "golang.org/x/net/context" - "golang.org/x/oauth2/google" "google.golang.org/grpc" - "google.golang.org/api/internal" "google.golang.org/api/option" gtransport "google.golang.org/api/transport/grpc" htransport "google.golang.org/api/transport/http" @@ -49,13 +47,3 @@ func DialGRPC(ctx context.Context, opts ...option.ClientOption) (*grpc.ClientCon func DialGRPCInsecure(ctx context.Context, opts ...option.ClientOption) (*grpc.ClientConn, error) { return gtransport.DialInsecure(ctx, opts...) } - -// Creds constructs a google.DefaultCredentials from the information in the options, -// or obtains the default credentials in the same way as google.FindDefaultCredentials. -func Creds(ctx context.Context, opts ...option.ClientOption) (*google.DefaultCredentials, error) { - var ds internal.DialSettings - for _, opt := range opts { - opt.Apply(&ds) - } - return internal.Creds(ctx, &ds) -} diff --git a/google.golang.org/api/transport/go19.go b/google.golang.org/api/transport/go19.go new file mode 100644 index 00000000..0177e560 --- /dev/null +++ b/google.golang.org/api/transport/go19.go @@ -0,0 +1,34 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// +build go1.9 + +package transport + +import ( + "golang.org/x/net/context" + "golang.org/x/oauth2/google" + "google.golang.org/api/internal" + "google.golang.org/api/option" +) + +// Creds constructs a google.Credentials from the information in the options, +// or obtains the default credentials in the same way as google.FindDefaultCredentials. +func Creds(ctx context.Context, opts ...option.ClientOption) (*google.Credentials, error) { + var ds internal.DialSettings + for _, opt := range opts { + opt.Apply(&ds) + } + return internal.Creds(ctx, &ds) +} diff --git a/google.golang.org/api/transport/grpc/dial.go b/google.golang.org/api/transport/grpc/dial.go index 4d0c346f..2b8ed6b0 100644 --- a/google.golang.org/api/transport/grpc/dial.go +++ b/google.golang.org/api/transport/grpc/dial.go @@ -75,6 +75,10 @@ func dial(ctx context.Context, insecure bool, opts []option.ClientOption) (*grpc // Use the Socket API on App Engine. grpcOpts = append(grpcOpts, appengineDialerHook(ctx)) } + // Add tracing, but before the other options, so that clients can override the + // gRPC stats handler. + // This assumes that gRPC options are processed in order, left to right. + grpcOpts = addOCStatsHandler(grpcOpts) grpcOpts = append(grpcOpts, o.GRPCDialOpts...) if o.UserAgent != "" { grpcOpts = append(grpcOpts, grpc.WithUserAgent(o.UserAgent)) diff --git a/google.golang.org/api/transport/grpc/go18.go b/google.golang.org/api/transport/grpc/go18.go new file mode 100644 index 00000000..a4b4a994 --- /dev/null +++ b/google.golang.org/api/transport/grpc/go18.go @@ -0,0 +1,26 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// +build go1.8 + +package grpc + +import ( + "go.opencensus.io/plugin/ocgrpc" + "google.golang.org/grpc" +) + +func addOCStatsHandler(opts []grpc.DialOption) []grpc.DialOption { + return append(opts, grpc.WithStatsHandler(&ocgrpc.ClientHandler{})) +} diff --git a/google.golang.org/api/transport/grpc/not_go18.go b/google.golang.org/api/transport/grpc/not_go18.go new file mode 100644 index 00000000..f509d863 --- /dev/null +++ b/google.golang.org/api/transport/grpc/not_go18.go @@ -0,0 +1,21 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// +build !go1.8 + +package grpc + +import "google.golang.org/grpc" + +func addOCStatsHandler(opts []grpc.DialOption) []grpc.DialOption { return opts } diff --git a/google.golang.org/api/transport/http/dial.go b/google.golang.org/api/transport/http/dial.go index eda6e5ed..df34c681 100644 --- a/google.golang.org/api/transport/http/dial.go +++ b/google.golang.org/api/transport/http/dial.go @@ -46,34 +46,31 @@ func NewClient(ctx context.Context, opts ...option.ClientOption) (*http.Client, if o.HTTPClient != nil { return o.HTTPClient, o.Endpoint, nil } - uat := userAgentTransport{ - base: baseTransport(ctx), + trans := baseTransport(ctx) + trans = userAgentTransport{ + base: trans, userAgent: o.UserAgent, } - var hc *http.Client + trans = addOCTransport(trans) switch { case o.NoAuth: - hc = &http.Client{Transport: uat} + // Do nothing. case o.APIKey != "": - hc = &http.Client{ - Transport: &transport.APIKey{ - Key: o.APIKey, - Transport: uat, - }, + trans = &transport.APIKey{ + Transport: trans, + Key: o.APIKey, } default: creds, err := internal.Creds(ctx, &o) if err != nil { return nil, "", err } - hc = &http.Client{ - Transport: &oauth2.Transport{ - Source: creds.TokenSource, - Base: uat, - }, + trans = &oauth2.Transport{ + Base: trans, + Source: creds.TokenSource, } } - return hc, o.Endpoint, nil + return &http.Client{Transport: trans}, o.Endpoint, nil } type userAgentTransport struct { diff --git a/google.golang.org/api/transport/http/go18.go b/google.golang.org/api/transport/http/go18.go new file mode 100644 index 00000000..1d4bb8e7 --- /dev/null +++ b/google.golang.org/api/transport/http/go18.go @@ -0,0 +1,31 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// +build go1.8 + +package http + +import ( + "net/http" + + "go.opencensus.io/exporter/stackdriver/propagation" + "go.opencensus.io/plugin/ochttp" +) + +func addOCTransport(trans http.RoundTripper) http.RoundTripper { + return &ochttp.Transport{ + Base: trans, + Propagation: &propagation.HTTPFormat{}, + } +} diff --git a/google.golang.org/api/transport/http/not_go18.go b/google.golang.org/api/transport/http/not_go18.go new file mode 100644 index 00000000..628a21a8 --- /dev/null +++ b/google.golang.org/api/transport/http/not_go18.go @@ -0,0 +1,21 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// +build !go1.8 + +package http + +import "net/http" + +func addOCTransport(trans http.RoundTripper) http.RoundTripper { return trans } diff --git a/google.golang.org/api/transport/not_go19.go b/google.golang.org/api/transport/not_go19.go new file mode 100644 index 00000000..4489bc9b --- /dev/null +++ b/google.golang.org/api/transport/not_go19.go @@ -0,0 +1,34 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// +build !go1.9 + +package transport + +import ( + "golang.org/x/net/context" + "golang.org/x/oauth2/google" + "google.golang.org/api/internal" + "google.golang.org/api/option" +) + +// Creds constructs a google.DefaultCredentials from the information in the options, +// or obtains the default credentials in the same way as google.FindDefaultCredentials. +func Creds(ctx context.Context, opts ...option.ClientOption) (*google.DefaultCredentials, error) { + var ds internal.DialSettings + for _, opt := range opts { + opt.Apply(&ds) + } + return internal.Creds(ctx, &ds) +} diff --git a/google.golang.org/genproto/googleapis/monitoring/v3/alert.pb.go b/google.golang.org/genproto/googleapis/monitoring/v3/alert.pb.go new file mode 100644 index 00000000..61570e2a --- /dev/null +++ b/google.golang.org/genproto/googleapis/monitoring/v3/alert.pb.go @@ -0,0 +1,904 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/monitoring/v3/alert.proto + +/* +Package monitoring is a generated protocol buffer package. + +It is generated from these files: + google/monitoring/v3/alert.proto + google/monitoring/v3/alert_service.proto + google/monitoring/v3/common.proto + google/monitoring/v3/group.proto + google/monitoring/v3/group_service.proto + google/monitoring/v3/metric.proto + google/monitoring/v3/metric_service.proto + google/monitoring/v3/mutation_record.proto + google/monitoring/v3/notification.proto + google/monitoring/v3/notification_service.proto + google/monitoring/v3/uptime.proto + google/monitoring/v3/uptime_service.proto + +It has these top-level messages: + AlertPolicy + CreateAlertPolicyRequest + GetAlertPolicyRequest + ListAlertPoliciesRequest + ListAlertPoliciesResponse + UpdateAlertPolicyRequest + DeleteAlertPolicyRequest + TypedValue + TimeInterval + Aggregation + Group + ListGroupsRequest + ListGroupsResponse + GetGroupRequest + CreateGroupRequest + UpdateGroupRequest + DeleteGroupRequest + ListGroupMembersRequest + ListGroupMembersResponse + Point + TimeSeries + ListMonitoredResourceDescriptorsRequest + ListMonitoredResourceDescriptorsResponse + GetMonitoredResourceDescriptorRequest + ListMetricDescriptorsRequest + ListMetricDescriptorsResponse + GetMetricDescriptorRequest + CreateMetricDescriptorRequest + DeleteMetricDescriptorRequest + ListTimeSeriesRequest + ListTimeSeriesResponse + CreateTimeSeriesRequest + CreateTimeSeriesError + MutationRecord + NotificationChannelDescriptor + NotificationChannel + ListNotificationChannelDescriptorsRequest + ListNotificationChannelDescriptorsResponse + GetNotificationChannelDescriptorRequest + CreateNotificationChannelRequest + ListNotificationChannelsRequest + ListNotificationChannelsResponse + GetNotificationChannelRequest + UpdateNotificationChannelRequest + DeleteNotificationChannelRequest + SendNotificationChannelVerificationCodeRequest + GetNotificationChannelVerificationCodeRequest + GetNotificationChannelVerificationCodeResponse + VerifyNotificationChannelRequest + UptimeCheckConfig + UptimeCheckIp + ListUptimeCheckConfigsRequest + ListUptimeCheckConfigsResponse + GetUptimeCheckConfigRequest + CreateUptimeCheckConfigRequest + UpdateUptimeCheckConfigRequest + DeleteUptimeCheckConfigRequest + ListUptimeCheckIpsRequest + ListUptimeCheckIpsResponse +*/ +package monitoring + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_protobuf3 "github.com/golang/protobuf/ptypes/duration" +import google_protobuf4 "github.com/golang/protobuf/ptypes/wrappers" + +// 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.ProtoPackageIsVersion2 // please upgrade the proto package + +// Operators for combining conditions. +type AlertPolicy_ConditionCombinerType int32 + +const ( + // An unspecified combiner. + AlertPolicy_COMBINE_UNSPECIFIED AlertPolicy_ConditionCombinerType = 0 + // Combine conditions using the logical `AND` operator. An + // incident is created only if all conditions are met + // simultaneously. This combiner is satisfied if all conditions are + // met, even if they are met on completely different resources. + AlertPolicy_AND AlertPolicy_ConditionCombinerType = 1 + // Combine conditions using the logical `OR` operator. An incident + // is created if any of the listed conditions is met. + AlertPolicy_OR AlertPolicy_ConditionCombinerType = 2 + // Combine conditions using logical `AND` operator, but unlike the regular + // `AND` option, an incident is created only if all conditions are met + // simultaneously on at least one resource. + AlertPolicy_AND_WITH_MATCHING_RESOURCE AlertPolicy_ConditionCombinerType = 3 +) + +var AlertPolicy_ConditionCombinerType_name = map[int32]string{ + 0: "COMBINE_UNSPECIFIED", + 1: "AND", + 2: "OR", + 3: "AND_WITH_MATCHING_RESOURCE", +} +var AlertPolicy_ConditionCombinerType_value = map[string]int32{ + "COMBINE_UNSPECIFIED": 0, + "AND": 1, + "OR": 2, + "AND_WITH_MATCHING_RESOURCE": 3, +} + +func (x AlertPolicy_ConditionCombinerType) String() string { + return proto.EnumName(AlertPolicy_ConditionCombinerType_name, int32(x)) +} +func (AlertPolicy_ConditionCombinerType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{0, 0} +} + +// A description of the conditions under which some aspect of your system is +// considered to be "unhealthy" and the ways to notify people or services about +// this state. For an overview of alert policies, see +// [Introduction to Alerting](/monitoring/alerts/). +type AlertPolicy struct { + // Required if the policy exists. The resource name for this policy. The + // syntax is: + // + // projects/[PROJECT_ID]/alertPolicies/[ALERT_POLICY_ID] + // + // `[ALERT_POLICY_ID]` is assigned by Stackdriver Monitoring when the policy + // is created. When calling the + // [alertPolicies.create][google.monitoring.v3.AlertPolicyService.CreateAlertPolicy] + // method, do not include the `name` field in the alerting policy passed as + // part of the request. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // A short name or phrase used to identify the policy in dashboards, + // notifications, and incidents. To avoid confusion, don't use the same + // display name for multiple policies in the same project. The name is + // limited to 512 Unicode characters. + DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName" json:"display_name,omitempty"` + // Documentation that is included with notifications and incidents related to + // this policy. Best practice is for the documentation to include information + // to help responders understand, mitigate, escalate, and correct the + // underlying problems detected by the alerting policy. Notification channels + // that have limited capacity might not show this documentation. + Documentation *AlertPolicy_Documentation `protobuf:"bytes,13,opt,name=documentation" json:"documentation,omitempty"` + // User-supplied key/value data to be used for organizing and + // identifying the `AlertPolicy` objects. + // + // The field can contain up to 64 entries. Each key and value is limited to + // 63 Unicode characters or 128 bytes, whichever is smaller. Labels and + // values can contain only lowercase letters, numerals, underscores, and + // dashes. Keys must begin with a letter. + UserLabels map[string]string `protobuf:"bytes,16,rep,name=user_labels,json=userLabels" json:"user_labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // A list of conditions for the policy. The conditions are combined by AND or + // OR according to the `combiner` field. If the combined conditions evaluate + // to true, then an incident is created. A policy can have from one to six + // conditions. + Conditions []*AlertPolicy_Condition `protobuf:"bytes,12,rep,name=conditions" json:"conditions,omitempty"` + // How to combine the results of multiple conditions + // to determine if an incident should be opened. + Combiner AlertPolicy_ConditionCombinerType `protobuf:"varint,6,opt,name=combiner,enum=google.monitoring.v3.AlertPolicy_ConditionCombinerType" json:"combiner,omitempty"` + // Whether or not the policy is enabled. On write, the default interpretation + // if unset is that the policy is enabled. On read, clients should not make + // any assumption about the state if it has not been populated. The + // field should always be populated on List and Get operations, unless + // a field projection has been specified that strips it out. + Enabled *google_protobuf4.BoolValue `protobuf:"bytes,17,opt,name=enabled" json:"enabled,omitempty"` + // Identifies the notification channels to which notifications should be sent + // when incidents are opened or closed or when new violations occur on + // an already opened incident. Each element of this array corresponds to + // the `name` field in each of the + // [`NotificationChannel`][google.monitoring.v3.NotificationChannel] + // objects that are returned from the [`ListNotificationChannels`] + // [google.monitoring.v3.NotificationChannelService.ListNotificationChannels] + // method. The syntax of the entries in this field is: + // + // projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID] + NotificationChannels []string `protobuf:"bytes,14,rep,name=notification_channels,json=notificationChannels" json:"notification_channels,omitempty"` + // A read-only record of the creation of the alerting policy. If provided + // in a call to create or update, this field will be ignored. + CreationRecord *MutationRecord `protobuf:"bytes,10,opt,name=creation_record,json=creationRecord" json:"creation_record,omitempty"` + // A read-only record of the most recent change to the alerting policy. If + // provided in a call to create or update, this field will be ignored. + MutationRecord *MutationRecord `protobuf:"bytes,11,opt,name=mutation_record,json=mutationRecord" json:"mutation_record,omitempty"` +} + +func (m *AlertPolicy) Reset() { *m = AlertPolicy{} } +func (m *AlertPolicy) String() string { return proto.CompactTextString(m) } +func (*AlertPolicy) ProtoMessage() {} +func (*AlertPolicy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *AlertPolicy) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *AlertPolicy) GetDisplayName() string { + if m != nil { + return m.DisplayName + } + return "" +} + +func (m *AlertPolicy) GetDocumentation() *AlertPolicy_Documentation { + if m != nil { + return m.Documentation + } + return nil +} + +func (m *AlertPolicy) GetUserLabels() map[string]string { + if m != nil { + return m.UserLabels + } + return nil +} + +func (m *AlertPolicy) GetConditions() []*AlertPolicy_Condition { + if m != nil { + return m.Conditions + } + return nil +} + +func (m *AlertPolicy) GetCombiner() AlertPolicy_ConditionCombinerType { + if m != nil { + return m.Combiner + } + return AlertPolicy_COMBINE_UNSPECIFIED +} + +func (m *AlertPolicy) GetEnabled() *google_protobuf4.BoolValue { + if m != nil { + return m.Enabled + } + return nil +} + +func (m *AlertPolicy) GetNotificationChannels() []string { + if m != nil { + return m.NotificationChannels + } + return nil +} + +func (m *AlertPolicy) GetCreationRecord() *MutationRecord { + if m != nil { + return m.CreationRecord + } + return nil +} + +func (m *AlertPolicy) GetMutationRecord() *MutationRecord { + if m != nil { + return m.MutationRecord + } + return nil +} + +// A content string and a MIME type that describes the content string's +// format. +type AlertPolicy_Documentation struct { + // The text of the documentation, interpreted according to `mime_type`. + // The content may not exceed 8,192 Unicode characters and may not exceed + // more than 10,240 bytes when encoded in UTF-8 format, whichever is + // smaller. + Content string `protobuf:"bytes,1,opt,name=content" json:"content,omitempty"` + // The format of the `content` field. Presently, only the value + // `"text/markdown"` is supported. See + // [Markdown](https://en.wikipedia.org/wiki/Markdown) for more information. + MimeType string `protobuf:"bytes,2,opt,name=mime_type,json=mimeType" json:"mime_type,omitempty"` +} + +func (m *AlertPolicy_Documentation) Reset() { *m = AlertPolicy_Documentation{} } +func (m *AlertPolicy_Documentation) String() string { return proto.CompactTextString(m) } +func (*AlertPolicy_Documentation) ProtoMessage() {} +func (*AlertPolicy_Documentation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} } + +func (m *AlertPolicy_Documentation) GetContent() string { + if m != nil { + return m.Content + } + return "" +} + +func (m *AlertPolicy_Documentation) GetMimeType() string { + if m != nil { + return m.MimeType + } + return "" +} + +// A condition is a true/false test that determines when an alerting policy +// should open an incident. If a condition evaluates to true, it signifies +// that something is wrong. +type AlertPolicy_Condition struct { + // Required if the condition exists. The unique resource name for this + // condition. Its syntax is: + // + // projects/[PROJECT_ID]/alertPolicies/[POLICY_ID]/conditions/[CONDITION_ID] + // + // `[CONDITION_ID]` is assigned by Stackdriver Monitoring when the + // condition is created as part of a new or updated alerting policy. + // + // When calling the + // [alertPolicies.create][google.monitoring.v3.AlertPolicyService.CreateAlertPolicy] + // method, do not include the `name` field in the conditions of the + // requested alerting policy. Stackdriver Monitoring creates the + // condition identifiers and includes them in the new policy. + // + // When calling the + // [alertPolicies.update][google.monitoring.v3.AlertPolicyService.UpdateAlertPolicy] + // method to update a policy, including a condition `name` causes the + // existing condition to be updated. Conditions without names are added to + // the updated policy. Existing conditions are deleted if they are not + // updated. + // + // Best practice is to preserve `[CONDITION_ID]` if you make only small + // changes, such as those to condition thresholds, durations, or trigger + // values. Otherwise, treat the change as a new condition and let the + // existing condition be deleted. + Name string `protobuf:"bytes,12,opt,name=name" json:"name,omitempty"` + // A short name or phrase used to identify the condition in dashboards, + // notifications, and incidents. To avoid confusion, don't use the same + // display name for multiple conditions in the same policy. + DisplayName string `protobuf:"bytes,6,opt,name=display_name,json=displayName" json:"display_name,omitempty"` + // Only one of the following condition types will be specified. + // + // Types that are valid to be assigned to Condition: + // *AlertPolicy_Condition_ConditionThreshold + // *AlertPolicy_Condition_ConditionAbsent + Condition isAlertPolicy_Condition_Condition `protobuf_oneof:"condition"` +} + +func (m *AlertPolicy_Condition) Reset() { *m = AlertPolicy_Condition{} } +func (m *AlertPolicy_Condition) String() string { return proto.CompactTextString(m) } +func (*AlertPolicy_Condition) ProtoMessage() {} +func (*AlertPolicy_Condition) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 1} } + +type isAlertPolicy_Condition_Condition interface { + isAlertPolicy_Condition_Condition() +} + +type AlertPolicy_Condition_ConditionThreshold struct { + ConditionThreshold *AlertPolicy_Condition_MetricThreshold `protobuf:"bytes,1,opt,name=condition_threshold,json=conditionThreshold,oneof"` +} +type AlertPolicy_Condition_ConditionAbsent struct { + ConditionAbsent *AlertPolicy_Condition_MetricAbsence `protobuf:"bytes,2,opt,name=condition_absent,json=conditionAbsent,oneof"` +} + +func (*AlertPolicy_Condition_ConditionThreshold) isAlertPolicy_Condition_Condition() {} +func (*AlertPolicy_Condition_ConditionAbsent) isAlertPolicy_Condition_Condition() {} + +func (m *AlertPolicy_Condition) GetCondition() isAlertPolicy_Condition_Condition { + if m != nil { + return m.Condition + } + return nil +} + +func (m *AlertPolicy_Condition) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *AlertPolicy_Condition) GetDisplayName() string { + if m != nil { + return m.DisplayName + } + return "" +} + +func (m *AlertPolicy_Condition) GetConditionThreshold() *AlertPolicy_Condition_MetricThreshold { + if x, ok := m.GetCondition().(*AlertPolicy_Condition_ConditionThreshold); ok { + return x.ConditionThreshold + } + return nil +} + +func (m *AlertPolicy_Condition) GetConditionAbsent() *AlertPolicy_Condition_MetricAbsence { + if x, ok := m.GetCondition().(*AlertPolicy_Condition_ConditionAbsent); ok { + return x.ConditionAbsent + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*AlertPolicy_Condition) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _AlertPolicy_Condition_OneofMarshaler, _AlertPolicy_Condition_OneofUnmarshaler, _AlertPolicy_Condition_OneofSizer, []interface{}{ + (*AlertPolicy_Condition_ConditionThreshold)(nil), + (*AlertPolicy_Condition_ConditionAbsent)(nil), + } +} + +func _AlertPolicy_Condition_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*AlertPolicy_Condition) + // condition + switch x := m.Condition.(type) { + case *AlertPolicy_Condition_ConditionThreshold: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ConditionThreshold); err != nil { + return err + } + case *AlertPolicy_Condition_ConditionAbsent: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ConditionAbsent); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("AlertPolicy_Condition.Condition has unexpected type %T", x) + } + return nil +} + +func _AlertPolicy_Condition_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*AlertPolicy_Condition) + switch tag { + case 1: // condition.condition_threshold + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(AlertPolicy_Condition_MetricThreshold) + err := b.DecodeMessage(msg) + m.Condition = &AlertPolicy_Condition_ConditionThreshold{msg} + return true, err + case 2: // condition.condition_absent + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(AlertPolicy_Condition_MetricAbsence) + err := b.DecodeMessage(msg) + m.Condition = &AlertPolicy_Condition_ConditionAbsent{msg} + return true, err + default: + return false, nil + } +} + +func _AlertPolicy_Condition_OneofSizer(msg proto.Message) (n int) { + m := msg.(*AlertPolicy_Condition) + // condition + switch x := m.Condition.(type) { + case *AlertPolicy_Condition_ConditionThreshold: + s := proto.Size(x.ConditionThreshold) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *AlertPolicy_Condition_ConditionAbsent: + s := proto.Size(x.ConditionAbsent) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Specifies how many time series must fail a predicate to trigger a +// condition. If not specified, then a `{count: 1}` trigger is used. +type AlertPolicy_Condition_Trigger struct { + // A type of trigger. + // + // Types that are valid to be assigned to Type: + // *AlertPolicy_Condition_Trigger_Count + // *AlertPolicy_Condition_Trigger_Percent + Type isAlertPolicy_Condition_Trigger_Type `protobuf_oneof:"type"` +} + +func (m *AlertPolicy_Condition_Trigger) Reset() { *m = AlertPolicy_Condition_Trigger{} } +func (m *AlertPolicy_Condition_Trigger) String() string { return proto.CompactTextString(m) } +func (*AlertPolicy_Condition_Trigger) ProtoMessage() {} +func (*AlertPolicy_Condition_Trigger) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{0, 1, 0} +} + +type isAlertPolicy_Condition_Trigger_Type interface { + isAlertPolicy_Condition_Trigger_Type() +} + +type AlertPolicy_Condition_Trigger_Count struct { + Count int32 `protobuf:"varint,1,opt,name=count,oneof"` +} +type AlertPolicy_Condition_Trigger_Percent struct { + Percent float64 `protobuf:"fixed64,2,opt,name=percent,oneof"` +} + +func (*AlertPolicy_Condition_Trigger_Count) isAlertPolicy_Condition_Trigger_Type() {} +func (*AlertPolicy_Condition_Trigger_Percent) isAlertPolicy_Condition_Trigger_Type() {} + +func (m *AlertPolicy_Condition_Trigger) GetType() isAlertPolicy_Condition_Trigger_Type { + if m != nil { + return m.Type + } + return nil +} + +func (m *AlertPolicy_Condition_Trigger) GetCount() int32 { + if x, ok := m.GetType().(*AlertPolicy_Condition_Trigger_Count); ok { + return x.Count + } + return 0 +} + +func (m *AlertPolicy_Condition_Trigger) GetPercent() float64 { + if x, ok := m.GetType().(*AlertPolicy_Condition_Trigger_Percent); ok { + return x.Percent + } + return 0 +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*AlertPolicy_Condition_Trigger) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _AlertPolicy_Condition_Trigger_OneofMarshaler, _AlertPolicy_Condition_Trigger_OneofUnmarshaler, _AlertPolicy_Condition_Trigger_OneofSizer, []interface{}{ + (*AlertPolicy_Condition_Trigger_Count)(nil), + (*AlertPolicy_Condition_Trigger_Percent)(nil), + } +} + +func _AlertPolicy_Condition_Trigger_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*AlertPolicy_Condition_Trigger) + // type + switch x := m.Type.(type) { + case *AlertPolicy_Condition_Trigger_Count: + b.EncodeVarint(1<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.Count)) + case *AlertPolicy_Condition_Trigger_Percent: + b.EncodeVarint(2<<3 | proto.WireFixed64) + b.EncodeFixed64(math.Float64bits(x.Percent)) + case nil: + default: + return fmt.Errorf("AlertPolicy_Condition_Trigger.Type has unexpected type %T", x) + } + return nil +} + +func _AlertPolicy_Condition_Trigger_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*AlertPolicy_Condition_Trigger) + switch tag { + case 1: // type.count + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Type = &AlertPolicy_Condition_Trigger_Count{int32(x)} + return true, err + case 2: // type.percent + if wire != proto.WireFixed64 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed64() + m.Type = &AlertPolicy_Condition_Trigger_Percent{math.Float64frombits(x)} + return true, err + default: + return false, nil + } +} + +func _AlertPolicy_Condition_Trigger_OneofSizer(msg proto.Message) (n int) { + m := msg.(*AlertPolicy_Condition_Trigger) + // type + switch x := m.Type.(type) { + case *AlertPolicy_Condition_Trigger_Count: + n += proto.SizeVarint(1<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.Count)) + case *AlertPolicy_Condition_Trigger_Percent: + n += proto.SizeVarint(2<<3 | proto.WireFixed64) + n += 8 + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// A condition type that compares a collection of time series +// against a threshold. +type AlertPolicy_Condition_MetricThreshold struct { + // A [filter](/monitoring/api/v3/filters) that + // identifies which time series should be compared with the threshold. + // + // The filter is similar to the one that is specified in the + // [`MetricService.ListTimeSeries` + // request](/monitoring/api/ref_v3/rest/v3/projects.timeSeries/list) (that + // call is useful to verify the time series that will be retrieved / + // processed) and must specify the metric type and optionally may contain + // restrictions on resource type, resource labels, and metric labels. + // This field may not exceed 2048 Unicode characters in length. + Filter string `protobuf:"bytes,2,opt,name=filter" json:"filter,omitempty"` + // Specifies the alignment of data points in individual time series as + // well as how to combine the retrieved time series together (such as + // when aggregating multiple streams on each resource to a single + // stream for each resource or when aggregating streams across all + // members of a group of resrouces). Multiple aggregations + // are applied in the order specified. + // + // This field is similar to the one in the + // [`MetricService.ListTimeSeries` request](/monitoring/api/ref_v3/rest/v3/projects.timeSeries/list). + // It is advisable to use the `ListTimeSeries` method when debugging this field. + Aggregations []*Aggregation `protobuf:"bytes,8,rep,name=aggregations" json:"aggregations,omitempty"` + // A [filter](/monitoring/api/v3/filters) that identifies a time + // series that should be used as the denominator of a ratio that will be + // compared with the threshold. If a `denominator_filter` is specified, + // the time series specified by the `filter` field will be used as the + // numerator. + // + // The filter is similar to the one that is specified in the + // [`MetricService.ListTimeSeries` + // request](/monitoring/api/ref_v3/rest/v3/projects.timeSeries/list) (that + // call is useful to verify the time series that will be retrieved / + // processed) and must specify the metric type and optionally may contain + // restrictions on resource type, resource labels, and metric labels. + // This field may not exceed 2048 Unicode characters in length. + DenominatorFilter string `protobuf:"bytes,9,opt,name=denominator_filter,json=denominatorFilter" json:"denominator_filter,omitempty"` + // Specifies the alignment of data points in individual time series + // selected by `denominatorFilter` as + // well as how to combine the retrieved time series together (such as + // when aggregating multiple streams on each resource to a single + // stream for each resource or when aggregating streams across all + // members of a group of resources). + // + // When computing ratios, the `aggregations` and + // `denominator_aggregations` fields must use the same alignment period + // and produce time series that have the same periodicity and labels. + // + // This field is similar to the one in the + // [`MetricService.ListTimeSeries` + // request](/monitoring/api/ref_v3/rest/v3/projects.timeSeries/list). It + // is advisable to use the `ListTimeSeries` method when debugging this + // field. + DenominatorAggregations []*Aggregation `protobuf:"bytes,10,rep,name=denominator_aggregations,json=denominatorAggregations" json:"denominator_aggregations,omitempty"` + // The comparison to apply between the time series (indicated by `filter` + // and `aggregation`) and the threshold (indicated by `threshold_value`). + // The comparison is applied on each time series, with the time series + // on the left-hand side and the threshold on the right-hand side. + // + // Only `COMPARISON_LT` and `COMPARISON_GT` are supported currently. + Comparison ComparisonType `protobuf:"varint,4,opt,name=comparison,enum=google.monitoring.v3.ComparisonType" json:"comparison,omitempty"` + // A value against which to compare the time series. + ThresholdValue float64 `protobuf:"fixed64,5,opt,name=threshold_value,json=thresholdValue" json:"threshold_value,omitempty"` + // The amount of time that a time series must violate the + // threshold to be considered failing. Currently, only values + // that are a multiple of a minute--e.g. 60, 120, or 300 + // seconds--are supported. If an invalid value is given, an + // error will be returned. The `Duration.nanos` field is + // ignored. When choosing a duration, it is useful to keep in mind the + // frequency of the underlying time series data (which may also be + // affected by any alignments specified in the `aggregation` field); + // a good duration is long enough so that a single outlier does not + // generate spurious alerts, but short enough that unhealthy states + // are detected and alerted on quickly. + Duration *google_protobuf3.Duration `protobuf:"bytes,6,opt,name=duration" json:"duration,omitempty"` + // The number/percent of time series for which the comparison must hold + // in order for the condition to trigger. If unspecified, then the + // condition will trigger if the comparison is true for any of the + // time series that have been identified by `filter` and `aggregations`, + // or by the ratio, if `denominator_filter` and `denominator_aggregations` + // are specified. + Trigger *AlertPolicy_Condition_Trigger `protobuf:"bytes,7,opt,name=trigger" json:"trigger,omitempty"` +} + +func (m *AlertPolicy_Condition_MetricThreshold) Reset() { *m = AlertPolicy_Condition_MetricThreshold{} } +func (m *AlertPolicy_Condition_MetricThreshold) String() string { return proto.CompactTextString(m) } +func (*AlertPolicy_Condition_MetricThreshold) ProtoMessage() {} +func (*AlertPolicy_Condition_MetricThreshold) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{0, 1, 1} +} + +func (m *AlertPolicy_Condition_MetricThreshold) GetFilter() string { + if m != nil { + return m.Filter + } + return "" +} + +func (m *AlertPolicy_Condition_MetricThreshold) GetAggregations() []*Aggregation { + if m != nil { + return m.Aggregations + } + return nil +} + +func (m *AlertPolicy_Condition_MetricThreshold) GetDenominatorFilter() string { + if m != nil { + return m.DenominatorFilter + } + return "" +} + +func (m *AlertPolicy_Condition_MetricThreshold) GetDenominatorAggregations() []*Aggregation { + if m != nil { + return m.DenominatorAggregations + } + return nil +} + +func (m *AlertPolicy_Condition_MetricThreshold) GetComparison() ComparisonType { + if m != nil { + return m.Comparison + } + return ComparisonType_COMPARISON_UNSPECIFIED +} + +func (m *AlertPolicy_Condition_MetricThreshold) GetThresholdValue() float64 { + if m != nil { + return m.ThresholdValue + } + return 0 +} + +func (m *AlertPolicy_Condition_MetricThreshold) GetDuration() *google_protobuf3.Duration { + if m != nil { + return m.Duration + } + return nil +} + +func (m *AlertPolicy_Condition_MetricThreshold) GetTrigger() *AlertPolicy_Condition_Trigger { + if m != nil { + return m.Trigger + } + return nil +} + +// A condition type that checks that monitored resources +// are reporting data. The configuration defines a metric and +// a set of monitored resources. The predicate is considered in violation +// when a time series for the specified metric of a monitored +// resource does not include any data in the specified `duration`. +type AlertPolicy_Condition_MetricAbsence struct { + // A [filter](/monitoring/api/v3/filters) that + // identifies which time series should be compared with the threshold. + // + // The filter is similar to the one that is specified in the + // [`MetricService.ListTimeSeries` + // request](/monitoring/api/ref_v3/rest/v3/projects.timeSeries/list) (that + // call is useful to verify the time series that will be retrieved / + // processed) and must specify the metric type and optionally may contain + // restrictions on resource type, resource labels, and metric labels. + // This field may not exceed 2048 Unicode characters in length. + Filter string `protobuf:"bytes,1,opt,name=filter" json:"filter,omitempty"` + // Specifies the alignment of data points in individual time series as + // well as how to combine the retrieved time series together (such as + // when aggregating multiple streams on each resource to a single + // stream for each resource or when aggregating streams across all + // members of a group of resrouces). Multiple aggregations + // are applied in the order specified. + // + // This field is similar to the + // one in the [`MetricService.ListTimeSeries` request](/monitoring/api/ref_v3/rest/v3/projects.timeSeries/list). + // It is advisable to use the `ListTimeSeries` method when debugging this field. + Aggregations []*Aggregation `protobuf:"bytes,5,rep,name=aggregations" json:"aggregations,omitempty"` + // The amount of time that a time series must fail to report new + // data to be considered failing. Currently, only values that + // are a multiple of a minute--e.g. 60, 120, or 300 + // seconds--are supported. If an invalid value is given, an + // error will be returned. The `Duration.nanos` field is + // ignored. + Duration *google_protobuf3.Duration `protobuf:"bytes,2,opt,name=duration" json:"duration,omitempty"` + // The number/percent of time series for which the comparison must hold + // in order for the condition to trigger. If unspecified, then the + // condition will trigger if the comparison is true for any of the + // time series that have been identified by `filter` and `aggregations`. + Trigger *AlertPolicy_Condition_Trigger `protobuf:"bytes,3,opt,name=trigger" json:"trigger,omitempty"` +} + +func (m *AlertPolicy_Condition_MetricAbsence) Reset() { *m = AlertPolicy_Condition_MetricAbsence{} } +func (m *AlertPolicy_Condition_MetricAbsence) String() string { return proto.CompactTextString(m) } +func (*AlertPolicy_Condition_MetricAbsence) ProtoMessage() {} +func (*AlertPolicy_Condition_MetricAbsence) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{0, 1, 2} +} + +func (m *AlertPolicy_Condition_MetricAbsence) GetFilter() string { + if m != nil { + return m.Filter + } + return "" +} + +func (m *AlertPolicy_Condition_MetricAbsence) GetAggregations() []*Aggregation { + if m != nil { + return m.Aggregations + } + return nil +} + +func (m *AlertPolicy_Condition_MetricAbsence) GetDuration() *google_protobuf3.Duration { + if m != nil { + return m.Duration + } + return nil +} + +func (m *AlertPolicy_Condition_MetricAbsence) GetTrigger() *AlertPolicy_Condition_Trigger { + if m != nil { + return m.Trigger + } + return nil +} + +func init() { + proto.RegisterType((*AlertPolicy)(nil), "google.monitoring.v3.AlertPolicy") + proto.RegisterType((*AlertPolicy_Documentation)(nil), "google.monitoring.v3.AlertPolicy.Documentation") + proto.RegisterType((*AlertPolicy_Condition)(nil), "google.monitoring.v3.AlertPolicy.Condition") + proto.RegisterType((*AlertPolicy_Condition_Trigger)(nil), "google.monitoring.v3.AlertPolicy.Condition.Trigger") + proto.RegisterType((*AlertPolicy_Condition_MetricThreshold)(nil), "google.monitoring.v3.AlertPolicy.Condition.MetricThreshold") + proto.RegisterType((*AlertPolicy_Condition_MetricAbsence)(nil), "google.monitoring.v3.AlertPolicy.Condition.MetricAbsence") + proto.RegisterEnum("google.monitoring.v3.AlertPolicy_ConditionCombinerType", AlertPolicy_ConditionCombinerType_name, AlertPolicy_ConditionCombinerType_value) +} + +func init() { proto.RegisterFile("google/monitoring/v3/alert.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 941 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xeb, 0x6e, 0xe3, 0x44, + 0x14, 0xae, 0x93, 0xe6, 0x76, 0xd2, 0x36, 0xd9, 0xd9, 0xee, 0xae, 0x31, 0x68, 0x95, 0xae, 0x90, + 0x88, 0x40, 0x38, 0x22, 0x01, 0x71, 0x59, 0x81, 0x94, 0x5b, 0x37, 0x11, 0x24, 0xad, 0xa6, 0x69, + 0x91, 0x50, 0x25, 0xcb, 0x71, 0xa6, 0xae, 0x85, 0x3d, 0x63, 0x4d, 0xec, 0xa2, 0xbc, 0x0e, 0x3f, + 0x79, 0x14, 0x1e, 0x81, 0x7f, 0xbc, 0x02, 0xe2, 0x01, 0x90, 0xc7, 0x63, 0xc7, 0xe9, 0xa6, 0xbb, + 0x64, 0xf7, 0x5f, 0xce, 0x9c, 0xef, 0x7c, 0xe7, 0xf6, 0xcd, 0x38, 0xd0, 0xb0, 0x19, 0xb3, 0x5d, + 0xd2, 0xf2, 0x18, 0x75, 0x02, 0xc6, 0x1d, 0x6a, 0xb7, 0xee, 0x3a, 0x2d, 0xd3, 0x25, 0x3c, 0xd0, + 0x7d, 0xce, 0x02, 0x86, 0x8e, 0x63, 0x84, 0xbe, 0x46, 0xe8, 0x77, 0x1d, 0xed, 0x23, 0x19, 0x67, + 0xfa, 0x4e, 0xcb, 0xa4, 0x94, 0x05, 0x66, 0xe0, 0x30, 0xba, 0x8c, 0x63, 0xb4, 0x93, 0xad, 0xac, + 0x16, 0xf3, 0x3c, 0x46, 0x25, 0xe4, 0xd3, 0xad, 0x10, 0x2f, 0x8c, 0x89, 0x0c, 0x4e, 0x2c, 0xc6, + 0x17, 0x12, 0xfb, 0x5c, 0x62, 0x85, 0x35, 0x0f, 0x6f, 0x5a, 0x8b, 0x90, 0x0b, 0xd8, 0x43, 0xfe, + 0xdf, 0xb8, 0xe9, 0xfb, 0x84, 0xcb, 0x72, 0x5e, 0xfc, 0x5d, 0x83, 0x6a, 0x37, 0x6a, 0xe9, 0x9c, + 0xb9, 0x8e, 0xb5, 0x42, 0x08, 0xf6, 0xa9, 0xe9, 0x11, 0x55, 0x69, 0x28, 0xcd, 0x0a, 0x16, 0xbf, + 0xd1, 0x09, 0x1c, 0x2c, 0x9c, 0xa5, 0xef, 0x9a, 0x2b, 0x43, 0xf8, 0x72, 0xc2, 0x57, 0x95, 0x67, + 0xd3, 0x08, 0x72, 0x09, 0x87, 0x0b, 0x66, 0x85, 0x1e, 0xa1, 0x71, 0x91, 0xea, 0x61, 0x43, 0x69, + 0x56, 0xdb, 0x2d, 0x7d, 0xdb, 0x84, 0xf4, 0x4c, 0x42, 0x7d, 0x90, 0x0d, 0xc3, 0x9b, 0x2c, 0x08, + 0x43, 0x35, 0x5c, 0x12, 0x6e, 0xb8, 0xe6, 0x9c, 0xb8, 0x4b, 0xb5, 0xde, 0xc8, 0x37, 0xab, 0xed, + 0x2f, 0xde, 0x4e, 0x7a, 0xb9, 0x24, 0xfc, 0x27, 0x11, 0x33, 0xa4, 0x01, 0x5f, 0x61, 0x08, 0xd3, + 0x03, 0xf4, 0x23, 0x80, 0xc5, 0xe8, 0xc2, 0x11, 0x4b, 0x51, 0x0f, 0x04, 0xe5, 0x67, 0x6f, 0xa7, + 0xec, 0x27, 0x31, 0x38, 0x13, 0x8e, 0x2e, 0xa0, 0x6c, 0x31, 0x6f, 0xee, 0x50, 0xc2, 0xd5, 0x62, + 0x43, 0x69, 0x1e, 0xb5, 0xbf, 0xde, 0x81, 0xaa, 0x2f, 0x43, 0x67, 0x2b, 0x9f, 0xe0, 0x94, 0x08, + 0x7d, 0x09, 0x25, 0x42, 0xcd, 0xb9, 0x4b, 0x16, 0xea, 0x23, 0x31, 0x46, 0x2d, 0xe1, 0x4c, 0xb6, + 0xa8, 0xf7, 0x18, 0x73, 0xaf, 0x4c, 0x37, 0x24, 0x38, 0x81, 0xa2, 0x0e, 0x3c, 0xa1, 0x2c, 0x70, + 0x6e, 0x1c, 0x2b, 0x96, 0x89, 0x75, 0x6b, 0x52, 0x1a, 0x4d, 0xed, 0xa8, 0x91, 0x6f, 0x56, 0xf0, + 0x71, 0xd6, 0xd9, 0x97, 0x3e, 0x34, 0x81, 0x9a, 0xc5, 0x49, 0x56, 0x57, 0x2a, 0x88, 0x94, 0x1f, + 0x6f, 0x6f, 0x63, 0x22, 0x45, 0x88, 0x05, 0x16, 0x1f, 0x25, 0xc1, 0xb1, 0x1d, 0xd1, 0xdd, 0x93, + 0xa9, 0x5a, 0xdd, 0x85, 0xce, 0xdb, 0xb0, 0xb5, 0x53, 0x38, 0xdc, 0x90, 0x07, 0x52, 0xa1, 0x64, + 0x31, 0x1a, 0x10, 0x1a, 0x48, 0x81, 0x26, 0x26, 0xfa, 0x10, 0x2a, 0x9e, 0xe3, 0x11, 0x23, 0x58, + 0xf9, 0x89, 0x40, 0xcb, 0xd1, 0x41, 0x34, 0x5a, 0xed, 0xaf, 0x32, 0x54, 0xd2, 0xa1, 0xa7, 0x12, + 0x3f, 0x78, 0x83, 0xc4, 0x8b, 0xaf, 0x4b, 0x9c, 0xc2, 0xe3, 0x74, 0xf1, 0x46, 0x70, 0xcb, 0xc9, + 0xf2, 0x96, 0xb9, 0x0b, 0x51, 0x47, 0xb5, 0xfd, 0x72, 0x87, 0xad, 0xeb, 0x13, 0x12, 0x70, 0xc7, + 0x9a, 0x25, 0x14, 0xa3, 0x3d, 0x8c, 0x52, 0xe6, 0xf4, 0x14, 0xdd, 0x40, 0x7d, 0x9d, 0xcf, 0x9c, + 0x2f, 0xa3, 0xa6, 0x73, 0x22, 0xd9, 0xb7, 0xbb, 0x27, 0xeb, 0x46, 0xf1, 0x16, 0x19, 0xed, 0xe1, + 0x5a, 0x4a, 0x2a, 0xce, 0x02, 0x6d, 0x08, 0xa5, 0x19, 0x77, 0x6c, 0x9b, 0x70, 0xf4, 0x14, 0x0a, + 0x16, 0x0b, 0xe5, 0x70, 0x0b, 0xa3, 0x3d, 0x1c, 0x9b, 0x48, 0x83, 0x92, 0x4f, 0xb8, 0x95, 0x54, + 0xa0, 0x8c, 0xf6, 0x70, 0x72, 0xd0, 0x2b, 0xc2, 0x7e, 0x34, 0x73, 0xed, 0x9f, 0x3c, 0xd4, 0xee, + 0x35, 0x86, 0x9e, 0x42, 0xf1, 0xc6, 0x71, 0x03, 0xc2, 0xe5, 0x46, 0xa4, 0x85, 0x86, 0x70, 0x60, + 0xda, 0x36, 0x27, 0x76, 0xfc, 0x32, 0xaa, 0x65, 0x71, 0x09, 0x4f, 0x1e, 0x68, 0x6b, 0x8d, 0xc4, + 0x1b, 0x61, 0xe8, 0x73, 0x40, 0x0b, 0x42, 0x99, 0xe7, 0x50, 0x33, 0x60, 0xdc, 0x90, 0xa9, 0x2a, + 0x22, 0xd5, 0xa3, 0x8c, 0xe7, 0x34, 0xce, 0x7a, 0x0d, 0x6a, 0x16, 0xbe, 0x51, 0x01, 0xfc, 0xdf, + 0x0a, 0x9e, 0x65, 0x28, 0xba, 0xd9, 0x62, 0x06, 0xd1, 0xb3, 0xe2, 0xf9, 0x26, 0x77, 0x96, 0x8c, + 0xaa, 0xfb, 0xe2, 0x2d, 0x78, 0x40, 0xf5, 0xfd, 0x14, 0x27, 0x2e, 0x7e, 0x26, 0x0e, 0x7d, 0x02, + 0xb5, 0x54, 0x5a, 0xc6, 0x5d, 0x74, 0xc1, 0xd5, 0x42, 0x34, 0x71, 0x7c, 0x94, 0x1e, 0x8b, 0x6b, + 0x8f, 0xbe, 0x82, 0x72, 0xf2, 0xd2, 0x0b, 0xb1, 0x56, 0xdb, 0x1f, 0xbc, 0xf6, 0x48, 0x0c, 0x24, + 0x00, 0xa7, 0x50, 0x34, 0x81, 0x52, 0x10, 0x2f, 0x5b, 0x2d, 0x89, 0xa8, 0xce, 0x2e, 0x5a, 0x92, + 0x3a, 0xc1, 0x09, 0x87, 0xf6, 0xaf, 0x02, 0x87, 0x1b, 0x02, 0xcb, 0xac, 0x5c, 0x79, 0xe3, 0xca, + 0x0b, 0xef, 0xb6, 0xf2, 0x6c, 0xdb, 0xb9, 0x77, 0x6a, 0x3b, 0xff, 0xfe, 0x6d, 0xf7, 0xaa, 0x50, + 0x49, 0x6f, 0x91, 0xf6, 0x3d, 0xd4, 0xee, 0x7d, 0x6e, 0x50, 0x1d, 0xf2, 0xbf, 0x92, 0x95, 0x9c, + 0x40, 0xf4, 0x13, 0x1d, 0x43, 0x21, 0xde, 0x66, 0x7c, 0x11, 0x62, 0xe3, 0xbb, 0xdc, 0x37, 0xca, + 0x0b, 0x13, 0x9e, 0x6c, 0xfd, 0x1e, 0xa0, 0x67, 0xf0, 0xb8, 0x7f, 0x36, 0xe9, 0x8d, 0xa7, 0x43, + 0xe3, 0x72, 0x7a, 0x71, 0x3e, 0xec, 0x8f, 0x4f, 0xc7, 0xc3, 0x41, 0x7d, 0x0f, 0x95, 0x20, 0xdf, + 0x9d, 0x0e, 0xea, 0x0a, 0x2a, 0x42, 0xee, 0x0c, 0xd7, 0x73, 0xe8, 0x39, 0x68, 0xdd, 0xe9, 0xc0, + 0xf8, 0x79, 0x3c, 0x1b, 0x19, 0x93, 0xee, 0xac, 0x3f, 0x1a, 0x4f, 0x5f, 0x19, 0x78, 0x78, 0x71, + 0x76, 0x89, 0xfb, 0xc3, 0x7a, 0xbe, 0xf7, 0xbb, 0x02, 0xaa, 0xc5, 0xbc, 0xad, 0x2d, 0xf7, 0x20, + 0xee, 0x39, 0x1a, 0xde, 0xb9, 0xf2, 0xcb, 0x0f, 0x12, 0x63, 0x33, 0xd7, 0xa4, 0xb6, 0xce, 0xb8, + 0xdd, 0xb2, 0x09, 0x15, 0xa3, 0x6d, 0xc5, 0x2e, 0xd3, 0x77, 0x96, 0x9b, 0xff, 0x4c, 0x5e, 0xae, + 0xad, 0x3f, 0x72, 0xda, 0xab, 0x98, 0xa0, 0xef, 0xb2, 0x70, 0xa1, 0x4f, 0xd6, 0xa9, 0xae, 0x3a, + 0x7f, 0x26, 0xce, 0x6b, 0xe1, 0xbc, 0x5e, 0x3b, 0xaf, 0xaf, 0x3a, 0xf3, 0xa2, 0x48, 0xd2, 0xf9, + 0x2f, 0x00, 0x00, 0xff, 0xff, 0x66, 0xb5, 0x16, 0x64, 0x76, 0x09, 0x00, 0x00, +} diff --git a/google.golang.org/genproto/googleapis/monitoring/v3/alert_service.pb.go b/google.golang.org/genproto/googleapis/monitoring/v3/alert_service.pb.go new file mode 100644 index 00000000..0b51478a --- /dev/null +++ b/google.golang.org/genproto/googleapis/monitoring/v3/alert_service.pb.go @@ -0,0 +1,527 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/monitoring/v3/alert_service.proto + +package monitoring + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_protobuf5 "github.com/golang/protobuf/ptypes/empty" +import google_protobuf6 "google.golang.org/genproto/protobuf/field_mask" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// The protocol for the `CreateAlertPolicy` request. +type CreateAlertPolicyRequest struct { + // The project in which to create the alerting policy. The format is + // `projects/[PROJECT_ID]`. + // + // Note that this field names the parent container in which the alerting + // policy will be written, not the name of the created policy. The alerting + // policy that is returned will have a name that contains a normalized + // representation of this name as a prefix but adds a suffix of the form + // `/alertPolicies/[POLICY_ID]`, identifying the policy in the container. + Name string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"` + // The requested alerting policy. You should omit the `name` field in this + // policy. The name will be returned in the new policy, including + // a new [ALERT_POLICY_ID] value. + AlertPolicy *AlertPolicy `protobuf:"bytes,2,opt,name=alert_policy,json=alertPolicy" json:"alert_policy,omitempty"` +} + +func (m *CreateAlertPolicyRequest) Reset() { *m = CreateAlertPolicyRequest{} } +func (m *CreateAlertPolicyRequest) String() string { return proto.CompactTextString(m) } +func (*CreateAlertPolicyRequest) ProtoMessage() {} +func (*CreateAlertPolicyRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } + +func (m *CreateAlertPolicyRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *CreateAlertPolicyRequest) GetAlertPolicy() *AlertPolicy { + if m != nil { + return m.AlertPolicy + } + return nil +} + +// The protocol for the `GetAlertPolicy` request. +type GetAlertPolicyRequest struct { + // The alerting policy to retrieve. The format is + // + // projects/[PROJECT_ID]/alertPolicies/[ALERT_POLICY_ID] + Name string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"` +} + +func (m *GetAlertPolicyRequest) Reset() { *m = GetAlertPolicyRequest{} } +func (m *GetAlertPolicyRequest) String() string { return proto.CompactTextString(m) } +func (*GetAlertPolicyRequest) ProtoMessage() {} +func (*GetAlertPolicyRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } + +func (m *GetAlertPolicyRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// The protocol for the `ListAlertPolicies` request. +type ListAlertPoliciesRequest struct { + // The project whose alert policies are to be listed. The format is + // + // projects/[PROJECT_ID] + // + // Note that this field names the parent container in which the alerting + // policies to be listed are stored. To retrieve a single alerting policy + // by name, use the + // [GetAlertPolicy][google.monitoring.v3.AlertPolicyService.GetAlertPolicy] + // operation, instead. + Name string `protobuf:"bytes,4,opt,name=name" json:"name,omitempty"` + // If provided, this field specifies the criteria that must be met by + // alert policies to be included in the response. + // + // For more details, see [sorting and + // filtering](/monitoring/api/v3/sorting-and-filtering). + Filter string `protobuf:"bytes,5,opt,name=filter" json:"filter,omitempty"` + // A comma-separated list of fields by which to sort the result. Supports + // the same set of field references as the `filter` field. Entries can be + // prefixed with a minus sign to sort by the field in descending order. + // + // For more details, see [sorting and + // filtering](/monitoring/api/v3/sorting-and-filtering). + OrderBy string `protobuf:"bytes,6,opt,name=order_by,json=orderBy" json:"order_by,omitempty"` + // The maximum number of results to return in a single response. + PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize" json:"page_size,omitempty"` + // If this field is not empty then it must contain the `nextPageToken` value + // returned by a previous call to this method. Using this field causes the + // method to return more results from the previous method call. + PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken" json:"page_token,omitempty"` +} + +func (m *ListAlertPoliciesRequest) Reset() { *m = ListAlertPoliciesRequest{} } +func (m *ListAlertPoliciesRequest) String() string { return proto.CompactTextString(m) } +func (*ListAlertPoliciesRequest) ProtoMessage() {} +func (*ListAlertPoliciesRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} } + +func (m *ListAlertPoliciesRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *ListAlertPoliciesRequest) GetFilter() string { + if m != nil { + return m.Filter + } + return "" +} + +func (m *ListAlertPoliciesRequest) GetOrderBy() string { + if m != nil { + return m.OrderBy + } + return "" +} + +func (m *ListAlertPoliciesRequest) GetPageSize() int32 { + if m != nil { + return m.PageSize + } + return 0 +} + +func (m *ListAlertPoliciesRequest) GetPageToken() string { + if m != nil { + return m.PageToken + } + return "" +} + +// The protocol for the `ListAlertPolicies` response. +type ListAlertPoliciesResponse struct { + // The returned alert policies. + AlertPolicies []*AlertPolicy `protobuf:"bytes,3,rep,name=alert_policies,json=alertPolicies" json:"alert_policies,omitempty"` + // If there might be more results than were returned, then this field is set + // to a non-empty value. To see the additional results, + // use that value as `pageToken` in the next call to this method. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken" json:"next_page_token,omitempty"` +} + +func (m *ListAlertPoliciesResponse) Reset() { *m = ListAlertPoliciesResponse{} } +func (m *ListAlertPoliciesResponse) String() string { return proto.CompactTextString(m) } +func (*ListAlertPoliciesResponse) ProtoMessage() {} +func (*ListAlertPoliciesResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } + +func (m *ListAlertPoliciesResponse) GetAlertPolicies() []*AlertPolicy { + if m != nil { + return m.AlertPolicies + } + return nil +} + +func (m *ListAlertPoliciesResponse) GetNextPageToken() string { + if m != nil { + return m.NextPageToken + } + return "" +} + +// The protocol for the `UpdateAlertPolicy` request. +type UpdateAlertPolicyRequest struct { + // Optional. A list of alerting policy field names. If this field is not + // empty, each listed field in the existing alerting policy is set to the + // value of the corresponding field in the supplied policy (`alert_policy`), + // or to the field's default value if the field is not in the supplied + // alerting policy. Fields not listed retain their previous value. + // + // Examples of valid field masks include `display_name`, `documentation`, + // `documentation.content`, `documentation.mime_type`, `user_labels`, + // `user_label.nameofkey`, `enabled`, `conditions`, `combiner`, etc. + // + // If this field is empty, then the supplied alerting policy replaces the + // existing policy. It is the same as deleting the existing policy and + // adding the supplied policy, except for the following: + // + // + The new policy will have the same `[ALERT_POLICY_ID]` as the former + // policy. This gives you continuity with the former policy in your + // notifications and incidents. + // + Conditions in the new policy will keep their former `[CONDITION_ID]` if + // the supplied condition includes the `name` field with that + // `[CONDITION_ID]`. If the supplied condition omits the `name` field, + // then a new `[CONDITION_ID]` is created. + UpdateMask *google_protobuf6.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` + // Required. The updated alerting policy or the updated values for the + // fields listed in `update_mask`. + // If `update_mask` is not empty, any fields in this policy that are + // not in `update_mask` are ignored. + AlertPolicy *AlertPolicy `protobuf:"bytes,3,opt,name=alert_policy,json=alertPolicy" json:"alert_policy,omitempty"` +} + +func (m *UpdateAlertPolicyRequest) Reset() { *m = UpdateAlertPolicyRequest{} } +func (m *UpdateAlertPolicyRequest) String() string { return proto.CompactTextString(m) } +func (*UpdateAlertPolicyRequest) ProtoMessage() {} +func (*UpdateAlertPolicyRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} } + +func (m *UpdateAlertPolicyRequest) GetUpdateMask() *google_protobuf6.FieldMask { + if m != nil { + return m.UpdateMask + } + return nil +} + +func (m *UpdateAlertPolicyRequest) GetAlertPolicy() *AlertPolicy { + if m != nil { + return m.AlertPolicy + } + return nil +} + +// The protocol for the `DeleteAlertPolicy` request. +type DeleteAlertPolicyRequest struct { + // The alerting policy to delete. The format is: + // + // projects/[PROJECT_ID]/alertPolicies/[ALERT_POLICY_ID] + // + // For more information, see [AlertPolicy][google.monitoring.v3.AlertPolicy]. + Name string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"` +} + +func (m *DeleteAlertPolicyRequest) Reset() { *m = DeleteAlertPolicyRequest{} } +func (m *DeleteAlertPolicyRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteAlertPolicyRequest) ProtoMessage() {} +func (*DeleteAlertPolicyRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} } + +func (m *DeleteAlertPolicyRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func init() { + proto.RegisterType((*CreateAlertPolicyRequest)(nil), "google.monitoring.v3.CreateAlertPolicyRequest") + proto.RegisterType((*GetAlertPolicyRequest)(nil), "google.monitoring.v3.GetAlertPolicyRequest") + proto.RegisterType((*ListAlertPoliciesRequest)(nil), "google.monitoring.v3.ListAlertPoliciesRequest") + proto.RegisterType((*ListAlertPoliciesResponse)(nil), "google.monitoring.v3.ListAlertPoliciesResponse") + proto.RegisterType((*UpdateAlertPolicyRequest)(nil), "google.monitoring.v3.UpdateAlertPolicyRequest") + proto.RegisterType((*DeleteAlertPolicyRequest)(nil), "google.monitoring.v3.DeleteAlertPolicyRequest") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for AlertPolicyService service + +type AlertPolicyServiceClient interface { + // Lists the existing alerting policies for the project. + ListAlertPolicies(ctx context.Context, in *ListAlertPoliciesRequest, opts ...grpc.CallOption) (*ListAlertPoliciesResponse, error) + // Gets a single alerting policy. + GetAlertPolicy(ctx context.Context, in *GetAlertPolicyRequest, opts ...grpc.CallOption) (*AlertPolicy, error) + // Creates a new alerting policy. + CreateAlertPolicy(ctx context.Context, in *CreateAlertPolicyRequest, opts ...grpc.CallOption) (*AlertPolicy, error) + // Deletes an alerting policy. + DeleteAlertPolicy(ctx context.Context, in *DeleteAlertPolicyRequest, opts ...grpc.CallOption) (*google_protobuf5.Empty, error) + // Updates an alerting policy. You can either replace the entire policy with + // a new one or replace only certain fields in the current alerting policy by + // specifying the fields to be updated via `updateMask`. Returns the + // updated alerting policy. + UpdateAlertPolicy(ctx context.Context, in *UpdateAlertPolicyRequest, opts ...grpc.CallOption) (*AlertPolicy, error) +} + +type alertPolicyServiceClient struct { + cc *grpc.ClientConn +} + +func NewAlertPolicyServiceClient(cc *grpc.ClientConn) AlertPolicyServiceClient { + return &alertPolicyServiceClient{cc} +} + +func (c *alertPolicyServiceClient) ListAlertPolicies(ctx context.Context, in *ListAlertPoliciesRequest, opts ...grpc.CallOption) (*ListAlertPoliciesResponse, error) { + out := new(ListAlertPoliciesResponse) + err := grpc.Invoke(ctx, "/google.monitoring.v3.AlertPolicyService/ListAlertPolicies", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *alertPolicyServiceClient) GetAlertPolicy(ctx context.Context, in *GetAlertPolicyRequest, opts ...grpc.CallOption) (*AlertPolicy, error) { + out := new(AlertPolicy) + err := grpc.Invoke(ctx, "/google.monitoring.v3.AlertPolicyService/GetAlertPolicy", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *alertPolicyServiceClient) CreateAlertPolicy(ctx context.Context, in *CreateAlertPolicyRequest, opts ...grpc.CallOption) (*AlertPolicy, error) { + out := new(AlertPolicy) + err := grpc.Invoke(ctx, "/google.monitoring.v3.AlertPolicyService/CreateAlertPolicy", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *alertPolicyServiceClient) DeleteAlertPolicy(ctx context.Context, in *DeleteAlertPolicyRequest, opts ...grpc.CallOption) (*google_protobuf5.Empty, error) { + out := new(google_protobuf5.Empty) + err := grpc.Invoke(ctx, "/google.monitoring.v3.AlertPolicyService/DeleteAlertPolicy", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *alertPolicyServiceClient) UpdateAlertPolicy(ctx context.Context, in *UpdateAlertPolicyRequest, opts ...grpc.CallOption) (*AlertPolicy, error) { + out := new(AlertPolicy) + err := grpc.Invoke(ctx, "/google.monitoring.v3.AlertPolicyService/UpdateAlertPolicy", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for AlertPolicyService service + +type AlertPolicyServiceServer interface { + // Lists the existing alerting policies for the project. + ListAlertPolicies(context.Context, *ListAlertPoliciesRequest) (*ListAlertPoliciesResponse, error) + // Gets a single alerting policy. + GetAlertPolicy(context.Context, *GetAlertPolicyRequest) (*AlertPolicy, error) + // Creates a new alerting policy. + CreateAlertPolicy(context.Context, *CreateAlertPolicyRequest) (*AlertPolicy, error) + // Deletes an alerting policy. + DeleteAlertPolicy(context.Context, *DeleteAlertPolicyRequest) (*google_protobuf5.Empty, error) + // Updates an alerting policy. You can either replace the entire policy with + // a new one or replace only certain fields in the current alerting policy by + // specifying the fields to be updated via `updateMask`. Returns the + // updated alerting policy. + UpdateAlertPolicy(context.Context, *UpdateAlertPolicyRequest) (*AlertPolicy, error) +} + +func RegisterAlertPolicyServiceServer(s *grpc.Server, srv AlertPolicyServiceServer) { + s.RegisterService(&_AlertPolicyService_serviceDesc, srv) +} + +func _AlertPolicyService_ListAlertPolicies_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListAlertPoliciesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AlertPolicyServiceServer).ListAlertPolicies(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.AlertPolicyService/ListAlertPolicies", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AlertPolicyServiceServer).ListAlertPolicies(ctx, req.(*ListAlertPoliciesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AlertPolicyService_GetAlertPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetAlertPolicyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AlertPolicyServiceServer).GetAlertPolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.AlertPolicyService/GetAlertPolicy", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AlertPolicyServiceServer).GetAlertPolicy(ctx, req.(*GetAlertPolicyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AlertPolicyService_CreateAlertPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateAlertPolicyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AlertPolicyServiceServer).CreateAlertPolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.AlertPolicyService/CreateAlertPolicy", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AlertPolicyServiceServer).CreateAlertPolicy(ctx, req.(*CreateAlertPolicyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AlertPolicyService_DeleteAlertPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteAlertPolicyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AlertPolicyServiceServer).DeleteAlertPolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.AlertPolicyService/DeleteAlertPolicy", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AlertPolicyServiceServer).DeleteAlertPolicy(ctx, req.(*DeleteAlertPolicyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AlertPolicyService_UpdateAlertPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateAlertPolicyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AlertPolicyServiceServer).UpdateAlertPolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.AlertPolicyService/UpdateAlertPolicy", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AlertPolicyServiceServer).UpdateAlertPolicy(ctx, req.(*UpdateAlertPolicyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _AlertPolicyService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "google.monitoring.v3.AlertPolicyService", + HandlerType: (*AlertPolicyServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ListAlertPolicies", + Handler: _AlertPolicyService_ListAlertPolicies_Handler, + }, + { + MethodName: "GetAlertPolicy", + Handler: _AlertPolicyService_GetAlertPolicy_Handler, + }, + { + MethodName: "CreateAlertPolicy", + Handler: _AlertPolicyService_CreateAlertPolicy_Handler, + }, + { + MethodName: "DeleteAlertPolicy", + Handler: _AlertPolicyService_DeleteAlertPolicy_Handler, + }, + { + MethodName: "UpdateAlertPolicy", + Handler: _AlertPolicyService_UpdateAlertPolicy_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "google/monitoring/v3/alert_service.proto", +} + +func init() { proto.RegisterFile("google/monitoring/v3/alert_service.proto", fileDescriptor1) } + +var fileDescriptor1 = []byte{ + // 656 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0x41, 0x6f, 0xd3, 0x4c, + 0x10, 0x95, 0x93, 0x36, 0x5f, 0xbb, 0xfd, 0x5a, 0x94, 0x15, 0x54, 0xae, 0x0b, 0x52, 0x30, 0x2a, + 0x54, 0xad, 0xb0, 0xa5, 0xf8, 0x04, 0x15, 0x48, 0xa4, 0x85, 0xf6, 0x40, 0xa5, 0x28, 0x85, 0x1e, + 0x50, 0xa4, 0x68, 0x93, 0x4c, 0xac, 0x25, 0x8e, 0xd7, 0x78, 0x37, 0x11, 0x29, 0xea, 0x85, 0x23, + 0x12, 0xe2, 0xc0, 0x99, 0x03, 0x47, 0x38, 0x20, 0x7e, 0x07, 0x57, 0xfe, 0x02, 0x3f, 0x04, 0x79, + 0xed, 0x34, 0x76, 0x6d, 0xab, 0x16, 0xb7, 0xcc, 0xce, 0xdb, 0x99, 0xb7, 0x6f, 0xde, 0x38, 0x68, + 0xdb, 0x66, 0xcc, 0x76, 0xc0, 0x1c, 0x31, 0x97, 0x0a, 0xe6, 0x53, 0xd7, 0x36, 0x27, 0x96, 0x49, + 0x1c, 0xf0, 0x45, 0x87, 0x83, 0x3f, 0xa1, 0x3d, 0x30, 0x3c, 0x9f, 0x09, 0x86, 0xaf, 0x87, 0x48, + 0x63, 0x8e, 0x34, 0x26, 0x96, 0x76, 0x33, 0xba, 0x4f, 0x3c, 0x6a, 0x12, 0xd7, 0x65, 0x82, 0x08, + 0xca, 0x5c, 0x1e, 0xde, 0xd1, 0x6a, 0xf9, 0xd5, 0x23, 0xc4, 0x66, 0x84, 0x90, 0x51, 0x77, 0x3c, + 0x30, 0x61, 0xe4, 0x89, 0xe9, 0xa5, 0xeb, 0x17, 0xc9, 0x01, 0x05, 0xa7, 0xdf, 0x19, 0x11, 0x3e, + 0x0c, 0x11, 0xba, 0x40, 0xea, 0xbe, 0x0f, 0x44, 0xc0, 0x93, 0xa0, 0x66, 0x93, 0x39, 0xb4, 0x37, + 0x6d, 0xc1, 0x9b, 0x31, 0x70, 0x81, 0x31, 0x5a, 0x70, 0xc9, 0x08, 0xd4, 0x72, 0x4d, 0xd9, 0x5e, + 0x6e, 0xc9, 0xdf, 0xf8, 0x00, 0xfd, 0x1f, 0xbe, 0xcd, 0x93, 0x50, 0xb5, 0x54, 0x53, 0xb6, 0x57, + 0xea, 0xb7, 0x8d, 0xac, 0xb7, 0x19, 0xf1, 0x9a, 0x2b, 0x64, 0x1e, 0xe8, 0xbb, 0xe8, 0xc6, 0x21, + 0x88, 0x62, 0x2d, 0xf5, 0x2f, 0x0a, 0x52, 0x9f, 0x53, 0x1e, 0x83, 0x53, 0xe0, 0x97, 0x2f, 0x2c, + 0xc4, 0x38, 0xae, 0xa3, 0xca, 0x80, 0x3a, 0x02, 0x7c, 0x75, 0x51, 0x9e, 0x46, 0x11, 0xde, 0x40, + 0x4b, 0xcc, 0xef, 0x83, 0xdf, 0xe9, 0x4e, 0xd5, 0x8a, 0xcc, 0xfc, 0x27, 0xe3, 0xc6, 0x14, 0x6f, + 0xa2, 0x65, 0x8f, 0xd8, 0xd0, 0xe1, 0xf4, 0x0c, 0xe4, 0x9b, 0x16, 0x5b, 0x4b, 0xc1, 0xc1, 0x09, + 0x3d, 0x03, 0x7c, 0x0b, 0x21, 0x99, 0x14, 0x6c, 0x08, 0x6e, 0x44, 0x4d, 0xc2, 0x5f, 0x04, 0x07, + 0xfa, 0x47, 0x05, 0x6d, 0x64, 0xf0, 0xe3, 0x1e, 0x73, 0x39, 0xe0, 0x23, 0xb4, 0x16, 0x13, 0x8c, + 0x02, 0x57, 0xcb, 0xb5, 0x72, 0x31, 0xc9, 0x56, 0x49, 0xbc, 0x22, 0xbe, 0x8b, 0xae, 0xb9, 0xf0, + 0x56, 0x74, 0x62, 0x5c, 0x4a, 0x92, 0xcb, 0x6a, 0x70, 0xdc, 0xbc, 0xe0, 0x13, 0xe8, 0xf5, 0xd2, + 0xeb, 0x67, 0xcf, 0x74, 0x0f, 0xad, 0x8c, 0x65, 0x4e, 0x9a, 0x20, 0x1a, 0x9f, 0x36, 0xe3, 0x32, + 0xf3, 0x89, 0xf1, 0x2c, 0xf0, 0xc9, 0x31, 0xe1, 0xc3, 0x16, 0x0a, 0xe1, 0xc1, 0xef, 0xd4, 0xf0, + 0xcb, 0xff, 0x34, 0x7c, 0x03, 0xa9, 0x07, 0xe0, 0x40, 0x51, 0xcb, 0xd5, 0x7f, 0x54, 0x10, 0x8e, + 0x41, 0x4f, 0xc2, 0xa5, 0xc2, 0x5f, 0x15, 0x54, 0x4d, 0xc9, 0x8e, 0x8d, 0x6c, 0x32, 0x79, 0xfe, + 0xd1, 0xcc, 0xc2, 0xf8, 0x70, 0x9e, 0xfa, 0xee, 0xfb, 0xdf, 0x7f, 0x3e, 0x97, 0xb6, 0xf0, 0x9d, + 0x60, 0x11, 0xdf, 0x05, 0x04, 0x1f, 0x79, 0x3e, 0x7b, 0x0d, 0x3d, 0xc1, 0xcd, 0x9d, 0x73, 0x33, + 0x39, 0xb2, 0x4f, 0x0a, 0x5a, 0x4b, 0x1a, 0x1d, 0xef, 0x66, 0x37, 0xcc, 0x5c, 0x07, 0xed, 0x6a, + 0x69, 0xf5, 0xfb, 0x92, 0xcf, 0x3d, 0xbc, 0x95, 0xc5, 0x27, 0x49, 0xc7, 0xdc, 0x39, 0x97, 0xaa, + 0xa5, 0x16, 0x3e, 0x4f, 0xb5, 0xbc, 0x2f, 0x43, 0x11, 0x5e, 0x0f, 0x24, 0x2f, 0x4b, 0x2f, 0xa2, + 0xd3, 0xc3, 0x84, 0xad, 0xf0, 0x07, 0x05, 0x55, 0x53, 0x0e, 0xc9, 0xe3, 0x98, 0x67, 0x25, 0x6d, + 0x3d, 0x65, 0xea, 0xa7, 0xc1, 0x97, 0x71, 0x26, 0xd8, 0x4e, 0x41, 0xc1, 0x7e, 0x2a, 0xa8, 0x9a, + 0xda, 0xa6, 0x3c, 0x32, 0x79, 0x6b, 0x57, 0x44, 0xb0, 0x23, 0xc9, 0xab, 0x51, 0xaf, 0x4b, 0x5e, + 0x71, 0x41, 0x8c, 0xab, 0x48, 0x26, 0xf5, 0x6b, 0x7c, 0x53, 0x90, 0xda, 0x63, 0xa3, 0xcc, 0x96, + 0x8d, 0xaa, 0xec, 0x19, 0x2d, 0x51, 0x33, 0x90, 0xa6, 0xa9, 0xbc, 0x7a, 0x1c, 0x41, 0x6d, 0xe6, + 0x10, 0xd7, 0x36, 0x98, 0x6f, 0x9b, 0x36, 0xb8, 0x52, 0x38, 0x33, 0x4c, 0x11, 0x8f, 0xf2, 0xe4, + 0xbf, 0xd0, 0xde, 0x3c, 0xfa, 0x5e, 0xd2, 0x0e, 0xc3, 0x02, 0xfb, 0x0e, 0x1b, 0xf7, 0x8d, 0xe3, + 0x79, 0xc7, 0x53, 0xeb, 0xd7, 0x2c, 0xd9, 0x96, 0xc9, 0xf6, 0x3c, 0xd9, 0x3e, 0xb5, 0xba, 0x15, + 0xd9, 0xc4, 0xfa, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x6f, 0x1f, 0xe6, 0xf0, 0x47, 0x07, 0x00, 0x00, +} diff --git a/google.golang.org/genproto/googleapis/monitoring/v3/common.pb.go b/google.golang.org/genproto/googleapis/monitoring/v3/common.pb.go index 4d967f52..60239967 100644 --- a/google.golang.org/genproto/googleapis/monitoring/v3/common.pb.go +++ b/google.golang.org/genproto/googleapis/monitoring/v3/common.pb.go @@ -1,61 +1,12 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // source: google/monitoring/v3/common.proto -/* -Package monitoring is a generated protocol buffer package. - -It is generated from these files: - google/monitoring/v3/common.proto - google/monitoring/v3/group.proto - google/monitoring/v3/group_service.proto - google/monitoring/v3/metric.proto - google/monitoring/v3/metric_service.proto - google/monitoring/v3/uptime.proto - google/monitoring/v3/uptime_service.proto - -It has these top-level messages: - TypedValue - TimeInterval - Aggregation - Group - ListGroupsRequest - ListGroupsResponse - GetGroupRequest - CreateGroupRequest - UpdateGroupRequest - DeleteGroupRequest - ListGroupMembersRequest - ListGroupMembersResponse - Point - TimeSeries - ListMonitoredResourceDescriptorsRequest - ListMonitoredResourceDescriptorsResponse - GetMonitoredResourceDescriptorRequest - ListMetricDescriptorsRequest - ListMetricDescriptorsResponse - GetMetricDescriptorRequest - CreateMetricDescriptorRequest - DeleteMetricDescriptorRequest - ListTimeSeriesRequest - ListTimeSeriesResponse - CreateTimeSeriesRequest - CreateTimeSeriesError - UptimeCheckConfig - UptimeCheckIp - ListUptimeCheckConfigsRequest - ListUptimeCheckConfigsResponse - GetUptimeCheckConfigRequest - CreateUptimeCheckConfigRequest - UpdateUptimeCheckConfigRequest - DeleteUptimeCheckConfigRequest - ListUptimeCheckIpsRequest - ListUptimeCheckIpsResponse -*/ package monitoring import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" import google_api2 "google.golang.org/genproto/googleapis/api/distribution" import google_protobuf3 "github.com/golang/protobuf/ptypes/duration" import google_protobuf2 "github.com/golang/protobuf/ptypes/timestamp" @@ -65,11 +16,87 @@ 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.ProtoPackageIsVersion2 // please upgrade the proto package +// Specifies an ordering relationship on two arguments, here called left and +// right. +type ComparisonType int32 + +const ( + // No ordering relationship is specified. + ComparisonType_COMPARISON_UNSPECIFIED ComparisonType = 0 + // The left argument is greater than the right argument. + ComparisonType_COMPARISON_GT ComparisonType = 1 + // The left argument is greater than or equal to the right argument. + ComparisonType_COMPARISON_GE ComparisonType = 2 + // The left argument is less than the right argument. + ComparisonType_COMPARISON_LT ComparisonType = 3 + // The left argument is less than or equal to the right argument. + ComparisonType_COMPARISON_LE ComparisonType = 4 + // The left argument is equal to the right argument. + ComparisonType_COMPARISON_EQ ComparisonType = 5 + // The left argument is not equal to the right argument. + ComparisonType_COMPARISON_NE ComparisonType = 6 +) + +var ComparisonType_name = map[int32]string{ + 0: "COMPARISON_UNSPECIFIED", + 1: "COMPARISON_GT", + 2: "COMPARISON_GE", + 3: "COMPARISON_LT", + 4: "COMPARISON_LE", + 5: "COMPARISON_EQ", + 6: "COMPARISON_NE", +} +var ComparisonType_value = map[string]int32{ + "COMPARISON_UNSPECIFIED": 0, + "COMPARISON_GT": 1, + "COMPARISON_GE": 2, + "COMPARISON_LT": 3, + "COMPARISON_LE": 4, + "COMPARISON_EQ": 5, + "COMPARISON_NE": 6, +} + +func (x ComparisonType) String() string { + return proto.EnumName(ComparisonType_name, int32(x)) +} +func (ComparisonType) EnumDescriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } + +// The tier of service for a Stackdriver account. Please see the +// [service tiers documentation](https://cloud.google.com/monitoring/accounts/tiers) +// for more details. +type ServiceTier int32 + +const ( + // An invalid sentinel value, used to indicate that a tier has not + // been provided explicitly. + ServiceTier_SERVICE_TIER_UNSPECIFIED ServiceTier = 0 + // The Stackdriver Basic tier, a free tier of service that provides basic + // features, a moderate allotment of logs, and access to built-in metrics. + // A number of features are not available in this tier. For more details, + // see [the service tiers documentation](https://cloud.google.com/monitoring/accounts/tiers). + ServiceTier_SERVICE_TIER_BASIC ServiceTier = 1 + // The Stackdriver Premium tier, a higher, more expensive tier of service + // that provides access to all Stackdriver features, lets you use Stackdriver + // with AWS accounts, and has a larger allotments for logs and metrics. For + // more details, see [the service tiers documentation](https://cloud.google.com/monitoring/accounts/tiers). + ServiceTier_SERVICE_TIER_PREMIUM ServiceTier = 2 +) + +var ServiceTier_name = map[int32]string{ + 0: "SERVICE_TIER_UNSPECIFIED", + 1: "SERVICE_TIER_BASIC", + 2: "SERVICE_TIER_PREMIUM", +} +var ServiceTier_value = map[string]int32{ + "SERVICE_TIER_UNSPECIFIED": 0, + "SERVICE_TIER_BASIC": 1, + "SERVICE_TIER_PREMIUM": 2, +} + +func (x ServiceTier) String() string { + return proto.EnumName(ServiceTier_name, int32(x)) +} +func (ServiceTier) EnumDescriptor() ([]byte, []int) { return fileDescriptor2, []int{1} } // The Aligner describes how to bring the data points in a single // time series into temporal alignment. @@ -85,11 +112,22 @@ const ( // delta metric to a delta metric requires that the alignment // period be increased. The value type of the result is the same // as the value type of the input. + // + // One can think of this aligner as a rate but without time units; that + // is, the output is conceptually (second_point - first_point). Aggregation_ALIGN_DELTA Aggregation_Aligner = 1 // Align and convert to a rate. This alignment is valid for // cumulative metrics and delta metrics with numeric values. The output is a // gauge metric with value type // [DOUBLE][google.api.MetricDescriptor.ValueType.DOUBLE]. + // + // One can think of this aligner as conceptually providing the slope of + // the line that passes through the value at the start and end of the + // window. In other words, this is conceptually ((y1 - y0)/(t1 - t0)), + // and the output unit is one that has a "/time" dimension. + // + // If, by rate, you are looking for percentage change, see the + // `ALIGN_PERCENT_CHANGE` aligner option. Aggregation_ALIGN_RATE Aggregation_Aligner = 2 // Align by interpolating between adjacent points around the // period boundary. This alignment is valid for gauge @@ -144,6 +182,12 @@ const ( // [INT64][google.api.MetricDescriptor.ValueType.INT64]. Aggregation_ALIGN_COUNT_TRUE Aggregation_Aligner = 16 // Align time series via aggregation. The resulting data point in + // the alignment period is the count of False-valued data points in the + // period. This alignment is valid for gauge metrics with + // Boolean values. The value type of the output is + // [INT64][google.api.MetricDescriptor.ValueType.INT64]. + Aggregation_ALIGN_COUNT_FALSE Aggregation_Aligner = 24 + // Align time series via aggregation. The resulting data point in // the alignment period is the fraction of True-valued data points in the // period. This alignment is valid for gauge metrics with Boolean values. // The output value is in the range [0, 1] and has value type @@ -173,6 +217,22 @@ const ( // with distribution values. The output is a gauge metric with value type // [DOUBLE][google.api.MetricDescriptor.ValueType.DOUBLE]. Aggregation_ALIGN_PERCENTILE_05 Aggregation_Aligner = 21 + // Align and convert to a percentage change. This alignment is valid for + // gauge and delta metrics with numeric values. This alignment conceptually + // computes the equivalent of "((current - previous)/previous)*100" + // where previous value is determined based on the alignmentPeriod. + // In the event that previous is 0 the calculated value is infinity with the + // exception that if both (current - previous) and previous are 0 the + // calculated value is 0. + // A 10 minute moving mean is computed at each point of the time window + // prior to the above calculation to smooth the metric and prevent false + // positives from very short lived spikes. + // Only applicable for data that is >= 0. Any values < 0 are treated as + // no data. While delta metrics are accepted by this alignment special care + // should be taken that the values for the metric will always be positive. + // The output is a gauge metric with value type + // [DOUBLE][google.api.MetricDescriptor.ValueType.DOUBLE]. + Aggregation_ALIGN_PERCENT_CHANGE Aggregation_Aligner = 23 ) var Aggregation_Aligner_name = map[int32]string{ @@ -188,36 +248,40 @@ var Aggregation_Aligner_name = map[int32]string{ 14: "ALIGN_SUM", 15: "ALIGN_STDDEV", 16: "ALIGN_COUNT_TRUE", + 24: "ALIGN_COUNT_FALSE", 17: "ALIGN_FRACTION_TRUE", 18: "ALIGN_PERCENTILE_99", 19: "ALIGN_PERCENTILE_95", 20: "ALIGN_PERCENTILE_50", 21: "ALIGN_PERCENTILE_05", + 23: "ALIGN_PERCENT_CHANGE", } var Aggregation_Aligner_value = map[string]int32{ - "ALIGN_NONE": 0, - "ALIGN_DELTA": 1, - "ALIGN_RATE": 2, - "ALIGN_INTERPOLATE": 3, - "ALIGN_NEXT_OLDER": 4, - "ALIGN_MIN": 10, - "ALIGN_MAX": 11, - "ALIGN_MEAN": 12, - "ALIGN_COUNT": 13, - "ALIGN_SUM": 14, - "ALIGN_STDDEV": 15, - "ALIGN_COUNT_TRUE": 16, - "ALIGN_FRACTION_TRUE": 17, - "ALIGN_PERCENTILE_99": 18, - "ALIGN_PERCENTILE_95": 19, - "ALIGN_PERCENTILE_50": 20, - "ALIGN_PERCENTILE_05": 21, + "ALIGN_NONE": 0, + "ALIGN_DELTA": 1, + "ALIGN_RATE": 2, + "ALIGN_INTERPOLATE": 3, + "ALIGN_NEXT_OLDER": 4, + "ALIGN_MIN": 10, + "ALIGN_MAX": 11, + "ALIGN_MEAN": 12, + "ALIGN_COUNT": 13, + "ALIGN_SUM": 14, + "ALIGN_STDDEV": 15, + "ALIGN_COUNT_TRUE": 16, + "ALIGN_COUNT_FALSE": 24, + "ALIGN_FRACTION_TRUE": 17, + "ALIGN_PERCENTILE_99": 18, + "ALIGN_PERCENTILE_95": 19, + "ALIGN_PERCENTILE_50": 20, + "ALIGN_PERCENTILE_05": 21, + "ALIGN_PERCENT_CHANGE": 23, } func (x Aggregation_Aligner) String() string { return proto.EnumName(Aggregation_Aligner_name, int32(x)) } -func (Aggregation_Aligner) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } +func (Aggregation_Aligner) EnumDescriptor() ([]byte, []int) { return fileDescriptor2, []int{2, 0} } // A Reducer describes how to aggregate data points from multiple // time series into a single time series. @@ -263,6 +327,11 @@ const ( // and gauge metrics of Boolean value type. The value type of // the output is [INT64][google.api.MetricDescriptor.ValueType.INT64]. Aggregation_REDUCE_COUNT_TRUE Aggregation_Reducer = 7 + // Reduce by computing the count of False-valued data points across time + // series for each alignment period. This reducer is valid for delta + // and gauge metrics of Boolean value type. The value type of + // the output is [INT64][google.api.MetricDescriptor.ValueType.INT64]. + Aggregation_REDUCE_COUNT_FALSE Aggregation_Reducer = 15 // Reduce by computing the fraction of True-valued data points across time // series for each alignment period. This reducer is valid for delta // and gauge metrics of Boolean value type. The output value is in the @@ -300,6 +369,7 @@ var Aggregation_Reducer_name = map[int32]string{ 5: "REDUCE_STDDEV", 6: "REDUCE_COUNT", 7: "REDUCE_COUNT_TRUE", + 15: "REDUCE_COUNT_FALSE", 8: "REDUCE_FRACTION_TRUE", 9: "REDUCE_PERCENTILE_99", 10: "REDUCE_PERCENTILE_95", @@ -315,6 +385,7 @@ var Aggregation_Reducer_value = map[string]int32{ "REDUCE_STDDEV": 5, "REDUCE_COUNT": 6, "REDUCE_COUNT_TRUE": 7, + "REDUCE_COUNT_FALSE": 15, "REDUCE_FRACTION_TRUE": 8, "REDUCE_PERCENTILE_99": 9, "REDUCE_PERCENTILE_95": 10, @@ -325,7 +396,7 @@ var Aggregation_Reducer_value = map[string]int32{ func (x Aggregation_Reducer) String() string { return proto.EnumName(Aggregation_Reducer_name, int32(x)) } -func (Aggregation_Reducer) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 1} } +func (Aggregation_Reducer) EnumDescriptor() ([]byte, []int) { return fileDescriptor2, []int{2, 1} } // A single strongly-typed value. type TypedValue struct { @@ -343,7 +414,7 @@ type TypedValue struct { func (m *TypedValue) Reset() { *m = TypedValue{} } func (m *TypedValue) String() string { return proto.CompactTextString(m) } func (*TypedValue) ProtoMessage() {} -func (*TypedValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*TypedValue) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } type isTypedValue_Value interface { isTypedValue_Value() @@ -544,7 +615,7 @@ type TimeInterval struct { func (m *TimeInterval) Reset() { *m = TimeInterval{} } func (m *TimeInterval) String() string { return proto.CompactTextString(m) } func (*TimeInterval) ProtoMessage() {} -func (*TimeInterval) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*TimeInterval) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{1} } func (m *TimeInterval) GetEndTime() *google_protobuf2.Timestamp { if m != nil { @@ -562,8 +633,9 @@ func (m *TimeInterval) GetStartTime() *google_protobuf2.Timestamp { // Describes how to combine multiple time series to provide different views of // the data. Aggregation consists of an alignment step on individual time -// series (`per_series_aligner`) followed by an optional reduction of the data -// across different time series (`cross_series_reducer`). For more details, see +// series (`alignment_period` and `per_series_aligner`) followed by an optional +// reduction step of the data across the aligned time series +// (`cross_series_reducer` and `group_by_fields`). For more details, see // [Aggregation](/monitoring/api/learn_more#aggregation). type Aggregation struct { // The alignment period for per-[time series][google.monitoring.v3.TimeSeries] @@ -619,7 +691,7 @@ type Aggregation struct { func (m *Aggregation) Reset() { *m = Aggregation{} } func (m *Aggregation) String() string { return proto.CompactTextString(m) } func (*Aggregation) ProtoMessage() {} -func (*Aggregation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*Aggregation) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{2} } func (m *Aggregation) GetAlignmentPeriod() *google_protobuf3.Duration { if m != nil { @@ -653,62 +725,74 @@ func init() { proto.RegisterType((*TypedValue)(nil), "google.monitoring.v3.TypedValue") proto.RegisterType((*TimeInterval)(nil), "google.monitoring.v3.TimeInterval") proto.RegisterType((*Aggregation)(nil), "google.monitoring.v3.Aggregation") + proto.RegisterEnum("google.monitoring.v3.ComparisonType", ComparisonType_name, ComparisonType_value) + proto.RegisterEnum("google.monitoring.v3.ServiceTier", ServiceTier_name, ServiceTier_value) proto.RegisterEnum("google.monitoring.v3.Aggregation_Aligner", Aggregation_Aligner_name, Aggregation_Aligner_value) proto.RegisterEnum("google.monitoring.v3.Aggregation_Reducer", Aggregation_Reducer_name, Aggregation_Reducer_value) } -func init() { proto.RegisterFile("google/monitoring/v3/common.proto", fileDescriptor0) } - -var fileDescriptor0 = []byte{ - // 792 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0xdd, 0x6a, 0xe3, 0x46, - 0x14, 0xb6, 0xec, 0x64, 0x1d, 0x1f, 0x39, 0xf1, 0x64, 0xd6, 0x4b, 0xdd, 0x40, 0xbb, 0x5e, 0x17, - 0x8a, 0x7b, 0x23, 0x87, 0xb8, 0x2e, 0x84, 0x42, 0x41, 0xb1, 0xb5, 0x1b, 0x83, 0x23, 0x9b, 0x59, - 0x25, 0x0d, 0x6d, 0x40, 0xc8, 0xd1, 0xac, 0x10, 0xc8, 0x1a, 0x31, 0x92, 0x0d, 0xb9, 0xeb, 0x6b, - 0xf4, 0xba, 0x77, 0xfb, 0x28, 0x7d, 0x84, 0x3e, 0x44, 0x9f, 0xa1, 0x68, 0x66, 0xb4, 0x52, 0x5a, - 0x97, 0xf6, 0xf2, 0xfb, 0x39, 0xdf, 0xe8, 0x7c, 0x23, 0xd9, 0xf0, 0x26, 0x60, 0x2c, 0x88, 0xe8, - 0x68, 0xc3, 0xe2, 0x30, 0x63, 0x3c, 0x8c, 0x83, 0xd1, 0x6e, 0x3c, 0x7a, 0x64, 0x9b, 0x0d, 0x8b, - 0x8d, 0x84, 0xb3, 0x8c, 0xe1, 0xae, 0xb4, 0x18, 0xa5, 0xc5, 0xd8, 0x8d, 0xcf, 0xbe, 0x50, 0x83, - 0x5e, 0x12, 0x8e, 0xfc, 0x30, 0xcd, 0x78, 0xb8, 0xde, 0x66, 0x61, 0x31, 0x74, 0xf6, 0xa5, 0x92, - 0x05, 0x5a, 0x6f, 0x3f, 0x8c, 0xfc, 0x2d, 0xf7, 0x2a, 0xfa, 0xeb, 0xbf, 0xeb, 0x59, 0xb8, 0xa1, - 0x69, 0xe6, 0x6d, 0x12, 0x69, 0x18, 0xfc, 0xa9, 0x01, 0x38, 0x4f, 0x09, 0xf5, 0xef, 0xbc, 0x68, - 0x4b, 0xf1, 0x6b, 0x80, 0x35, 0x63, 0x91, 0xbb, 0xcb, 0x51, 0x4f, 0xeb, 0x6b, 0xc3, 0xa3, 0xeb, - 0x1a, 0x69, 0xe5, 0x9c, 0x34, 0xbc, 0x01, 0x3d, 0x8c, 0xb3, 0xef, 0xbe, 0x55, 0x8e, 0x7a, 0x5f, - 0x1b, 0x36, 0xae, 0x6b, 0x04, 0x04, 0x29, 0x2d, 0x5f, 0x41, 0xdb, 0x67, 0xdb, 0x75, 0x44, 0x95, - 0xa7, 0xd1, 0xd7, 0x86, 0xda, 0x75, 0x8d, 0xe8, 0x92, 0xfd, 0x64, 0xca, 0x97, 0x89, 0x03, 0x65, - 0x3a, 0xe8, 0x6b, 0xc3, 0x56, 0x6e, 0x92, 0xac, 0x34, 0xcd, 0x01, 0x57, 0x77, 0x56, 0xd6, 0xc3, - 0xbe, 0x36, 0xd4, 0x2f, 0x7a, 0x86, 0xea, 0xcb, 0x4b, 0x42, 0x63, 0x56, 0x71, 0x5d, 0xd7, 0xc8, - 0x69, 0x75, 0x4a, 0x44, 0x5d, 0x35, 0xe1, 0x50, 0x4c, 0x0f, 0x7e, 0xd1, 0xa0, 0xed, 0x84, 0x1b, - 0x3a, 0x8f, 0x33, 0xca, 0x77, 0x5e, 0x84, 0x27, 0x70, 0x44, 0x63, 0xdf, 0xcd, 0x8b, 0x11, 0xeb, - 0xe8, 0x17, 0x67, 0x45, 0x74, 0xd1, 0x9a, 0xe1, 0x14, 0xad, 0x91, 0x26, 0x8d, 0xfd, 0x1c, 0xe1, - 0x4b, 0x80, 0x34, 0xf3, 0x78, 0x26, 0x07, 0xb5, 0xff, 0x1c, 0x6c, 0x09, 0x77, 0x8e, 0x07, 0x1f, - 0x9b, 0xa0, 0x9b, 0x41, 0xc0, 0x69, 0x20, 0xae, 0x0a, 0xcf, 0x00, 0x79, 0x51, 0x18, 0xc4, 0x1b, - 0x1a, 0x67, 0x6e, 0x42, 0x79, 0xc8, 0x7c, 0x15, 0xf8, 0xf9, 0x3f, 0x02, 0x67, 0xea, 0x7e, 0x49, - 0xe7, 0xd3, 0xc8, 0x4a, 0x4c, 0xe0, 0x1f, 0x01, 0x27, 0x94, 0xbb, 0x29, 0xe5, 0x21, 0x4d, 0x5d, - 0xa1, 0x52, 0x2e, 0x36, 0x3a, 0xb9, 0xf8, 0xc6, 0xd8, 0xf7, 0x72, 0x19, 0x95, 0x87, 0x30, 0x4c, - 0x39, 0x40, 0x50, 0x42, 0xf9, 0x7b, 0x91, 0xa1, 0x18, 0xfc, 0x33, 0x74, 0x1f, 0x39, 0x4b, 0xd3, - 0x22, 0x9a, 0x53, 0x7f, 0xfb, 0x48, 0xb9, 0xb8, 0xb2, 0xff, 0x15, 0x4d, 0xe4, 0x00, 0xc1, 0x22, - 0x46, 0x86, 0x2b, 0x0e, 0x7f, 0x0d, 0x9d, 0x80, 0xb3, 0x6d, 0xe2, 0xae, 0x9f, 0xdc, 0x0f, 0x21, - 0x8d, 0xfc, 0xb4, 0x77, 0xd8, 0x6f, 0x0c, 0x5b, 0xe4, 0x58, 0xd0, 0x57, 0x4f, 0x6f, 0x05, 0x39, - 0xf8, 0xa3, 0x0e, 0xcd, 0xe2, 0x81, 0x4e, 0x00, 0xcc, 0xc5, 0xfc, 0x9d, 0xed, 0xda, 0x4b, 0xdb, - 0x42, 0x35, 0xdc, 0x01, 0x5d, 0xe2, 0x99, 0xb5, 0x70, 0x4c, 0xa4, 0x95, 0x06, 0x62, 0x3a, 0x16, - 0xaa, 0xe3, 0x57, 0x70, 0x2a, 0xf1, 0xdc, 0x76, 0x2c, 0xb2, 0x5a, 0x2e, 0x72, 0xba, 0x81, 0xbb, - 0x80, 0x54, 0x8e, 0x75, 0xef, 0xb8, 0xcb, 0xc5, 0xcc, 0x22, 0xe8, 0x00, 0x1f, 0x43, 0x4b, 0xb2, - 0x37, 0x73, 0x1b, 0x41, 0x05, 0x9a, 0xf7, 0x48, 0x2f, 0xa3, 0x6f, 0x2c, 0xd3, 0x46, 0xed, 0xf2, - 0xec, 0xe9, 0xf2, 0xd6, 0x76, 0xd0, 0x71, 0xe9, 0x7f, 0x7f, 0x7b, 0x83, 0x4e, 0x30, 0x82, 0xb6, - 0x82, 0xce, 0x6c, 0x66, 0xdd, 0xa1, 0x4e, 0x79, 0xaa, 0x98, 0x70, 0x1d, 0x72, 0x6b, 0x21, 0x84, - 0x3f, 0x83, 0x97, 0x92, 0x7d, 0x4b, 0xcc, 0xa9, 0x33, 0x5f, 0xda, 0x52, 0x38, 0x2d, 0x85, 0x95, - 0x45, 0xa6, 0x96, 0xed, 0xcc, 0x17, 0x96, 0x7b, 0x79, 0x89, 0xf0, 0x7e, 0x61, 0x82, 0x5e, 0xee, - 0x15, 0x26, 0xe7, 0xa8, 0xbb, 0x57, 0x38, 0x9f, 0xa0, 0x57, 0x83, 0x5f, 0xeb, 0xd0, 0x2c, 0x2e, - 0xa4, 0x03, 0x3a, 0xb1, 0x66, 0xb7, 0x53, 0xab, 0xd2, 0xae, 0x22, 0xc4, 0xca, 0xa2, 0xdd, 0x82, - 0x98, 0xdb, 0xa8, 0x5e, 0xc5, 0xe6, 0x3d, 0x6a, 0x54, 0x70, 0x5e, 0xc1, 0x01, 0x3e, 0x85, 0xe3, - 0x02, 0xcb, 0x0e, 0x0e, 0xf3, 0x56, 0x14, 0x25, 0x6b, 0x7b, 0x91, 0x5f, 0x51, 0x95, 0x91, 0xdb, - 0x37, 0x71, 0x0f, 0xba, 0x8a, 0x7e, 0xde, 0xcb, 0x51, 0x45, 0x79, 0x5e, 0x4c, 0xeb, 0x5f, 0x94, - 0x09, 0x82, 0xfd, 0xca, 0xe4, 0x1c, 0xe9, 0xfb, 0x95, 0xf3, 0x09, 0x6a, 0x5f, 0xfd, 0xa6, 0x41, - 0xef, 0x91, 0x6d, 0xf6, 0xbe, 0xe5, 0x57, 0xfa, 0x54, 0xfc, 0x82, 0xaf, 0xf2, 0xaf, 0x73, 0xa5, - 0xfd, 0xf4, 0x83, 0x32, 0x05, 0x2c, 0xf2, 0xe2, 0xc0, 0x60, 0x3c, 0x18, 0x05, 0x34, 0x16, 0xdf, - 0xee, 0x48, 0x4a, 0x5e, 0x12, 0xa6, 0xcf, 0xff, 0x04, 0xbe, 0x2f, 0xd1, 0xc7, 0xfa, 0xd9, 0x3b, - 0x19, 0x30, 0x8d, 0xd8, 0xd6, 0x37, 0x6e, 0xca, 0xb3, 0xee, 0xc6, 0xbf, 0x17, 0xe2, 0x83, 0x10, - 0x1f, 0x4a, 0xf1, 0xe1, 0x6e, 0xbc, 0x7e, 0x21, 0x0e, 0x19, 0xff, 0x15, 0x00, 0x00, 0xff, 0xff, - 0x57, 0xa4, 0xb9, 0xce, 0x68, 0x06, 0x00, 0x00, +func init() { proto.RegisterFile("google/monitoring/v3/common.proto", fileDescriptor2) } + +var fileDescriptor2 = []byte{ + // 954 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x95, 0xc1, 0x6e, 0xe3, 0x44, + 0x18, 0xc7, 0xe3, 0xa4, 0x6d, 0x9a, 0xcf, 0x6d, 0x33, 0x9d, 0xed, 0x76, 0x43, 0xb5, 0xb0, 0xd9, + 0x22, 0xa1, 0xb0, 0x07, 0xa7, 0x6a, 0x09, 0x52, 0x85, 0x84, 0xe4, 0x3a, 0xd3, 0xd6, 0x52, 0xe2, + 0x84, 0x89, 0x53, 0x2a, 0x28, 0xb2, 0x9c, 0x66, 0xd6, 0xb2, 0x94, 0x78, 0x2c, 0xdb, 0xa9, 0xd4, + 0x1b, 0x77, 0xde, 0x81, 0x0b, 0x37, 0x6e, 0xbc, 0x06, 0x0f, 0xc3, 0x85, 0x17, 0x40, 0x9e, 0x71, + 0xd6, 0x4e, 0x08, 0x62, 0x8f, 0xdf, 0xef, 0xff, 0xff, 0xbe, 0x99, 0xf9, 0x8f, 0x35, 0x86, 0xb7, + 0x1e, 0xe7, 0xde, 0x8c, 0xb5, 0xe7, 0x3c, 0xf0, 0x13, 0x1e, 0xf9, 0x81, 0xd7, 0x7e, 0xba, 0x68, + 0x3f, 0xf2, 0xf9, 0x9c, 0x07, 0x5a, 0x18, 0xf1, 0x84, 0xe3, 0x23, 0x69, 0xd1, 0x72, 0x8b, 0xf6, + 0x74, 0x71, 0xf2, 0x3a, 0x6b, 0x74, 0x43, 0xbf, 0xed, 0x06, 0x01, 0x4f, 0xdc, 0xc4, 0xe7, 0x41, + 0x2c, 0x7b, 0x4e, 0x3e, 0x2d, 0xa8, 0x53, 0x3f, 0x4e, 0x22, 0x7f, 0xb2, 0x48, 0xf5, 0x4c, 0xfe, + 0x2c, 0x93, 0x45, 0x35, 0x59, 0xbc, 0x6f, 0x4f, 0x17, 0x91, 0x5b, 0xd0, 0xdf, 0xac, 0xeb, 0x89, + 0x3f, 0x67, 0x71, 0xe2, 0xce, 0x43, 0x69, 0x38, 0xfd, 0x4b, 0x01, 0xb0, 0x9f, 0x43, 0x36, 0xbd, + 0x73, 0x67, 0x0b, 0x86, 0xdf, 0x00, 0x4c, 0x38, 0x9f, 0x39, 0x4f, 0x69, 0xd5, 0x50, 0x9a, 0x4a, + 0x6b, 0xf7, 0xb6, 0x44, 0x6b, 0x29, 0x93, 0x86, 0xb7, 0xa0, 0xfa, 0x41, 0xf2, 0xf5, 0x57, 0x99, + 0xa3, 0xdc, 0x54, 0x5a, 0x95, 0xdb, 0x12, 0x05, 0x01, 0xa5, 0xe5, 0x73, 0xd8, 0x9b, 0xf2, 0xc5, + 0x64, 0xc6, 0x32, 0x4f, 0xa5, 0xa9, 0xb4, 0x94, 0xdb, 0x12, 0x55, 0x25, 0xfd, 0x60, 0x4a, 0x0f, + 0x13, 0x78, 0x99, 0x69, 0xab, 0xa9, 0xb4, 0x6a, 0xa9, 0x49, 0x52, 0x69, 0x32, 0x01, 0x17, 0xcf, + 0x9c, 0x59, 0xb7, 0x9b, 0x4a, 0x4b, 0x3d, 0x6f, 0x68, 0x59, 0x9a, 0x6e, 0xe8, 0x6b, 0xdd, 0x82, + 0xeb, 0xb6, 0x44, 0x0f, 0x8b, 0x5d, 0x62, 0xd4, 0x55, 0x15, 0xb6, 0x45, 0xf7, 0xe9, 0xcf, 0x0a, + 0xec, 0xd9, 0xfe, 0x9c, 0x99, 0x41, 0xc2, 0xa2, 0x27, 0x77, 0x86, 0x3b, 0xb0, 0xcb, 0x82, 0xa9, + 0x93, 0x06, 0x23, 0x8e, 0xa3, 0x9e, 0x9f, 0x2c, 0x47, 0x2f, 0x53, 0xd3, 0xec, 0x65, 0x6a, 0xb4, + 0xca, 0x82, 0x69, 0x5a, 0xe1, 0x4b, 0x80, 0x38, 0x71, 0xa3, 0x44, 0x36, 0x2a, 0xff, 0xdb, 0x58, + 0x13, 0xee, 0xb4, 0x3e, 0xfd, 0xbb, 0x0a, 0xaa, 0xee, 0x79, 0x11, 0xf3, 0xc4, 0x55, 0xe1, 0x2e, + 0x20, 0x77, 0xe6, 0x7b, 0xc1, 0x9c, 0x05, 0x89, 0x13, 0xb2, 0xc8, 0xe7, 0xd3, 0x6c, 0xe0, 0x27, + 0xff, 0x1a, 0xd8, 0xcd, 0xee, 0x97, 0xd6, 0x3f, 0xb4, 0x0c, 0x45, 0x07, 0xfe, 0x1e, 0x70, 0xc8, + 0x22, 0x27, 0x66, 0x91, 0xcf, 0x62, 0x47, 0xa8, 0x2c, 0x12, 0x27, 0x3a, 0x38, 0xff, 0x52, 0xdb, + 0xf4, 0xe9, 0x69, 0x85, 0x4d, 0x68, 0xba, 0x6c, 0xa0, 0x28, 0x64, 0xd1, 0x48, 0xcc, 0xc8, 0x08, + 0xfe, 0x11, 0x8e, 0x1e, 0x23, 0x1e, 0xc7, 0xcb, 0xd1, 0x11, 0x9b, 0x2e, 0x1e, 0x59, 0x24, 0xae, + 0xec, 0xa3, 0x46, 0x53, 0xd9, 0x40, 0xb1, 0x18, 0x23, 0x87, 0x67, 0x0c, 0x7f, 0x01, 0x75, 0x2f, + 0xe2, 0x8b, 0xd0, 0x99, 0x3c, 0x3b, 0xef, 0x7d, 0x36, 0x9b, 0xc6, 0x8d, 0xed, 0x66, 0xa5, 0x55, + 0xa3, 0xfb, 0x02, 0x5f, 0x3d, 0x5f, 0x0b, 0x78, 0xfa, 0x4b, 0x05, 0xaa, 0xcb, 0x0d, 0x1d, 0x00, + 0xe8, 0x3d, 0xf3, 0xc6, 0x72, 0xac, 0x81, 0x45, 0x50, 0x09, 0xd7, 0x41, 0x95, 0x75, 0x97, 0xf4, + 0x6c, 0x1d, 0x29, 0xb9, 0x81, 0xea, 0x36, 0x41, 0x65, 0xfc, 0x12, 0x0e, 0x65, 0x6d, 0x5a, 0x36, + 0xa1, 0xc3, 0x41, 0x2f, 0xc5, 0x15, 0x7c, 0x04, 0x28, 0x9b, 0x43, 0xee, 0x6d, 0x67, 0xd0, 0xeb, + 0x12, 0x8a, 0xb6, 0xf0, 0x3e, 0xd4, 0x24, 0xed, 0x9b, 0x16, 0x82, 0x42, 0xa9, 0xdf, 0x23, 0x35, + 0x1f, 0xdd, 0x27, 0xba, 0x85, 0xf6, 0xf2, 0xb5, 0x8d, 0xc1, 0xd8, 0xb2, 0xd1, 0x7e, 0xee, 0x1f, + 0x8d, 0xfb, 0xe8, 0x00, 0x23, 0xd8, 0xcb, 0x4a, 0xbb, 0xdb, 0x25, 0x77, 0xa8, 0x9e, 0xaf, 0x2a, + 0x3a, 0x1c, 0x9b, 0x8e, 0x09, 0x42, 0xf9, 0x16, 0x25, 0xbd, 0xd6, 0x7b, 0x23, 0x82, 0x1a, 0xf8, + 0x15, 0xbc, 0x90, 0xf8, 0x9a, 0xea, 0x86, 0x6d, 0x0e, 0x2c, 0xe9, 0x3f, 0xcc, 0x85, 0x21, 0xa1, + 0x06, 0xb1, 0x6c, 0xb3, 0x47, 0x9c, 0xcb, 0x4b, 0x84, 0x37, 0x0b, 0x1d, 0xf4, 0x62, 0xa3, 0xd0, + 0x39, 0x43, 0x47, 0x1b, 0x85, 0xb3, 0x0e, 0x7a, 0x89, 0x1b, 0x70, 0xb4, 0x22, 0x38, 0xc6, 0xad, + 0x6e, 0xdd, 0x10, 0xf4, 0xea, 0xf4, 0x8f, 0x32, 0x54, 0x97, 0x37, 0x58, 0x07, 0x95, 0x92, 0xee, + 0xd8, 0x20, 0x85, 0xeb, 0xc8, 0x80, 0xc8, 0x48, 0x5c, 0xc7, 0x12, 0x98, 0x16, 0x2a, 0x17, 0x6b, + 0xfd, 0x1e, 0x55, 0x0a, 0x75, 0x9a, 0xd9, 0x16, 0x3e, 0x84, 0xfd, 0x65, 0x2d, 0x43, 0xdb, 0x4e, + 0x63, 0xcc, 0x90, 0xcc, 0x79, 0x27, 0x0d, 0xac, 0x48, 0x64, 0x2e, 0x55, 0x7c, 0x0c, 0x78, 0x05, + 0xcb, 0x20, 0xeb, 0xe9, 0x59, 0x32, 0xbe, 0x9a, 0xe4, 0x6e, 0x41, 0x59, 0x8d, 0xb2, 0xf6, 0x1f, + 0x4a, 0x07, 0xc1, 0x66, 0xa5, 0x73, 0x86, 0xd4, 0xcd, 0xca, 0x59, 0x07, 0xed, 0xbd, 0xfb, 0x55, + 0x81, 0x03, 0x83, 0xcf, 0x43, 0x37, 0xf2, 0x63, 0x1e, 0xa4, 0x6f, 0x2e, 0x3e, 0x81, 0x63, 0x63, + 0xd0, 0x1f, 0xea, 0xd4, 0x1c, 0x0d, 0x2c, 0x67, 0x6c, 0x8d, 0x86, 0xc4, 0x30, 0xaf, 0x4d, 0xd2, + 0x45, 0xa5, 0x34, 0x84, 0x82, 0x76, 0x63, 0x23, 0x65, 0x1d, 0xa5, 0x5f, 0xf6, 0x2a, 0xea, 0xd9, + 0xa8, 0xb2, 0x8e, 0x88, 0x0c, 0xb4, 0x80, 0xc8, 0x77, 0x68, 0x7b, 0x0d, 0x59, 0x04, 0xed, 0xbc, + 0xfb, 0x09, 0xd4, 0x11, 0x8b, 0x9e, 0xfc, 0x47, 0x66, 0xfb, 0x2c, 0xc2, 0xaf, 0xa1, 0x31, 0x22, + 0xf4, 0xce, 0x34, 0x88, 0x63, 0x9b, 0x84, 0xae, 0x6d, 0xef, 0x18, 0xf0, 0x8a, 0x7a, 0xa5, 0x8f, + 0x4c, 0x03, 0x29, 0xe9, 0xf9, 0x57, 0xf8, 0x90, 0x92, 0xbe, 0x39, 0xee, 0xa3, 0xf2, 0xd5, 0x6f, + 0x0a, 0x34, 0x1e, 0xf9, 0x7c, 0xe3, 0x73, 0x71, 0xa5, 0x1a, 0xe2, 0x47, 0x39, 0x4c, 0x9f, 0xb9, + 0xa1, 0xf2, 0xc3, 0xb7, 0x99, 0xc9, 0xe3, 0x33, 0x37, 0xf0, 0x34, 0x1e, 0x79, 0x6d, 0x8f, 0x05, + 0xe2, 0x11, 0x6c, 0x4b, 0xc9, 0x0d, 0xfd, 0x78, 0xf5, 0x5f, 0xfb, 0x4d, 0x5e, 0xfd, 0x5e, 0x3e, + 0xb9, 0x91, 0x03, 0x8c, 0x19, 0x5f, 0x4c, 0xb5, 0x7e, 0xbe, 0xd6, 0xdd, 0xc5, 0x9f, 0x4b, 0xf1, + 0x41, 0x88, 0x0f, 0xb9, 0xf8, 0x70, 0x77, 0x31, 0xd9, 0x11, 0x8b, 0x5c, 0xfc, 0x13, 0x00, 0x00, + 0xff, 0xff, 0xe2, 0x9f, 0x67, 0xb2, 0xcf, 0x07, 0x00, 0x00, } diff --git a/google.golang.org/genproto/googleapis/monitoring/v3/group.pb.go b/google.golang.org/genproto/googleapis/monitoring/v3/group.pb.go index a9c0dd81..0afad7a6 100644 --- a/google.golang.org/genproto/googleapis/monitoring/v3/group.pb.go +++ b/google.golang.org/genproto/googleapis/monitoring/v3/group.pb.go @@ -61,7 +61,7 @@ type Group struct { func (m *Group) Reset() { *m = Group{} } func (m *Group) String() string { return proto.CompactTextString(m) } func (*Group) ProtoMessage() {} -func (*Group) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } +func (*Group) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0} } func (m *Group) GetName() string { if m != nil { @@ -102,9 +102,9 @@ func init() { proto.RegisterType((*Group)(nil), "google.monitoring.v3.Group") } -func init() { proto.RegisterFile("google/monitoring/v3/group.proto", fileDescriptor1) } +func init() { proto.RegisterFile("google/monitoring/v3/group.proto", fileDescriptor3) } -var fileDescriptor1 = []byte{ +var fileDescriptor3 = []byte{ // 261 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xcf, 0x4a, 0x2b, 0x31, 0x14, 0x87, 0x49, 0xef, 0xed, 0x60, 0x4f, 0x5d, 0x0d, 0x22, 0x83, 0x20, 0x8e, 0xae, 0xba, 0xca, diff --git a/google.golang.org/genproto/googleapis/monitoring/v3/group_service.pb.go b/google.golang.org/genproto/googleapis/monitoring/v3/group_service.pb.go index 14750fa9..de212a50 100644 --- a/google.golang.org/genproto/googleapis/monitoring/v3/group_service.pb.go +++ b/google.golang.org/genproto/googleapis/monitoring/v3/group_service.pb.go @@ -8,7 +8,7 @@ import fmt "fmt" import math "math" import _ "google.golang.org/genproto/googleapis/api/annotations" import google_api4 "google.golang.org/genproto/googleapis/api/monitoredres" -import google_protobuf4 "github.com/golang/protobuf/ptypes/empty" +import google_protobuf5 "github.com/golang/protobuf/ptypes/empty" import ( context "golang.org/x/net/context" @@ -45,7 +45,7 @@ type ListGroupsRequest struct { func (m *ListGroupsRequest) Reset() { *m = ListGroupsRequest{} } func (m *ListGroupsRequest) String() string { return proto.CompactTextString(m) } func (*ListGroupsRequest) ProtoMessage() {} -func (*ListGroupsRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } +func (*ListGroupsRequest) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{0} } type isListGroupsRequest_Filter interface { isListGroupsRequest_Filter() @@ -208,7 +208,7 @@ type ListGroupsResponse struct { func (m *ListGroupsResponse) Reset() { *m = ListGroupsResponse{} } func (m *ListGroupsResponse) String() string { return proto.CompactTextString(m) } func (*ListGroupsResponse) ProtoMessage() {} -func (*ListGroupsResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{1} } +func (*ListGroupsResponse) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{1} } func (m *ListGroupsResponse) GetGroup() []*Group { if m != nil { @@ -234,7 +234,7 @@ type GetGroupRequest struct { func (m *GetGroupRequest) Reset() { *m = GetGroupRequest{} } func (m *GetGroupRequest) String() string { return proto.CompactTextString(m) } func (*GetGroupRequest) ProtoMessage() {} -func (*GetGroupRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{2} } +func (*GetGroupRequest) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{2} } func (m *GetGroupRequest) GetName() string { if m != nil { @@ -258,7 +258,7 @@ type CreateGroupRequest struct { func (m *CreateGroupRequest) Reset() { *m = CreateGroupRequest{} } func (m *CreateGroupRequest) String() string { return proto.CompactTextString(m) } func (*CreateGroupRequest) ProtoMessage() {} -func (*CreateGroupRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{3} } +func (*CreateGroupRequest) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{3} } func (m *CreateGroupRequest) GetName() string { if m != nil { @@ -293,7 +293,7 @@ type UpdateGroupRequest struct { func (m *UpdateGroupRequest) Reset() { *m = UpdateGroupRequest{} } func (m *UpdateGroupRequest) String() string { return proto.CompactTextString(m) } func (*UpdateGroupRequest) ProtoMessage() {} -func (*UpdateGroupRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{4} } +func (*UpdateGroupRequest) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{4} } func (m *UpdateGroupRequest) GetGroup() *Group { if m != nil { @@ -319,7 +319,7 @@ type DeleteGroupRequest struct { func (m *DeleteGroupRequest) Reset() { *m = DeleteGroupRequest{} } func (m *DeleteGroupRequest) String() string { return proto.CompactTextString(m) } func (*DeleteGroupRequest) ProtoMessage() {} -func (*DeleteGroupRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{5} } +func (*DeleteGroupRequest) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{5} } func (m *DeleteGroupRequest) GetName() string { if m != nil { @@ -357,7 +357,7 @@ type ListGroupMembersRequest struct { func (m *ListGroupMembersRequest) Reset() { *m = ListGroupMembersRequest{} } func (m *ListGroupMembersRequest) String() string { return proto.CompactTextString(m) } func (*ListGroupMembersRequest) ProtoMessage() {} -func (*ListGroupMembersRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{6} } +func (*ListGroupMembersRequest) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{6} } func (m *ListGroupMembersRequest) GetName() string { if m != nil { @@ -409,7 +409,7 @@ type ListGroupMembersResponse struct { func (m *ListGroupMembersResponse) Reset() { *m = ListGroupMembersResponse{} } func (m *ListGroupMembersResponse) String() string { return proto.CompactTextString(m) } func (*ListGroupMembersResponse) ProtoMessage() {} -func (*ListGroupMembersResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{7} } +func (*ListGroupMembersResponse) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{7} } func (m *ListGroupMembersResponse) GetMembers() []*google_api4.MonitoredResource { if m != nil { @@ -464,7 +464,7 @@ type GroupServiceClient interface { // You can change any group attributes except `name`. UpdateGroup(ctx context.Context, in *UpdateGroupRequest, opts ...grpc.CallOption) (*Group, error) // Deletes an existing group. - DeleteGroup(ctx context.Context, in *DeleteGroupRequest, opts ...grpc.CallOption) (*google_protobuf4.Empty, error) + DeleteGroup(ctx context.Context, in *DeleteGroupRequest, opts ...grpc.CallOption) (*google_protobuf5.Empty, error) // Lists the monitored resources that are members of a group. ListGroupMembers(ctx context.Context, in *ListGroupMembersRequest, opts ...grpc.CallOption) (*ListGroupMembersResponse, error) } @@ -513,8 +513,8 @@ func (c *groupServiceClient) UpdateGroup(ctx context.Context, in *UpdateGroupReq return out, nil } -func (c *groupServiceClient) DeleteGroup(ctx context.Context, in *DeleteGroupRequest, opts ...grpc.CallOption) (*google_protobuf4.Empty, error) { - out := new(google_protobuf4.Empty) +func (c *groupServiceClient) DeleteGroup(ctx context.Context, in *DeleteGroupRequest, opts ...grpc.CallOption) (*google_protobuf5.Empty, error) { + out := new(google_protobuf5.Empty) err := grpc.Invoke(ctx, "/google.monitoring.v3.GroupService/DeleteGroup", in, out, c.cc, opts...) if err != nil { return nil, err @@ -544,7 +544,7 @@ type GroupServiceServer interface { // You can change any group attributes except `name`. UpdateGroup(context.Context, *UpdateGroupRequest) (*Group, error) // Deletes an existing group. - DeleteGroup(context.Context, *DeleteGroupRequest) (*google_protobuf4.Empty, error) + DeleteGroup(context.Context, *DeleteGroupRequest) (*google_protobuf5.Empty, error) // Lists the monitored resources that are members of a group. ListGroupMembers(context.Context, *ListGroupMembersRequest) (*ListGroupMembersResponse, error) } @@ -694,9 +694,9 @@ var _GroupService_serviceDesc = grpc.ServiceDesc{ Metadata: "google/monitoring/v3/group_service.proto", } -func init() { proto.RegisterFile("google/monitoring/v3/group_service.proto", fileDescriptor2) } +func init() { proto.RegisterFile("google/monitoring/v3/group_service.proto", fileDescriptor4) } -var fileDescriptor2 = []byte{ +var fileDescriptor4 = []byte{ // 826 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0x4d, 0x6f, 0xd3, 0x4c, 0x10, 0x7e, 0xdd, 0xa4, 0x69, 0xb2, 0x69, 0xd5, 0x76, 0x55, 0xf5, 0x8d, 0xdc, 0x0f, 0x05, 0xf7, diff --git a/google.golang.org/genproto/googleapis/monitoring/v3/metric.pb.go b/google.golang.org/genproto/googleapis/monitoring/v3/metric.pb.go index 533b5373..99e74513 100644 --- a/google.golang.org/genproto/googleapis/monitoring/v3/metric.pb.go +++ b/google.golang.org/genproto/googleapis/monitoring/v3/metric.pb.go @@ -32,7 +32,7 @@ type Point struct { func (m *Point) Reset() { *m = Point{} } func (m *Point) String() string { return proto.CompactTextString(m) } func (*Point) ProtoMessage() {} -func (*Point) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0} } +func (*Point) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0} } func (m *Point) GetInterval() *TimeInterval { if m != nil { @@ -90,7 +90,7 @@ type TimeSeries struct { func (m *TimeSeries) Reset() { *m = TimeSeries{} } func (m *TimeSeries) String() string { return proto.CompactTextString(m) } func (*TimeSeries) ProtoMessage() {} -func (*TimeSeries) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{1} } +func (*TimeSeries) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{1} } func (m *TimeSeries) GetMetric() *google_api5.Metric { if m != nil { @@ -132,9 +132,9 @@ func init() { proto.RegisterType((*TimeSeries)(nil), "google.monitoring.v3.TimeSeries") } -func init() { proto.RegisterFile("google/monitoring/v3/metric.proto", fileDescriptor3) } +func init() { proto.RegisterFile("google/monitoring/v3/metric.proto", fileDescriptor5) } -var fileDescriptor3 = []byte{ +var fileDescriptor5 = []byte{ // 396 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0xc1, 0x4a, 0xeb, 0x40, 0x14, 0x86, 0x49, 0x7b, 0x5b, 0x7a, 0x27, 0x70, 0x17, 0xc3, 0x05, 0x43, 0x45, 0x88, 0x15, 0xb4, diff --git a/google.golang.org/genproto/googleapis/monitoring/v3/metric_service.pb.go b/google.golang.org/genproto/googleapis/monitoring/v3/metric_service.pb.go index 77840f1c..1673fecb 100644 --- a/google.golang.org/genproto/googleapis/monitoring/v3/metric_service.pb.go +++ b/google.golang.org/genproto/googleapis/monitoring/v3/metric_service.pb.go @@ -9,7 +9,7 @@ import math "math" import _ "google.golang.org/genproto/googleapis/api/annotations" import google_api5 "google.golang.org/genproto/googleapis/api/metric" import google_api4 "google.golang.org/genproto/googleapis/api/monitoredres" -import google_protobuf4 "github.com/golang/protobuf/ptypes/empty" +import google_protobuf5 "github.com/golang/protobuf/ptypes/empty" import google_rpc "google.golang.org/genproto/googleapis/rpc/status" import ( @@ -47,7 +47,7 @@ func (x ListTimeSeriesRequest_TimeSeriesView) String() string { return proto.EnumName(ListTimeSeriesRequest_TimeSeriesView_name, int32(x)) } func (ListTimeSeriesRequest_TimeSeriesView) EnumDescriptor() ([]byte, []int) { - return fileDescriptor4, []int{8, 0} + return fileDescriptor6, []int{8, 0} } // The `ListMonitoredResourceDescriptors` request. @@ -77,7 +77,7 @@ func (m *ListMonitoredResourceDescriptorsRequest) Reset() { func (m *ListMonitoredResourceDescriptorsRequest) String() string { return proto.CompactTextString(m) } func (*ListMonitoredResourceDescriptorsRequest) ProtoMessage() {} func (*ListMonitoredResourceDescriptorsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor4, []int{0} + return fileDescriptor6, []int{0} } func (m *ListMonitoredResourceDescriptorsRequest) GetName() string { @@ -125,7 +125,7 @@ func (m *ListMonitoredResourceDescriptorsResponse) Reset() { func (m *ListMonitoredResourceDescriptorsResponse) String() string { return proto.CompactTextString(m) } func (*ListMonitoredResourceDescriptorsResponse) ProtoMessage() {} func (*ListMonitoredResourceDescriptorsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor4, []int{1} + return fileDescriptor6, []int{1} } func (m *ListMonitoredResourceDescriptorsResponse) GetResourceDescriptors() []*google_api4.MonitoredResourceDescriptor { @@ -155,7 +155,7 @@ func (m *GetMonitoredResourceDescriptorRequest) Reset() { *m = GetMonito func (m *GetMonitoredResourceDescriptorRequest) String() string { return proto.CompactTextString(m) } func (*GetMonitoredResourceDescriptorRequest) ProtoMessage() {} func (*GetMonitoredResourceDescriptorRequest) Descriptor() ([]byte, []int) { - return fileDescriptor4, []int{2} + return fileDescriptor6, []int{2} } func (m *GetMonitoredResourceDescriptorRequest) GetName() string { @@ -190,7 +190,7 @@ type ListMetricDescriptorsRequest struct { func (m *ListMetricDescriptorsRequest) Reset() { *m = ListMetricDescriptorsRequest{} } func (m *ListMetricDescriptorsRequest) String() string { return proto.CompactTextString(m) } func (*ListMetricDescriptorsRequest) ProtoMessage() {} -func (*ListMetricDescriptorsRequest) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{3} } +func (*ListMetricDescriptorsRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{3} } func (m *ListMetricDescriptorsRequest) GetName() string { if m != nil { @@ -234,7 +234,7 @@ type ListMetricDescriptorsResponse struct { func (m *ListMetricDescriptorsResponse) Reset() { *m = ListMetricDescriptorsResponse{} } func (m *ListMetricDescriptorsResponse) String() string { return proto.CompactTextString(m) } func (*ListMetricDescriptorsResponse) ProtoMessage() {} -func (*ListMetricDescriptorsResponse) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{4} } +func (*ListMetricDescriptorsResponse) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{4} } func (m *ListMetricDescriptorsResponse) GetMetricDescriptors() []*google_api5.MetricDescriptor { if m != nil { @@ -262,7 +262,7 @@ type GetMetricDescriptorRequest struct { func (m *GetMetricDescriptorRequest) Reset() { *m = GetMetricDescriptorRequest{} } func (m *GetMetricDescriptorRequest) String() string { return proto.CompactTextString(m) } func (*GetMetricDescriptorRequest) ProtoMessage() {} -func (*GetMetricDescriptorRequest) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{5} } +func (*GetMetricDescriptorRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{5} } func (m *GetMetricDescriptorRequest) GetName() string { if m != nil { @@ -284,7 +284,7 @@ type CreateMetricDescriptorRequest struct { func (m *CreateMetricDescriptorRequest) Reset() { *m = CreateMetricDescriptorRequest{} } func (m *CreateMetricDescriptorRequest) String() string { return proto.CompactTextString(m) } func (*CreateMetricDescriptorRequest) ProtoMessage() {} -func (*CreateMetricDescriptorRequest) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{6} } +func (*CreateMetricDescriptorRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{6} } func (m *CreateMetricDescriptorRequest) GetName() string { if m != nil { @@ -312,7 +312,7 @@ type DeleteMetricDescriptorRequest struct { func (m *DeleteMetricDescriptorRequest) Reset() { *m = DeleteMetricDescriptorRequest{} } func (m *DeleteMetricDescriptorRequest) String() string { return proto.CompactTextString(m) } func (*DeleteMetricDescriptorRequest) ProtoMessage() {} -func (*DeleteMetricDescriptorRequest) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{7} } +func (*DeleteMetricDescriptorRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{7} } func (m *DeleteMetricDescriptorRequest) GetName() string { if m != nil { @@ -362,7 +362,7 @@ type ListTimeSeriesRequest struct { func (m *ListTimeSeriesRequest) Reset() { *m = ListTimeSeriesRequest{} } func (m *ListTimeSeriesRequest) String() string { return proto.CompactTextString(m) } func (*ListTimeSeriesRequest) ProtoMessage() {} -func (*ListTimeSeriesRequest) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{8} } +func (*ListTimeSeriesRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{8} } func (m *ListTimeSeriesRequest) GetName() string { if m != nil { @@ -433,7 +433,7 @@ type ListTimeSeriesResponse struct { func (m *ListTimeSeriesResponse) Reset() { *m = ListTimeSeriesResponse{} } func (m *ListTimeSeriesResponse) String() string { return proto.CompactTextString(m) } func (*ListTimeSeriesResponse) ProtoMessage() {} -func (*ListTimeSeriesResponse) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{9} } +func (*ListTimeSeriesResponse) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{9} } func (m *ListTimeSeriesResponse) GetTimeSeries() []*TimeSeries { if m != nil { @@ -465,7 +465,7 @@ type CreateTimeSeriesRequest struct { func (m *CreateTimeSeriesRequest) Reset() { *m = CreateTimeSeriesRequest{} } func (m *CreateTimeSeriesRequest) String() string { return proto.CompactTextString(m) } func (*CreateTimeSeriesRequest) ProtoMessage() {} -func (*CreateTimeSeriesRequest) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{10} } +func (*CreateTimeSeriesRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{10} } func (m *CreateTimeSeriesRequest) GetName() string { if m != nil { @@ -495,7 +495,7 @@ type CreateTimeSeriesError struct { func (m *CreateTimeSeriesError) Reset() { *m = CreateTimeSeriesError{} } func (m *CreateTimeSeriesError) String() string { return proto.CompactTextString(m) } func (*CreateTimeSeriesError) ProtoMessage() {} -func (*CreateTimeSeriesError) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{11} } +func (*CreateTimeSeriesError) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{11} } func (m *CreateTimeSeriesError) GetTimeSeries() *TimeSeries { if m != nil { @@ -552,14 +552,14 @@ type MetricServiceClient interface { CreateMetricDescriptor(ctx context.Context, in *CreateMetricDescriptorRequest, opts ...grpc.CallOption) (*google_api5.MetricDescriptor, error) // Deletes a metric descriptor. Only user-created // [custom metrics](/monitoring/custom-metrics) can be deleted. - DeleteMetricDescriptor(ctx context.Context, in *DeleteMetricDescriptorRequest, opts ...grpc.CallOption) (*google_protobuf4.Empty, error) + DeleteMetricDescriptor(ctx context.Context, in *DeleteMetricDescriptorRequest, opts ...grpc.CallOption) (*google_protobuf5.Empty, error) // Lists time series that match a filter. This method does not require a Stackdriver account. ListTimeSeries(ctx context.Context, in *ListTimeSeriesRequest, opts ...grpc.CallOption) (*ListTimeSeriesResponse, error) // Creates or adds data to one or more time series. // The response is empty if all time series in the request were written. // If any time series could not be written, a corresponding failure message is // included in the error response. - CreateTimeSeries(ctx context.Context, in *CreateTimeSeriesRequest, opts ...grpc.CallOption) (*google_protobuf4.Empty, error) + CreateTimeSeries(ctx context.Context, in *CreateTimeSeriesRequest, opts ...grpc.CallOption) (*google_protobuf5.Empty, error) } type metricServiceClient struct { @@ -615,8 +615,8 @@ func (c *metricServiceClient) CreateMetricDescriptor(ctx context.Context, in *Cr return out, nil } -func (c *metricServiceClient) DeleteMetricDescriptor(ctx context.Context, in *DeleteMetricDescriptorRequest, opts ...grpc.CallOption) (*google_protobuf4.Empty, error) { - out := new(google_protobuf4.Empty) +func (c *metricServiceClient) DeleteMetricDescriptor(ctx context.Context, in *DeleteMetricDescriptorRequest, opts ...grpc.CallOption) (*google_protobuf5.Empty, error) { + out := new(google_protobuf5.Empty) err := grpc.Invoke(ctx, "/google.monitoring.v3.MetricService/DeleteMetricDescriptor", in, out, c.cc, opts...) if err != nil { return nil, err @@ -633,8 +633,8 @@ func (c *metricServiceClient) ListTimeSeries(ctx context.Context, in *ListTimeSe return out, nil } -func (c *metricServiceClient) CreateTimeSeries(ctx context.Context, in *CreateTimeSeriesRequest, opts ...grpc.CallOption) (*google_protobuf4.Empty, error) { - out := new(google_protobuf4.Empty) +func (c *metricServiceClient) CreateTimeSeries(ctx context.Context, in *CreateTimeSeriesRequest, opts ...grpc.CallOption) (*google_protobuf5.Empty, error) { + out := new(google_protobuf5.Empty) err := grpc.Invoke(ctx, "/google.monitoring.v3.MetricService/CreateTimeSeries", in, out, c.cc, opts...) if err != nil { return nil, err @@ -659,14 +659,14 @@ type MetricServiceServer interface { CreateMetricDescriptor(context.Context, *CreateMetricDescriptorRequest) (*google_api5.MetricDescriptor, error) // Deletes a metric descriptor. Only user-created // [custom metrics](/monitoring/custom-metrics) can be deleted. - DeleteMetricDescriptor(context.Context, *DeleteMetricDescriptorRequest) (*google_protobuf4.Empty, error) + DeleteMetricDescriptor(context.Context, *DeleteMetricDescriptorRequest) (*google_protobuf5.Empty, error) // Lists time series that match a filter. This method does not require a Stackdriver account. ListTimeSeries(context.Context, *ListTimeSeriesRequest) (*ListTimeSeriesResponse, error) // Creates or adds data to one or more time series. // The response is empty if all time series in the request were written. // If any time series could not be written, a corresponding failure message is // included in the error response. - CreateTimeSeries(context.Context, *CreateTimeSeriesRequest) (*google_protobuf4.Empty, error) + CreateTimeSeries(context.Context, *CreateTimeSeriesRequest) (*google_protobuf5.Empty, error) } func RegisterMetricServiceServer(s *grpc.Server, srv MetricServiceServer) { @@ -858,9 +858,9 @@ var _MetricService_serviceDesc = grpc.ServiceDesc{ Metadata: "google/monitoring/v3/metric_service.proto", } -func init() { proto.RegisterFile("google/monitoring/v3/metric_service.proto", fileDescriptor4) } +func init() { proto.RegisterFile("google/monitoring/v3/metric_service.proto", fileDescriptor6) } -var fileDescriptor4 = []byte{ +var fileDescriptor6 = []byte{ // 1011 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x57, 0x4d, 0x6f, 0x1b, 0x45, 0x18, 0x66, 0x92, 0x34, 0x1f, 0xaf, 0xd5, 0x90, 0x4e, 0x5b, 0xd7, 0x6c, 0x13, 0xe4, 0x2e, 0x2a, diff --git a/google.golang.org/genproto/googleapis/monitoring/v3/mutation_record.pb.go b/google.golang.org/genproto/googleapis/monitoring/v3/mutation_record.pb.go new file mode 100644 index 00000000..32f983d0 --- /dev/null +++ b/google.golang.org/genproto/googleapis/monitoring/v3/mutation_record.pb.go @@ -0,0 +1,67 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/monitoring/v3/mutation_record.proto + +package monitoring + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import google_protobuf2 "github.com/golang/protobuf/ptypes/timestamp" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// Describes a change made to a configuration. +type MutationRecord struct { + // When the change occurred. + MutateTime *google_protobuf2.Timestamp `protobuf:"bytes,1,opt,name=mutate_time,json=mutateTime" json:"mutate_time,omitempty"` + // The email address of the user making the change. + MutatedBy string `protobuf:"bytes,2,opt,name=mutated_by,json=mutatedBy" json:"mutated_by,omitempty"` +} + +func (m *MutationRecord) Reset() { *m = MutationRecord{} } +func (m *MutationRecord) String() string { return proto.CompactTextString(m) } +func (*MutationRecord) ProtoMessage() {} +func (*MutationRecord) Descriptor() ([]byte, []int) { return fileDescriptor7, []int{0} } + +func (m *MutationRecord) GetMutateTime() *google_protobuf2.Timestamp { + if m != nil { + return m.MutateTime + } + return nil +} + +func (m *MutationRecord) GetMutatedBy() string { + if m != nil { + return m.MutatedBy + } + return "" +} + +func init() { + proto.RegisterType((*MutationRecord)(nil), "google.monitoring.v3.MutationRecord") +} + +func init() { proto.RegisterFile("google/monitoring/v3/mutation_record.proto", fileDescriptor7) } + +var fileDescriptor7 = []byte{ + // 251 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x4a, 0xcf, 0xcf, 0x4f, + 0xcf, 0x49, 0xd5, 0xcf, 0xcd, 0xcf, 0xcb, 0x2c, 0xc9, 0x2f, 0xca, 0xcc, 0x4b, 0xd7, 0x2f, 0x33, + 0xd6, 0xcf, 0x2d, 0x2d, 0x49, 0x2c, 0xc9, 0xcc, 0xcf, 0x8b, 0x2f, 0x4a, 0x4d, 0xce, 0x2f, 0x4a, + 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x81, 0xa8, 0xd5, 0x43, 0xa8, 0xd5, 0x2b, 0x33, + 0x96, 0x92, 0x87, 0x9a, 0x00, 0x56, 0x93, 0x54, 0x9a, 0xa6, 0x5f, 0x92, 0x99, 0x9b, 0x5a, 0x5c, + 0x92, 0x98, 0x5b, 0x00, 0xd1, 0xa6, 0x94, 0xc3, 0xc5, 0xe7, 0x0b, 0x35, 0x2f, 0x08, 0x6c, 0x9c, + 0x90, 0x35, 0x17, 0x37, 0xd8, 0x86, 0xd4, 0x78, 0x90, 0x5a, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x6e, + 0x23, 0x29, 0x3d, 0xa8, 0xf1, 0x30, 0x83, 0xf4, 0x42, 0x60, 0x06, 0x05, 0x71, 0x41, 0x94, 0x83, + 0x04, 0x84, 0x64, 0xb9, 0xa0, 0xbc, 0x94, 0xf8, 0xa4, 0x4a, 0x09, 0x26, 0x05, 0x46, 0x0d, 0xce, + 0x20, 0x4e, 0xa8, 0x88, 0x53, 0xa5, 0xd3, 0x6a, 0x46, 0x2e, 0x89, 0xe4, 0xfc, 0x5c, 0x3d, 0x6c, + 0x6e, 0x75, 0x12, 0x46, 0x75, 0x48, 0x00, 0xc8, 0xa6, 0x00, 0xc6, 0x28, 0x3b, 0xa8, 0xe2, 0xf4, + 0xfc, 0x9c, 0xc4, 0xbc, 0x74, 0xbd, 0xfc, 0xa2, 0x74, 0xfd, 0xf4, 0xd4, 0x3c, 0xb0, 0x3b, 0xf4, + 0x21, 0x52, 0x89, 0x05, 0x99, 0xc5, 0xa8, 0x61, 0x64, 0x8d, 0xe0, 0xad, 0x62, 0x92, 0x72, 0x87, + 0x18, 0xe0, 0x9c, 0x93, 0x5f, 0x9a, 0xa2, 0xe7, 0x8b, 0xb0, 0x33, 0xcc, 0xf8, 0x14, 0x4c, 0x32, + 0x06, 0x2c, 0x19, 0x83, 0x90, 0x8c, 0x09, 0x33, 0x4e, 0x62, 0x03, 0x5b, 0x62, 0x0c, 0x08, 0x00, + 0x00, 0xff, 0xff, 0x95, 0xa7, 0xf3, 0xbd, 0x87, 0x01, 0x00, 0x00, +} diff --git a/google.golang.org/genproto/googleapis/monitoring/v3/notification.pb.go b/google.golang.org/genproto/googleapis/monitoring/v3/notification.pb.go new file mode 100644 index 00000000..6d0534ef --- /dev/null +++ b/google.golang.org/genproto/googleapis/monitoring/v3/notification.pb.go @@ -0,0 +1,313 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/monitoring/v3/notification.proto + +package monitoring + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_api3 "google.golang.org/genproto/googleapis/api/label" +import google_protobuf4 "github.com/golang/protobuf/ptypes/wrappers" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// Indicates whether the channel has been verified or not. It is illegal +// to specify this field in a +// [`CreateNotificationChannel`][google.monitoring.v3.NotificationChannelService.CreateNotificationChannel] +// or an +// [`UpdateNotificationChannel`][google.monitoring.v3.NotificationChannelService.UpdateNotificationChannel] +// operation. +type NotificationChannel_VerificationStatus int32 + +const ( + // Sentinel value used to indicate that the state is unknown, omitted, or + // is not applicable (as in the case of channels that neither support + // nor require verification in order to function). + NotificationChannel_VERIFICATION_STATUS_UNSPECIFIED NotificationChannel_VerificationStatus = 0 + // The channel has yet to be verified and requires verification to function. + // Note that this state also applies to the case where the verification + // process has been initiated by sending a verification code but where + // the verification code has not been submitted to complete the process. + NotificationChannel_UNVERIFIED NotificationChannel_VerificationStatus = 1 + // It has been proven that notifications can be received on this + // notification channel and that someone on the project has access + // to messages that are delivered to that channel. + NotificationChannel_VERIFIED NotificationChannel_VerificationStatus = 2 +) + +var NotificationChannel_VerificationStatus_name = map[int32]string{ + 0: "VERIFICATION_STATUS_UNSPECIFIED", + 1: "UNVERIFIED", + 2: "VERIFIED", +} +var NotificationChannel_VerificationStatus_value = map[string]int32{ + "VERIFICATION_STATUS_UNSPECIFIED": 0, + "UNVERIFIED": 1, + "VERIFIED": 2, +} + +func (x NotificationChannel_VerificationStatus) String() string { + return proto.EnumName(NotificationChannel_VerificationStatus_name, int32(x)) +} +func (NotificationChannel_VerificationStatus) EnumDescriptor() ([]byte, []int) { + return fileDescriptor8, []int{1, 0} +} + +// A description of a notification channel. The descriptor includes +// the properties of the channel and the set of labels or fields that +// must be specified to configure channels of a given type. +type NotificationChannelDescriptor struct { + // The full REST resource name for this descriptor. The syntax is: + // + // projects/[PROJECT_ID]/notificationChannelDescriptors/[TYPE] + // + // In the above, `[TYPE]` is the value of the `type` field. + Name string `protobuf:"bytes,6,opt,name=name" json:"name,omitempty"` + // The type of notification channel, such as "email", "sms", etc. + // Notification channel types are globally unique. + Type string `protobuf:"bytes,1,opt,name=type" json:"type,omitempty"` + // A human-readable name for the notification channel type. This + // form of the name is suitable for a user interface. + DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName" json:"display_name,omitempty"` + // A human-readable description of the notification channel + // type. The description may include a description of the properties + // of the channel and pointers to external documentation. + Description string `protobuf:"bytes,3,opt,name=description" json:"description,omitempty"` + // The set of labels that must be defined to identify a particular + // channel of the corresponding type. Each label includes a + // description for how that field should be populated. + Labels []*google_api3.LabelDescriptor `protobuf:"bytes,4,rep,name=labels" json:"labels,omitempty"` + // The tiers that support this notification channel; the project service tier + // must be one of the supported_tiers. + SupportedTiers []ServiceTier `protobuf:"varint,5,rep,packed,name=supported_tiers,json=supportedTiers,enum=google.monitoring.v3.ServiceTier" json:"supported_tiers,omitempty"` +} + +func (m *NotificationChannelDescriptor) Reset() { *m = NotificationChannelDescriptor{} } +func (m *NotificationChannelDescriptor) String() string { return proto.CompactTextString(m) } +func (*NotificationChannelDescriptor) ProtoMessage() {} +func (*NotificationChannelDescriptor) Descriptor() ([]byte, []int) { return fileDescriptor8, []int{0} } + +func (m *NotificationChannelDescriptor) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *NotificationChannelDescriptor) GetType() string { + if m != nil { + return m.Type + } + return "" +} + +func (m *NotificationChannelDescriptor) GetDisplayName() string { + if m != nil { + return m.DisplayName + } + return "" +} + +func (m *NotificationChannelDescriptor) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *NotificationChannelDescriptor) GetLabels() []*google_api3.LabelDescriptor { + if m != nil { + return m.Labels + } + return nil +} + +func (m *NotificationChannelDescriptor) GetSupportedTiers() []ServiceTier { + if m != nil { + return m.SupportedTiers + } + return nil +} + +// A `NotificationChannel` is a medium through which an alert is +// delivered when a policy violation is detected. Examples of channels +// include email, SMS, and third-party messaging applications. Fields +// containing sensitive information like authentication tokens or +// contact info are only partially populated on retrieval. +type NotificationChannel struct { + // The type of the notification channel. This field matches the + // value of the [NotificationChannelDescriptor.type][google.monitoring.v3.NotificationChannelDescriptor.type] field. + Type string `protobuf:"bytes,1,opt,name=type" json:"type,omitempty"` + // The full REST resource name for this channel. The syntax is: + // + // projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID] + // + // The `[CHANNEL_ID]` is automatically assigned by the server on creation. + Name string `protobuf:"bytes,6,opt,name=name" json:"name,omitempty"` + // An optional human-readable name for this notification channel. It is + // recommended that you specify a non-empty and unique name in order to + // make it easier to identify the channels in your project, though this is + // not enforced. The display name is limited to 512 Unicode characters. + DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName" json:"display_name,omitempty"` + // An optional human-readable description of this notification channel. This + // description may provide additional details, beyond the display + // name, for the channel. This may not exceeed 1024 Unicode characters. + Description string `protobuf:"bytes,4,opt,name=description" json:"description,omitempty"` + // Configuration fields that define the channel and its behavior. The + // permissible and required labels are specified in the + // [NotificationChannelDescriptor.labels][google.monitoring.v3.NotificationChannelDescriptor.labels] of the + // `NotificationChannelDescriptor` corresponding to the `type` field. + Labels map[string]string `protobuf:"bytes,5,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // User-supplied key/value data that does not need to conform to + // the corresponding `NotificationChannelDescriptor`'s schema, unlike + // the `labels` field. This field is intended to be used for organizing + // and identifying the `NotificationChannel` objects. + // + // The field can contain up to 64 entries. Each key and value is limited to + // 63 Unicode characters or 128 bytes, whichever is smaller. Labels and + // values can contain only lowercase letters, numerals, underscores, and + // dashes. Keys must begin with a letter. + UserLabels map[string]string `protobuf:"bytes,8,rep,name=user_labels,json=userLabels" json:"user_labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // Indicates whether this channel has been verified or not. On a + // [`ListNotificationChannels`][google.monitoring.v3.NotificationChannelService.ListNotificationChannels] + // or + // [`GetNotificationChannel`][google.monitoring.v3.NotificationChannelService.GetNotificationChannel] + // operation, this field is expected to be populated. + // + // If the value is `UNVERIFIED`, then it indicates that the channel is + // non-functioning (it both requires verification and lacks verification); + // otherwise, it is assumed that the channel works. + // + // If the channel is neither `VERIFIED` nor `UNVERIFIED`, it implies that + // the channel is of a type that does not require verification or that + // this specific channel has been exempted from verification because it was + // created prior to verification being required for channels of this type. + // + // This field cannot be modified using a standard + // [`UpdateNotificationChannel`][google.monitoring.v3.NotificationChannelService.UpdateNotificationChannel] + // operation. To change the value of this field, you must call + // [`VerifyNotificationChannel`][google.monitoring.v3.NotificationChannelService.VerifyNotificationChannel]. + VerificationStatus NotificationChannel_VerificationStatus `protobuf:"varint,9,opt,name=verification_status,json=verificationStatus,enum=google.monitoring.v3.NotificationChannel_VerificationStatus" json:"verification_status,omitempty"` + // Whether notifications are forwarded to the described channel. This makes + // it possible to disable delivery of notifications to a particular channel + // without removing the channel from all alerting policies that reference + // the channel. This is a more convenient approach when the change is + // temporary and you want to receive notifications from the same set + // of alerting policies on the channel at some point in the future. + Enabled *google_protobuf4.BoolValue `protobuf:"bytes,11,opt,name=enabled" json:"enabled,omitempty"` +} + +func (m *NotificationChannel) Reset() { *m = NotificationChannel{} } +func (m *NotificationChannel) String() string { return proto.CompactTextString(m) } +func (*NotificationChannel) ProtoMessage() {} +func (*NotificationChannel) Descriptor() ([]byte, []int) { return fileDescriptor8, []int{1} } + +func (m *NotificationChannel) GetType() string { + if m != nil { + return m.Type + } + return "" +} + +func (m *NotificationChannel) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *NotificationChannel) GetDisplayName() string { + if m != nil { + return m.DisplayName + } + return "" +} + +func (m *NotificationChannel) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *NotificationChannel) GetLabels() map[string]string { + if m != nil { + return m.Labels + } + return nil +} + +func (m *NotificationChannel) GetUserLabels() map[string]string { + if m != nil { + return m.UserLabels + } + return nil +} + +func (m *NotificationChannel) GetVerificationStatus() NotificationChannel_VerificationStatus { + if m != nil { + return m.VerificationStatus + } + return NotificationChannel_VERIFICATION_STATUS_UNSPECIFIED +} + +func (m *NotificationChannel) GetEnabled() *google_protobuf4.BoolValue { + if m != nil { + return m.Enabled + } + return nil +} + +func init() { + proto.RegisterType((*NotificationChannelDescriptor)(nil), "google.monitoring.v3.NotificationChannelDescriptor") + proto.RegisterType((*NotificationChannel)(nil), "google.monitoring.v3.NotificationChannel") + proto.RegisterEnum("google.monitoring.v3.NotificationChannel_VerificationStatus", NotificationChannel_VerificationStatus_name, NotificationChannel_VerificationStatus_value) +} + +func init() { proto.RegisterFile("google/monitoring/v3/notification.proto", fileDescriptor8) } + +var fileDescriptor8 = []byte{ + // 599 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0xdd, 0x6e, 0xd3, 0x30, + 0x14, 0xc7, 0x49, 0xbb, 0x8e, 0xcd, 0x99, 0xba, 0xe1, 0x4d, 0x28, 0x0a, 0x5f, 0xdd, 0xb8, 0xa0, + 0x57, 0x89, 0xd4, 0x82, 0xc4, 0xf8, 0x92, 0xb6, 0xae, 0x43, 0x45, 0xac, 0x4c, 0xfd, 0x42, 0x9a, + 0x26, 0x55, 0x6e, 0xeb, 0x05, 0x8b, 0xc4, 0x8e, 0x6c, 0x27, 0xa8, 0x0f, 0xc1, 0x63, 0x70, 0x01, + 0x8f, 0xc2, 0x53, 0xa1, 0x38, 0x6e, 0x12, 0xb6, 0x48, 0x8c, 0x3b, 0x9f, 0x73, 0xfe, 0xe7, 0x7f, + 0xce, 0xf9, 0x35, 0x2a, 0x78, 0xe6, 0x31, 0xe6, 0xf9, 0xd8, 0x0d, 0x18, 0x25, 0x92, 0x71, 0x42, + 0x3d, 0x37, 0x6e, 0xbb, 0x94, 0x49, 0x72, 0x45, 0xe6, 0x48, 0x12, 0x46, 0x9d, 0x90, 0x33, 0xc9, + 0xe0, 0x5e, 0x2a, 0x74, 0x72, 0xa1, 0x13, 0xb7, 0xed, 0x87, 0xba, 0x1d, 0x85, 0xc4, 0x45, 0x94, + 0x32, 0xa9, 0x5a, 0x44, 0xda, 0x63, 0xdf, 0x2f, 0x54, 0x7d, 0x34, 0xc3, 0xbe, 0xce, 0xef, 0x97, + 0x0e, 0x9d, 0xb3, 0x20, 0x58, 0x8d, 0xb3, 0x1f, 0x6b, 0x89, 0x8a, 0x66, 0xd1, 0x95, 0xfb, 0x8d, + 0xa3, 0x30, 0xc4, 0x5c, 0x5b, 0x1f, 0x7c, 0xaf, 0x80, 0x47, 0xfd, 0xc2, 0x96, 0x9d, 0x2f, 0x88, + 0x52, 0xec, 0x9f, 0x60, 0x31, 0xe7, 0x24, 0x94, 0x8c, 0x43, 0x08, 0xd6, 0x28, 0x0a, 0xb0, 0xb5, + 0xde, 0x30, 0x9a, 0x9b, 0x03, 0xf5, 0x4e, 0x72, 0x72, 0x19, 0x62, 0xcb, 0x48, 0x73, 0xc9, 0x1b, + 0xee, 0x83, 0xad, 0x05, 0x11, 0xa1, 0x8f, 0x96, 0x53, 0xa5, 0xaf, 0xa8, 0x9a, 0xa9, 0x73, 0xfd, + 0xa4, 0xad, 0x01, 0xcc, 0x85, 0x36, 0x26, 0x8c, 0x5a, 0x55, 0xad, 0xc8, 0x53, 0xb0, 0x0d, 0xd6, + 0xd5, 0x81, 0xc2, 0x5a, 0x6b, 0x54, 0x9b, 0x66, 0xeb, 0x81, 0xa3, 0x71, 0xa1, 0x90, 0x38, 0x1f, + 0x93, 0x4a, 0xbe, 0xd9, 0x40, 0x4b, 0xe1, 0x07, 0xb0, 0x2d, 0xa2, 0x30, 0x64, 0x5c, 0xe2, 0xc5, + 0x54, 0x12, 0xcc, 0x85, 0x55, 0x6b, 0x54, 0x9b, 0xf5, 0xd6, 0xbe, 0x53, 0x06, 0xdb, 0x19, 0x62, + 0x1e, 0x93, 0x39, 0x1e, 0x11, 0xcc, 0x07, 0xf5, 0xac, 0x33, 0x09, 0xc5, 0xc1, 0x8f, 0x1a, 0xd8, + 0x2d, 0xe1, 0x51, 0x7a, 0x71, 0x19, 0x99, 0xeb, 0x14, 0xaa, 0xff, 0xa4, 0xb0, 0x76, 0x93, 0xc2, + 0x59, 0x46, 0xa1, 0xa6, 0x28, 0xbc, 0x28, 0xbf, 0xa3, 0x64, 0xcf, 0x94, 0x91, 0xe8, 0x52, 0xc9, + 0x97, 0x19, 0x9f, 0x0b, 0x60, 0x46, 0x02, 0xf3, 0xa9, 0xf6, 0xdc, 0x50, 0x9e, 0x87, 0xb7, 0xf7, + 0x1c, 0x0b, 0xcc, 0x8b, 0xbe, 0x20, 0xca, 0x12, 0x30, 0x00, 0xbb, 0x31, 0xe6, 0x59, 0xcb, 0x54, + 0x48, 0x24, 0x23, 0x61, 0x6d, 0x36, 0x8c, 0x66, 0xbd, 0xf5, 0xe6, 0xf6, 0x33, 0x26, 0x05, 0x93, + 0xa1, 0xf2, 0x18, 0xc0, 0xf8, 0x46, 0x0e, 0x3e, 0x07, 0x77, 0x31, 0x45, 0x33, 0x1f, 0x2f, 0x2c, + 0xb3, 0x61, 0x34, 0xcd, 0x96, 0xbd, 0x1a, 0xb1, 0xfa, 0xc0, 0x9d, 0x63, 0xc6, 0xfc, 0x09, 0xf2, + 0x23, 0x3c, 0x58, 0x49, 0xed, 0x43, 0x60, 0x16, 0xf6, 0x87, 0x3b, 0xa0, 0xfa, 0x15, 0x2f, 0xf5, + 0x4f, 0x99, 0x3c, 0xe1, 0x1e, 0xa8, 0xc5, 0x49, 0x8b, 0xfe, 0x68, 0xd3, 0xe0, 0x55, 0xe5, 0xa5, + 0x61, 0xbf, 0x05, 0xdb, 0xd7, 0xce, 0xff, 0x9f, 0xf6, 0x83, 0xcf, 0x00, 0xde, 0xbc, 0x0c, 0x3e, + 0x05, 0x4f, 0x26, 0xdd, 0x41, 0xef, 0xb4, 0xd7, 0x39, 0x1a, 0xf5, 0x3e, 0xf5, 0xa7, 0xc3, 0xd1, + 0xd1, 0x68, 0x3c, 0x9c, 0x8e, 0xfb, 0xc3, 0xf3, 0x6e, 0xa7, 0x77, 0xda, 0xeb, 0x9e, 0xec, 0xdc, + 0x81, 0x75, 0x00, 0xc6, 0xfd, 0x54, 0xd6, 0x3d, 0xd9, 0x31, 0xe0, 0x16, 0xd8, 0xc8, 0xa2, 0xca, + 0xf1, 0x4f, 0x03, 0x58, 0x73, 0x16, 0x94, 0x02, 0x3e, 0xbe, 0x57, 0x24, 0x7c, 0x9e, 0x80, 0x39, + 0x37, 0x2e, 0xde, 0x69, 0xa9, 0xc7, 0x7c, 0x44, 0x3d, 0x87, 0x71, 0xcf, 0xf5, 0x30, 0x55, 0xd8, + 0xdc, 0xb4, 0x84, 0x42, 0x22, 0xfe, 0xfe, 0x2f, 0x79, 0x9d, 0x47, 0xbf, 0x2a, 0xf6, 0xfb, 0xd4, + 0xa0, 0xe3, 0xb3, 0x68, 0xe1, 0x9c, 0xe5, 0x13, 0x27, 0xed, 0xdf, 0xab, 0xe2, 0xa5, 0x2a, 0x5e, + 0xe6, 0xc5, 0xcb, 0x49, 0x7b, 0xb6, 0xae, 0x86, 0xb4, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xdf, + 0xb9, 0x3f, 0x8b, 0x24, 0x05, 0x00, 0x00, +} diff --git a/google.golang.org/genproto/googleapis/monitoring/v3/notification_service.pb.go b/google.golang.org/genproto/googleapis/monitoring/v3/notification_service.pb.go new file mode 100644 index 00000000..ea5cf925 --- /dev/null +++ b/google.golang.org/genproto/googleapis/monitoring/v3/notification_service.pb.go @@ -0,0 +1,1035 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/monitoring/v3/notification_service.proto + +package monitoring + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_protobuf5 "github.com/golang/protobuf/ptypes/empty" +import google_protobuf6 "google.golang.org/genproto/protobuf/field_mask" +import google_protobuf2 "github.com/golang/protobuf/ptypes/timestamp" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// The `ListNotificationChannelDescriptors` request. +type ListNotificationChannelDescriptorsRequest struct { + // The REST resource name of the parent from which to retrieve + // the notification channel descriptors. The expected syntax is: + // + // projects/[PROJECT_ID] + // + // Note that this names the parent container in which to look for the + // descriptors; to retrieve a single descriptor by name, use the + // [GetNotificationChannelDescriptor][google.monitoring.v3.NotificationChannelService.GetNotificationChannelDescriptor] + // operation, instead. + Name string `protobuf:"bytes,4,opt,name=name" json:"name,omitempty"` + // The maximum number of results to return in a single response. If + // not set to a positive number, a reasonable value will be chosen by the + // service. + PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize" json:"page_size,omitempty"` + // If non-empty, `page_token` must contain a value returned as the + // `next_page_token` in a previous response to request the next set + // of results. + PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken" json:"page_token,omitempty"` +} + +func (m *ListNotificationChannelDescriptorsRequest) Reset() { + *m = ListNotificationChannelDescriptorsRequest{} +} +func (m *ListNotificationChannelDescriptorsRequest) String() string { return proto.CompactTextString(m) } +func (*ListNotificationChannelDescriptorsRequest) ProtoMessage() {} +func (*ListNotificationChannelDescriptorsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor9, []int{0} +} + +func (m *ListNotificationChannelDescriptorsRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *ListNotificationChannelDescriptorsRequest) GetPageSize() int32 { + if m != nil { + return m.PageSize + } + return 0 +} + +func (m *ListNotificationChannelDescriptorsRequest) GetPageToken() string { + if m != nil { + return m.PageToken + } + return "" +} + +// The `ListNotificationChannelDescriptors` response. +type ListNotificationChannelDescriptorsResponse struct { + // The monitored resource descriptors supported for the specified + // project, optionally filtered. + ChannelDescriptors []*NotificationChannelDescriptor `protobuf:"bytes,1,rep,name=channel_descriptors,json=channelDescriptors" json:"channel_descriptors,omitempty"` + // If not empty, indicates that there may be more results that match + // the request. Use the value in the `page_token` field in a + // subsequent request to fetch the next set of results. If empty, + // all results have been returned. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken" json:"next_page_token,omitempty"` +} + +func (m *ListNotificationChannelDescriptorsResponse) Reset() { + *m = ListNotificationChannelDescriptorsResponse{} +} +func (m *ListNotificationChannelDescriptorsResponse) String() string { + return proto.CompactTextString(m) +} +func (*ListNotificationChannelDescriptorsResponse) ProtoMessage() {} +func (*ListNotificationChannelDescriptorsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor9, []int{1} +} + +func (m *ListNotificationChannelDescriptorsResponse) GetChannelDescriptors() []*NotificationChannelDescriptor { + if m != nil { + return m.ChannelDescriptors + } + return nil +} + +func (m *ListNotificationChannelDescriptorsResponse) GetNextPageToken() string { + if m != nil { + return m.NextPageToken + } + return "" +} + +// The `GetNotificationChannelDescriptor` response. +type GetNotificationChannelDescriptorRequest struct { + // The channel type for which to execute the request. The format is + // `projects/[PROJECT_ID]/notificationChannelDescriptors/{channel_type}`. + Name string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"` +} + +func (m *GetNotificationChannelDescriptorRequest) Reset() { + *m = GetNotificationChannelDescriptorRequest{} +} +func (m *GetNotificationChannelDescriptorRequest) String() string { return proto.CompactTextString(m) } +func (*GetNotificationChannelDescriptorRequest) ProtoMessage() {} +func (*GetNotificationChannelDescriptorRequest) Descriptor() ([]byte, []int) { + return fileDescriptor9, []int{2} +} + +func (m *GetNotificationChannelDescriptorRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// The `CreateNotificationChannel` request. +type CreateNotificationChannelRequest struct { + // The project on which to execute the request. The format is: + // + // projects/[PROJECT_ID] + // + // Note that this names the container into which the channel will be + // written. This does not name the newly created channel. The resulting + // channel's name will have a normalized version of this field as a prefix, + // but will add `/notificationChannels/[CHANNEL_ID]` to identify the channel. + Name string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"` + // The definition of the `NotificationChannel` to create. + NotificationChannel *NotificationChannel `protobuf:"bytes,2,opt,name=notification_channel,json=notificationChannel" json:"notification_channel,omitempty"` +} + +func (m *CreateNotificationChannelRequest) Reset() { *m = CreateNotificationChannelRequest{} } +func (m *CreateNotificationChannelRequest) String() string { return proto.CompactTextString(m) } +func (*CreateNotificationChannelRequest) ProtoMessage() {} +func (*CreateNotificationChannelRequest) Descriptor() ([]byte, []int) { + return fileDescriptor9, []int{3} +} + +func (m *CreateNotificationChannelRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *CreateNotificationChannelRequest) GetNotificationChannel() *NotificationChannel { + if m != nil { + return m.NotificationChannel + } + return nil +} + +// The `ListNotificationChannels` request. +type ListNotificationChannelsRequest struct { + // The project on which to execute the request. The format is + // `projects/[PROJECT_ID]`. That is, this names the container + // in which to look for the notification channels; it does not name a + // specific channel. To query a specific channel by REST resource name, use + // the + // [`GetNotificationChannel`][google.monitoring.v3.NotificationChannelService.GetNotificationChannel] operation. + Name string `protobuf:"bytes,5,opt,name=name" json:"name,omitempty"` + // If provided, this field specifies the criteria that must be met by + // notification channels to be included in the response. + // + // For more details, see [sorting and + // filtering](/monitoring/api/v3/sorting-and-filtering). + Filter string `protobuf:"bytes,6,opt,name=filter" json:"filter,omitempty"` + // A comma-separated list of fields by which to sort the result. Supports + // the same set of fields as in `filter`. Entries can be prefixed with + // a minus sign to sort in descending rather than ascending order. + // + // For more details, see [sorting and + // filtering](/monitoring/api/v3/sorting-and-filtering). + OrderBy string `protobuf:"bytes,7,opt,name=order_by,json=orderBy" json:"order_by,omitempty"` + // The maximum number of results to return in a single response. If + // not set to a positive number, a reasonable value will be chosen by the + // service. + PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize" json:"page_size,omitempty"` + // If non-empty, `page_token` must contain a value returned as the + // `next_page_token` in a previous response to request the next set + // of results. + PageToken string `protobuf:"bytes,4,opt,name=page_token,json=pageToken" json:"page_token,omitempty"` +} + +func (m *ListNotificationChannelsRequest) Reset() { *m = ListNotificationChannelsRequest{} } +func (m *ListNotificationChannelsRequest) String() string { return proto.CompactTextString(m) } +func (*ListNotificationChannelsRequest) ProtoMessage() {} +func (*ListNotificationChannelsRequest) Descriptor() ([]byte, []int) { return fileDescriptor9, []int{4} } + +func (m *ListNotificationChannelsRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *ListNotificationChannelsRequest) GetFilter() string { + if m != nil { + return m.Filter + } + return "" +} + +func (m *ListNotificationChannelsRequest) GetOrderBy() string { + if m != nil { + return m.OrderBy + } + return "" +} + +func (m *ListNotificationChannelsRequest) GetPageSize() int32 { + if m != nil { + return m.PageSize + } + return 0 +} + +func (m *ListNotificationChannelsRequest) GetPageToken() string { + if m != nil { + return m.PageToken + } + return "" +} + +// The `ListNotificationChannels` response. +type ListNotificationChannelsResponse struct { + // The notification channels defined for the specified project. + NotificationChannels []*NotificationChannel `protobuf:"bytes,3,rep,name=notification_channels,json=notificationChannels" json:"notification_channels,omitempty"` + // If not empty, indicates that there may be more results that match + // the request. Use the value in the `page_token` field in a + // subsequent request to fetch the next set of results. If empty, + // all results have been returned. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken" json:"next_page_token,omitempty"` +} + +func (m *ListNotificationChannelsResponse) Reset() { *m = ListNotificationChannelsResponse{} } +func (m *ListNotificationChannelsResponse) String() string { return proto.CompactTextString(m) } +func (*ListNotificationChannelsResponse) ProtoMessage() {} +func (*ListNotificationChannelsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor9, []int{5} +} + +func (m *ListNotificationChannelsResponse) GetNotificationChannels() []*NotificationChannel { + if m != nil { + return m.NotificationChannels + } + return nil +} + +func (m *ListNotificationChannelsResponse) GetNextPageToken() string { + if m != nil { + return m.NextPageToken + } + return "" +} + +// The `GetNotificationChannel` request. +type GetNotificationChannelRequest struct { + // The channel for which to execute the request. The format is + // `projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID]`. + Name string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"` +} + +func (m *GetNotificationChannelRequest) Reset() { *m = GetNotificationChannelRequest{} } +func (m *GetNotificationChannelRequest) String() string { return proto.CompactTextString(m) } +func (*GetNotificationChannelRequest) ProtoMessage() {} +func (*GetNotificationChannelRequest) Descriptor() ([]byte, []int) { return fileDescriptor9, []int{6} } + +func (m *GetNotificationChannelRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// The `UpdateNotificationChannel` request. +type UpdateNotificationChannelRequest struct { + // The fields to update. + UpdateMask *google_protobuf6.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` + // A description of the changes to be applied to the specified + // notification channel. The description must provide a definition for + // fields to be updated; the names of these fields should also be + // included in the `update_mask`. + NotificationChannel *NotificationChannel `protobuf:"bytes,3,opt,name=notification_channel,json=notificationChannel" json:"notification_channel,omitempty"` +} + +func (m *UpdateNotificationChannelRequest) Reset() { *m = UpdateNotificationChannelRequest{} } +func (m *UpdateNotificationChannelRequest) String() string { return proto.CompactTextString(m) } +func (*UpdateNotificationChannelRequest) ProtoMessage() {} +func (*UpdateNotificationChannelRequest) Descriptor() ([]byte, []int) { + return fileDescriptor9, []int{7} +} + +func (m *UpdateNotificationChannelRequest) GetUpdateMask() *google_protobuf6.FieldMask { + if m != nil { + return m.UpdateMask + } + return nil +} + +func (m *UpdateNotificationChannelRequest) GetNotificationChannel() *NotificationChannel { + if m != nil { + return m.NotificationChannel + } + return nil +} + +// The `DeleteNotificationChannel` request. +type DeleteNotificationChannelRequest struct { + // The channel for which to execute the request. The format is + // `projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID]`. + Name string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"` + // If true, the notification channel will be deleted regardless of its + // use in alert policies (the policies will be updated to remove the + // channel). If false, channels that are still referenced by an existing + // alerting policy will fail to be deleted in a delete operation. + Force bool `protobuf:"varint,5,opt,name=force" json:"force,omitempty"` +} + +func (m *DeleteNotificationChannelRequest) Reset() { *m = DeleteNotificationChannelRequest{} } +func (m *DeleteNotificationChannelRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteNotificationChannelRequest) ProtoMessage() {} +func (*DeleteNotificationChannelRequest) Descriptor() ([]byte, []int) { + return fileDescriptor9, []int{8} +} + +func (m *DeleteNotificationChannelRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *DeleteNotificationChannelRequest) GetForce() bool { + if m != nil { + return m.Force + } + return false +} + +// The `SendNotificationChannelVerificationCode` request. +type SendNotificationChannelVerificationCodeRequest struct { + // The notification channel to which to send a verification code. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *SendNotificationChannelVerificationCodeRequest) Reset() { + *m = SendNotificationChannelVerificationCodeRequest{} +} +func (m *SendNotificationChannelVerificationCodeRequest) String() string { + return proto.CompactTextString(m) +} +func (*SendNotificationChannelVerificationCodeRequest) ProtoMessage() {} +func (*SendNotificationChannelVerificationCodeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor9, []int{9} +} + +func (m *SendNotificationChannelVerificationCodeRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// The `GetNotificationChannelVerificationCode` request. +type GetNotificationChannelVerificationCodeRequest struct { + // The notification channel for which a verification code is to be generated + // and retrieved. This must name a channel that is already verified; if + // the specified channel is not verified, the request will fail. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The desired expiration time. If specified, the API will guarantee that + // the returned code will not be valid after the specified timestamp; + // however, the API cannot guarantee that the returned code will be + // valid for at least as long as the requested time (the API puts an upper + // bound on the amount of time for which a code may be valid). If omitted, + // a default expiration will be used, which may be less than the max + // permissible expiration (so specifying an expiration may extend the + // code's lifetime over omitting an expiration, even though the API does + // impose an upper limit on the maximum expiration that is permitted). + ExpireTime *google_protobuf2.Timestamp `protobuf:"bytes,2,opt,name=expire_time,json=expireTime" json:"expire_time,omitempty"` +} + +func (m *GetNotificationChannelVerificationCodeRequest) Reset() { + *m = GetNotificationChannelVerificationCodeRequest{} +} +func (m *GetNotificationChannelVerificationCodeRequest) String() string { + return proto.CompactTextString(m) +} +func (*GetNotificationChannelVerificationCodeRequest) ProtoMessage() {} +func (*GetNotificationChannelVerificationCodeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor9, []int{10} +} + +func (m *GetNotificationChannelVerificationCodeRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *GetNotificationChannelVerificationCodeRequest) GetExpireTime() *google_protobuf2.Timestamp { + if m != nil { + return m.ExpireTime + } + return nil +} + +// The `GetNotificationChannelVerificationCode` request. +type GetNotificationChannelVerificationCodeResponse struct { + // The verification code, which may be used to verify other channels + // that have an equivalent identity (i.e. other channels of the same + // type with the same fingerprint such as other email channels with + // the same email address or other sms channels with the same number). + Code string `protobuf:"bytes,1,opt,name=code" json:"code,omitempty"` + // The expiration time associated with the code that was returned. If + // an expiration was provided in the request, this is the minimum of the + // requested expiration in the request and the max permitted expiration. + ExpireTime *google_protobuf2.Timestamp `protobuf:"bytes,2,opt,name=expire_time,json=expireTime" json:"expire_time,omitempty"` +} + +func (m *GetNotificationChannelVerificationCodeResponse) Reset() { + *m = GetNotificationChannelVerificationCodeResponse{} +} +func (m *GetNotificationChannelVerificationCodeResponse) String() string { + return proto.CompactTextString(m) +} +func (*GetNotificationChannelVerificationCodeResponse) ProtoMessage() {} +func (*GetNotificationChannelVerificationCodeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor9, []int{11} +} + +func (m *GetNotificationChannelVerificationCodeResponse) GetCode() string { + if m != nil { + return m.Code + } + return "" +} + +func (m *GetNotificationChannelVerificationCodeResponse) GetExpireTime() *google_protobuf2.Timestamp { + if m != nil { + return m.ExpireTime + } + return nil +} + +// The `VerifyNotificationChannel` request. +type VerifyNotificationChannelRequest struct { + // The notification channel to verify. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The verification code that was delivered to the channel as + // a result of invoking the `SendNotificationChannelVerificationCode` API + // method or that was retrieved from a verified channel via + // `GetNotificationChannelVerificationCode`. For example, one might have + // "G-123456" or "TKNZGhhd2EyN3I1MnRnMjRv" (in general, one is only + // guaranteed that the code is valid UTF-8; one should not + // make any assumptions regarding the structure or format of the code). + Code string `protobuf:"bytes,2,opt,name=code" json:"code,omitempty"` +} + +func (m *VerifyNotificationChannelRequest) Reset() { *m = VerifyNotificationChannelRequest{} } +func (m *VerifyNotificationChannelRequest) String() string { return proto.CompactTextString(m) } +func (*VerifyNotificationChannelRequest) ProtoMessage() {} +func (*VerifyNotificationChannelRequest) Descriptor() ([]byte, []int) { + return fileDescriptor9, []int{12} +} + +func (m *VerifyNotificationChannelRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *VerifyNotificationChannelRequest) GetCode() string { + if m != nil { + return m.Code + } + return "" +} + +func init() { + proto.RegisterType((*ListNotificationChannelDescriptorsRequest)(nil), "google.monitoring.v3.ListNotificationChannelDescriptorsRequest") + proto.RegisterType((*ListNotificationChannelDescriptorsResponse)(nil), "google.monitoring.v3.ListNotificationChannelDescriptorsResponse") + proto.RegisterType((*GetNotificationChannelDescriptorRequest)(nil), "google.monitoring.v3.GetNotificationChannelDescriptorRequest") + proto.RegisterType((*CreateNotificationChannelRequest)(nil), "google.monitoring.v3.CreateNotificationChannelRequest") + proto.RegisterType((*ListNotificationChannelsRequest)(nil), "google.monitoring.v3.ListNotificationChannelsRequest") + proto.RegisterType((*ListNotificationChannelsResponse)(nil), "google.monitoring.v3.ListNotificationChannelsResponse") + proto.RegisterType((*GetNotificationChannelRequest)(nil), "google.monitoring.v3.GetNotificationChannelRequest") + proto.RegisterType((*UpdateNotificationChannelRequest)(nil), "google.monitoring.v3.UpdateNotificationChannelRequest") + proto.RegisterType((*DeleteNotificationChannelRequest)(nil), "google.monitoring.v3.DeleteNotificationChannelRequest") + proto.RegisterType((*SendNotificationChannelVerificationCodeRequest)(nil), "google.monitoring.v3.SendNotificationChannelVerificationCodeRequest") + proto.RegisterType((*GetNotificationChannelVerificationCodeRequest)(nil), "google.monitoring.v3.GetNotificationChannelVerificationCodeRequest") + proto.RegisterType((*GetNotificationChannelVerificationCodeResponse)(nil), "google.monitoring.v3.GetNotificationChannelVerificationCodeResponse") + proto.RegisterType((*VerifyNotificationChannelRequest)(nil), "google.monitoring.v3.VerifyNotificationChannelRequest") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for NotificationChannelService service + +type NotificationChannelServiceClient interface { + // Lists the descriptors for supported channel types. The use of descriptors + // makes it possible for new channel types to be dynamically added. + ListNotificationChannelDescriptors(ctx context.Context, in *ListNotificationChannelDescriptorsRequest, opts ...grpc.CallOption) (*ListNotificationChannelDescriptorsResponse, error) + // Gets a single channel descriptor. The descriptor indicates which fields + // are expected / permitted for a notification channel of the given type. + GetNotificationChannelDescriptor(ctx context.Context, in *GetNotificationChannelDescriptorRequest, opts ...grpc.CallOption) (*NotificationChannelDescriptor, error) + // Lists the notification channels that have been created for the project. + ListNotificationChannels(ctx context.Context, in *ListNotificationChannelsRequest, opts ...grpc.CallOption) (*ListNotificationChannelsResponse, error) + // Gets a single notification channel. The channel includes the relevant + // configuration details with which the channel was created. However, the + // response may truncate or omit passwords, API keys, or other private key + // matter and thus the response may not be 100% identical to the information + // that was supplied in the call to the create method. + GetNotificationChannel(ctx context.Context, in *GetNotificationChannelRequest, opts ...grpc.CallOption) (*NotificationChannel, error) + // Creates a new notification channel, representing a single notification + // endpoint such as an email address, SMS number, or pagerduty service. + CreateNotificationChannel(ctx context.Context, in *CreateNotificationChannelRequest, opts ...grpc.CallOption) (*NotificationChannel, error) + // Updates a notification channel. Fields not specified in the field mask + // remain unchanged. + UpdateNotificationChannel(ctx context.Context, in *UpdateNotificationChannelRequest, opts ...grpc.CallOption) (*NotificationChannel, error) + // Deletes a notification channel. + DeleteNotificationChannel(ctx context.Context, in *DeleteNotificationChannelRequest, opts ...grpc.CallOption) (*google_protobuf5.Empty, error) + // Causes a verification code to be delivered to the channel. The code + // can then be supplied in `VerifyNotificationChannel` to verify the channel. + SendNotificationChannelVerificationCode(ctx context.Context, in *SendNotificationChannelVerificationCodeRequest, opts ...grpc.CallOption) (*google_protobuf5.Empty, error) + // Requests a verification code for an already verified channel that can then + // be used in a call to VerifyNotificationChannel() on a different channel + // with an equivalent identity in the same or in a different project. This + // makes it possible to copy a channel between projects without requiring + // manual reverification of the channel. If the channel is not in the + // verified state, this method will fail (in other words, this may only be + // used if the SendNotificationChannelVerificationCode and + // VerifyNotificationChannel paths have already been used to put the given + // channel into the verified state). + // + // There is no guarantee that the verification codes returned by this method + // will be of a similar structure or form as the ones that are delivered + // to the channel via SendNotificationChannelVerificationCode; while + // VerifyNotificationChannel() will recognize both the codes delivered via + // SendNotificationChannelVerificationCode() and returned from + // GetNotificationChannelVerificationCode(), it is typically the case that + // the verification codes delivered via + // SendNotificationChannelVerificationCode() will be shorter and also + // have a shorter expiration (e.g. codes such as "G-123456") whereas + // GetVerificationCode() will typically return a much longer, websafe base + // 64 encoded string that has a longer expiration time. + GetNotificationChannelVerificationCode(ctx context.Context, in *GetNotificationChannelVerificationCodeRequest, opts ...grpc.CallOption) (*GetNotificationChannelVerificationCodeResponse, error) + // Verifies a `NotificationChannel` by proving receipt of the code + // delivered to the channel as a result of calling + // `SendNotificationChannelVerificationCode`. + VerifyNotificationChannel(ctx context.Context, in *VerifyNotificationChannelRequest, opts ...grpc.CallOption) (*NotificationChannel, error) +} + +type notificationChannelServiceClient struct { + cc *grpc.ClientConn +} + +func NewNotificationChannelServiceClient(cc *grpc.ClientConn) NotificationChannelServiceClient { + return ¬ificationChannelServiceClient{cc} +} + +func (c *notificationChannelServiceClient) ListNotificationChannelDescriptors(ctx context.Context, in *ListNotificationChannelDescriptorsRequest, opts ...grpc.CallOption) (*ListNotificationChannelDescriptorsResponse, error) { + out := new(ListNotificationChannelDescriptorsResponse) + err := grpc.Invoke(ctx, "/google.monitoring.v3.NotificationChannelService/ListNotificationChannelDescriptors", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notificationChannelServiceClient) GetNotificationChannelDescriptor(ctx context.Context, in *GetNotificationChannelDescriptorRequest, opts ...grpc.CallOption) (*NotificationChannelDescriptor, error) { + out := new(NotificationChannelDescriptor) + err := grpc.Invoke(ctx, "/google.monitoring.v3.NotificationChannelService/GetNotificationChannelDescriptor", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notificationChannelServiceClient) ListNotificationChannels(ctx context.Context, in *ListNotificationChannelsRequest, opts ...grpc.CallOption) (*ListNotificationChannelsResponse, error) { + out := new(ListNotificationChannelsResponse) + err := grpc.Invoke(ctx, "/google.monitoring.v3.NotificationChannelService/ListNotificationChannels", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notificationChannelServiceClient) GetNotificationChannel(ctx context.Context, in *GetNotificationChannelRequest, opts ...grpc.CallOption) (*NotificationChannel, error) { + out := new(NotificationChannel) + err := grpc.Invoke(ctx, "/google.monitoring.v3.NotificationChannelService/GetNotificationChannel", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notificationChannelServiceClient) CreateNotificationChannel(ctx context.Context, in *CreateNotificationChannelRequest, opts ...grpc.CallOption) (*NotificationChannel, error) { + out := new(NotificationChannel) + err := grpc.Invoke(ctx, "/google.monitoring.v3.NotificationChannelService/CreateNotificationChannel", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notificationChannelServiceClient) UpdateNotificationChannel(ctx context.Context, in *UpdateNotificationChannelRequest, opts ...grpc.CallOption) (*NotificationChannel, error) { + out := new(NotificationChannel) + err := grpc.Invoke(ctx, "/google.monitoring.v3.NotificationChannelService/UpdateNotificationChannel", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notificationChannelServiceClient) DeleteNotificationChannel(ctx context.Context, in *DeleteNotificationChannelRequest, opts ...grpc.CallOption) (*google_protobuf5.Empty, error) { + out := new(google_protobuf5.Empty) + err := grpc.Invoke(ctx, "/google.monitoring.v3.NotificationChannelService/DeleteNotificationChannel", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notificationChannelServiceClient) SendNotificationChannelVerificationCode(ctx context.Context, in *SendNotificationChannelVerificationCodeRequest, opts ...grpc.CallOption) (*google_protobuf5.Empty, error) { + out := new(google_protobuf5.Empty) + err := grpc.Invoke(ctx, "/google.monitoring.v3.NotificationChannelService/SendNotificationChannelVerificationCode", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notificationChannelServiceClient) GetNotificationChannelVerificationCode(ctx context.Context, in *GetNotificationChannelVerificationCodeRequest, opts ...grpc.CallOption) (*GetNotificationChannelVerificationCodeResponse, error) { + out := new(GetNotificationChannelVerificationCodeResponse) + err := grpc.Invoke(ctx, "/google.monitoring.v3.NotificationChannelService/GetNotificationChannelVerificationCode", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notificationChannelServiceClient) VerifyNotificationChannel(ctx context.Context, in *VerifyNotificationChannelRequest, opts ...grpc.CallOption) (*NotificationChannel, error) { + out := new(NotificationChannel) + err := grpc.Invoke(ctx, "/google.monitoring.v3.NotificationChannelService/VerifyNotificationChannel", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for NotificationChannelService service + +type NotificationChannelServiceServer interface { + // Lists the descriptors for supported channel types. The use of descriptors + // makes it possible for new channel types to be dynamically added. + ListNotificationChannelDescriptors(context.Context, *ListNotificationChannelDescriptorsRequest) (*ListNotificationChannelDescriptorsResponse, error) + // Gets a single channel descriptor. The descriptor indicates which fields + // are expected / permitted for a notification channel of the given type. + GetNotificationChannelDescriptor(context.Context, *GetNotificationChannelDescriptorRequest) (*NotificationChannelDescriptor, error) + // Lists the notification channels that have been created for the project. + ListNotificationChannels(context.Context, *ListNotificationChannelsRequest) (*ListNotificationChannelsResponse, error) + // Gets a single notification channel. The channel includes the relevant + // configuration details with which the channel was created. However, the + // response may truncate or omit passwords, API keys, or other private key + // matter and thus the response may not be 100% identical to the information + // that was supplied in the call to the create method. + GetNotificationChannel(context.Context, *GetNotificationChannelRequest) (*NotificationChannel, error) + // Creates a new notification channel, representing a single notification + // endpoint such as an email address, SMS number, or pagerduty service. + CreateNotificationChannel(context.Context, *CreateNotificationChannelRequest) (*NotificationChannel, error) + // Updates a notification channel. Fields not specified in the field mask + // remain unchanged. + UpdateNotificationChannel(context.Context, *UpdateNotificationChannelRequest) (*NotificationChannel, error) + // Deletes a notification channel. + DeleteNotificationChannel(context.Context, *DeleteNotificationChannelRequest) (*google_protobuf5.Empty, error) + // Causes a verification code to be delivered to the channel. The code + // can then be supplied in `VerifyNotificationChannel` to verify the channel. + SendNotificationChannelVerificationCode(context.Context, *SendNotificationChannelVerificationCodeRequest) (*google_protobuf5.Empty, error) + // Requests a verification code for an already verified channel that can then + // be used in a call to VerifyNotificationChannel() on a different channel + // with an equivalent identity in the same or in a different project. This + // makes it possible to copy a channel between projects without requiring + // manual reverification of the channel. If the channel is not in the + // verified state, this method will fail (in other words, this may only be + // used if the SendNotificationChannelVerificationCode and + // VerifyNotificationChannel paths have already been used to put the given + // channel into the verified state). + // + // There is no guarantee that the verification codes returned by this method + // will be of a similar structure or form as the ones that are delivered + // to the channel via SendNotificationChannelVerificationCode; while + // VerifyNotificationChannel() will recognize both the codes delivered via + // SendNotificationChannelVerificationCode() and returned from + // GetNotificationChannelVerificationCode(), it is typically the case that + // the verification codes delivered via + // SendNotificationChannelVerificationCode() will be shorter and also + // have a shorter expiration (e.g. codes such as "G-123456") whereas + // GetVerificationCode() will typically return a much longer, websafe base + // 64 encoded string that has a longer expiration time. + GetNotificationChannelVerificationCode(context.Context, *GetNotificationChannelVerificationCodeRequest) (*GetNotificationChannelVerificationCodeResponse, error) + // Verifies a `NotificationChannel` by proving receipt of the code + // delivered to the channel as a result of calling + // `SendNotificationChannelVerificationCode`. + VerifyNotificationChannel(context.Context, *VerifyNotificationChannelRequest) (*NotificationChannel, error) +} + +func RegisterNotificationChannelServiceServer(s *grpc.Server, srv NotificationChannelServiceServer) { + s.RegisterService(&_NotificationChannelService_serviceDesc, srv) +} + +func _NotificationChannelService_ListNotificationChannelDescriptors_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListNotificationChannelDescriptorsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotificationChannelServiceServer).ListNotificationChannelDescriptors(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.NotificationChannelService/ListNotificationChannelDescriptors", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotificationChannelServiceServer).ListNotificationChannelDescriptors(ctx, req.(*ListNotificationChannelDescriptorsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NotificationChannelService_GetNotificationChannelDescriptor_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetNotificationChannelDescriptorRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotificationChannelServiceServer).GetNotificationChannelDescriptor(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.NotificationChannelService/GetNotificationChannelDescriptor", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotificationChannelServiceServer).GetNotificationChannelDescriptor(ctx, req.(*GetNotificationChannelDescriptorRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NotificationChannelService_ListNotificationChannels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListNotificationChannelsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotificationChannelServiceServer).ListNotificationChannels(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.NotificationChannelService/ListNotificationChannels", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotificationChannelServiceServer).ListNotificationChannels(ctx, req.(*ListNotificationChannelsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NotificationChannelService_GetNotificationChannel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetNotificationChannelRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotificationChannelServiceServer).GetNotificationChannel(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.NotificationChannelService/GetNotificationChannel", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotificationChannelServiceServer).GetNotificationChannel(ctx, req.(*GetNotificationChannelRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NotificationChannelService_CreateNotificationChannel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateNotificationChannelRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotificationChannelServiceServer).CreateNotificationChannel(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.NotificationChannelService/CreateNotificationChannel", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotificationChannelServiceServer).CreateNotificationChannel(ctx, req.(*CreateNotificationChannelRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NotificationChannelService_UpdateNotificationChannel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateNotificationChannelRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotificationChannelServiceServer).UpdateNotificationChannel(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.NotificationChannelService/UpdateNotificationChannel", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotificationChannelServiceServer).UpdateNotificationChannel(ctx, req.(*UpdateNotificationChannelRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NotificationChannelService_DeleteNotificationChannel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteNotificationChannelRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotificationChannelServiceServer).DeleteNotificationChannel(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.NotificationChannelService/DeleteNotificationChannel", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotificationChannelServiceServer).DeleteNotificationChannel(ctx, req.(*DeleteNotificationChannelRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NotificationChannelService_SendNotificationChannelVerificationCode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SendNotificationChannelVerificationCodeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotificationChannelServiceServer).SendNotificationChannelVerificationCode(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.NotificationChannelService/SendNotificationChannelVerificationCode", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotificationChannelServiceServer).SendNotificationChannelVerificationCode(ctx, req.(*SendNotificationChannelVerificationCodeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NotificationChannelService_GetNotificationChannelVerificationCode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetNotificationChannelVerificationCodeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotificationChannelServiceServer).GetNotificationChannelVerificationCode(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.NotificationChannelService/GetNotificationChannelVerificationCode", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotificationChannelServiceServer).GetNotificationChannelVerificationCode(ctx, req.(*GetNotificationChannelVerificationCodeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _NotificationChannelService_VerifyNotificationChannel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(VerifyNotificationChannelRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotificationChannelServiceServer).VerifyNotificationChannel(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.monitoring.v3.NotificationChannelService/VerifyNotificationChannel", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotificationChannelServiceServer).VerifyNotificationChannel(ctx, req.(*VerifyNotificationChannelRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _NotificationChannelService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "google.monitoring.v3.NotificationChannelService", + HandlerType: (*NotificationChannelServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ListNotificationChannelDescriptors", + Handler: _NotificationChannelService_ListNotificationChannelDescriptors_Handler, + }, + { + MethodName: "GetNotificationChannelDescriptor", + Handler: _NotificationChannelService_GetNotificationChannelDescriptor_Handler, + }, + { + MethodName: "ListNotificationChannels", + Handler: _NotificationChannelService_ListNotificationChannels_Handler, + }, + { + MethodName: "GetNotificationChannel", + Handler: _NotificationChannelService_GetNotificationChannel_Handler, + }, + { + MethodName: "CreateNotificationChannel", + Handler: _NotificationChannelService_CreateNotificationChannel_Handler, + }, + { + MethodName: "UpdateNotificationChannel", + Handler: _NotificationChannelService_UpdateNotificationChannel_Handler, + }, + { + MethodName: "DeleteNotificationChannel", + Handler: _NotificationChannelService_DeleteNotificationChannel_Handler, + }, + { + MethodName: "SendNotificationChannelVerificationCode", + Handler: _NotificationChannelService_SendNotificationChannelVerificationCode_Handler, + }, + { + MethodName: "GetNotificationChannelVerificationCode", + Handler: _NotificationChannelService_GetNotificationChannelVerificationCode_Handler, + }, + { + MethodName: "VerifyNotificationChannel", + Handler: _NotificationChannelService_VerifyNotificationChannel_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "google/monitoring/v3/notification_service.proto", +} + +func init() { proto.RegisterFile("google/monitoring/v3/notification_service.proto", fileDescriptor9) } + +var fileDescriptor9 = []byte{ + // 1011 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0x41, 0x6f, 0xdc, 0x44, + 0x14, 0xd6, 0xec, 0x26, 0x69, 0xfa, 0x22, 0x04, 0x9a, 0x86, 0xc8, 0xbb, 0xa5, 0xaa, 0xe5, 0x43, + 0x93, 0xae, 0x8a, 0x2d, 0xad, 0x4b, 0x84, 0x52, 0x52, 0xda, 0x64, 0xdb, 0x22, 0x48, 0x51, 0xb4, + 0x29, 0x91, 0x40, 0x11, 0x2b, 0xc7, 0x7e, 0x6b, 0x4c, 0x76, 0x67, 0x8c, 0x3d, 0x89, 0x9a, 0x56, + 0x95, 0x0a, 0x7f, 0x01, 0xfe, 0x00, 0x12, 0xa7, 0x1e, 0x10, 0x67, 0x50, 0x39, 0x23, 0xae, 0x08, + 0xae, 0x5c, 0xe0, 0x7f, 0x20, 0x8f, 0xbd, 0xd9, 0xcd, 0x66, 0xbc, 0x6b, 0x37, 0xdc, 0x3c, 0xf3, + 0xde, 0xbc, 0xf7, 0xbd, 0xef, 0x7d, 0x9e, 0x67, 0x83, 0xe5, 0x73, 0xee, 0xf7, 0xd0, 0xea, 0x73, + 0x16, 0x08, 0x1e, 0x05, 0xcc, 0xb7, 0x8e, 0x6c, 0x8b, 0x71, 0x11, 0x74, 0x03, 0xd7, 0x11, 0x01, + 0x67, 0x9d, 0x18, 0xa3, 0xa3, 0xc0, 0x45, 0x33, 0x8c, 0xb8, 0xe0, 0x74, 0x31, 0x3d, 0x60, 0x0e, + 0x0f, 0x98, 0x47, 0x76, 0xfd, 0xad, 0x2c, 0x8c, 0x13, 0x06, 0x96, 0xc3, 0x18, 0x17, 0xf2, 0x68, + 0x9c, 0x9e, 0xa9, 0x2f, 0x4f, 0x4d, 0x92, 0x39, 0x5e, 0xce, 0x1c, 0xe5, 0x6a, 0xff, 0xb0, 0x6b, + 0x61, 0x3f, 0x14, 0xc7, 0x99, 0x51, 0x1f, 0x37, 0x76, 0x03, 0xec, 0x79, 0x9d, 0xbe, 0x13, 0x1f, + 0x64, 0x1e, 0x57, 0xc7, 0x3d, 0x44, 0xd0, 0xc7, 0x58, 0x38, 0xfd, 0x30, 0x75, 0x30, 0x9e, 0xc2, + 0xf5, 0xad, 0x20, 0x16, 0x1f, 0x8f, 0x64, 0xde, 0xfc, 0xc2, 0x61, 0x0c, 0x7b, 0x2d, 0x8c, 0xdd, + 0x28, 0x08, 0x05, 0x8f, 0xe2, 0x36, 0x7e, 0x75, 0x88, 0xb1, 0xa0, 0x14, 0x66, 0x98, 0xd3, 0x47, + 0x6d, 0x46, 0x27, 0x2b, 0x17, 0xdb, 0xf2, 0x99, 0x5e, 0x86, 0x8b, 0xa1, 0xe3, 0x63, 0x27, 0x0e, + 0x9e, 0xa0, 0x56, 0xd1, 0xc9, 0xca, 0x6c, 0x7b, 0x3e, 0xd9, 0xd8, 0x09, 0x9e, 0x20, 0xbd, 0x02, + 0x20, 0x8d, 0x82, 0x1f, 0x20, 0xd3, 0xaa, 0xf2, 0x98, 0x74, 0x7f, 0x94, 0x6c, 0x18, 0x3f, 0x13, + 0x68, 0x14, 0xc9, 0x1e, 0x87, 0x9c, 0xc5, 0x48, 0x3d, 0xb8, 0xe4, 0xa6, 0xd6, 0x8e, 0x37, 0x34, + 0x6b, 0x44, 0xaf, 0xae, 0x2c, 0x34, 0x6d, 0x53, 0xd5, 0x06, 0x73, 0x62, 0xe8, 0x36, 0x75, 0xcf, + 0x64, 0xa3, 0xd7, 0xe0, 0x75, 0x86, 0x8f, 0x45, 0x67, 0x04, 0x78, 0x45, 0x02, 0x7f, 0x2d, 0xd9, + 0xde, 0x3e, 0x01, 0xbf, 0x0e, 0xcb, 0x0f, 0x70, 0x32, 0xf4, 0x71, 0xde, 0xaa, 0x43, 0xde, 0x8c, + 0xef, 0x08, 0xe8, 0x9b, 0x11, 0x3a, 0x02, 0x15, 0x21, 0x26, 0x1c, 0xa4, 0x7b, 0xb0, 0x78, 0x4a, + 0x8c, 0x59, 0x09, 0x12, 0xe4, 0x42, 0xf3, 0x7a, 0x61, 0x1a, 0xda, 0x97, 0xd8, 0xd9, 0x4d, 0xe3, + 0x07, 0x02, 0x57, 0x73, 0x5a, 0x72, 0x46, 0x06, 0xb3, 0x23, 0xa8, 0x96, 0x60, 0xae, 0x1b, 0xf4, + 0x04, 0x46, 0xda, 0x9c, 0xdc, 0xcd, 0x56, 0xb4, 0x06, 0xf3, 0x3c, 0xf2, 0x30, 0xea, 0xec, 0x1f, + 0x6b, 0x17, 0xa4, 0xe5, 0x82, 0x5c, 0x6f, 0x1c, 0x9f, 0x56, 0x4e, 0x75, 0xa2, 0x72, 0x66, 0xc6, + 0x95, 0xf3, 0x82, 0x80, 0x9e, 0x0f, 0x33, 0xd3, 0xcb, 0xe7, 0xf0, 0xa6, 0x8a, 0xa9, 0x58, 0xab, + 0x4a, 0xc5, 0x94, 0xa0, 0x6a, 0x51, 0x41, 0x55, 0x71, 0xa5, 0xd8, 0x70, 0x45, 0xad, 0x94, 0x49, + 0xfa, 0x78, 0x49, 0x40, 0xff, 0x24, 0xf4, 0x26, 0xeb, 0xe3, 0x16, 0x2c, 0x1c, 0x4a, 0x1f, 0xf9, + 0xce, 0x67, 0x12, 0xa8, 0x0f, 0xea, 0x1a, 0xbc, 0xf4, 0xe6, 0xfd, 0xe4, 0x5a, 0x78, 0xe8, 0xc4, + 0x07, 0x6d, 0x48, 0xdd, 0x93, 0xe7, 0x5c, 0x21, 0x55, 0xff, 0x17, 0x21, 0x6d, 0x81, 0xde, 0xc2, + 0x1e, 0x96, 0x96, 0xf7, 0x22, 0xcc, 0x76, 0x79, 0xe4, 0xa6, 0xea, 0x9a, 0x6f, 0xa7, 0x0b, 0xa3, + 0x05, 0xe6, 0x0e, 0x32, 0x4f, 0x11, 0x6b, 0x17, 0xa3, 0xe1, 0x16, 0xf7, 0x70, 0x3c, 0x36, 0x19, + 0xe1, 0xf4, 0x39, 0x81, 0xb7, 0xd5, 0x9d, 0x28, 0x11, 0x25, 0x21, 0x1d, 0x1f, 0x87, 0x41, 0x84, + 0x9d, 0xe4, 0x32, 0xcd, 0x25, 0xfd, 0xd1, 0xe0, 0xa6, 0x6d, 0x43, 0xea, 0x9e, 0x6c, 0x18, 0x5f, + 0x13, 0x30, 0x8b, 0x42, 0xc8, 0x64, 0x4c, 0x61, 0xc6, 0xe5, 0xde, 0x09, 0x86, 0xe4, 0xf9, 0x7c, + 0x18, 0x3e, 0x04, 0x5d, 0x26, 0x3b, 0x2e, 0xd0, 0x9a, 0xd1, 0xc2, 0x07, 0x40, 0x2a, 0x43, 0x20, + 0xcd, 0x5f, 0xde, 0x80, 0xba, 0x22, 0xcc, 0x4e, 0x3a, 0x21, 0xe9, 0xbf, 0x04, 0x8c, 0xe9, 0x37, + 0x3c, 0x7d, 0x5f, 0x2d, 0xb6, 0xc2, 0x93, 0xa9, 0x7e, 0xe7, 0xd5, 0x03, 0xa4, 0x2c, 0x1b, 0xef, + 0x7d, 0xf3, 0xc7, 0x3f, 0xdf, 0x56, 0x56, 0xe9, 0xcd, 0x64, 0x10, 0x3f, 0x4d, 0xea, 0x5d, 0x0f, + 0x23, 0xfe, 0x25, 0xba, 0x22, 0xb6, 0x1a, 0xcf, 0x2c, 0x36, 0xb9, 0x80, 0xbf, 0x08, 0xe8, 0xd3, + 0xa6, 0x01, 0x5d, 0x57, 0x83, 0x2c, 0x38, 0x45, 0xea, 0xaf, 0x32, 0xe1, 0x8c, 0xdb, 0xb2, 0xac, + 0x77, 0xe9, 0xaa, 0xaa, 0xac, 0x29, 0x55, 0x59, 0x8d, 0x67, 0xf4, 0x25, 0x01, 0x2d, 0xef, 0xa2, + 0xa5, 0xef, 0x94, 0x62, 0xfd, 0xa4, 0x59, 0xab, 0x65, 0x8f, 0x65, 0x2d, 0x6a, 0xca, 0x5a, 0x6e, + 0xd0, 0x46, 0xe1, 0x16, 0xc5, 0xf4, 0x47, 0x02, 0x4b, 0x6a, 0x82, 0xa9, 0x5d, 0xa6, 0x1d, 0x03, + 0xec, 0xc5, 0xaf, 0x45, 0xe3, 0xa6, 0x84, 0x6b, 0xd2, 0x1b, 0x45, 0xa9, 0x97, 0x84, 0xff, 0x46, + 0xa0, 0x96, 0xfb, 0x5d, 0x40, 0x73, 0xa8, 0x9b, 0xf6, 0x21, 0x51, 0x06, 0xf6, 0x07, 0x12, 0xf6, + 0x86, 0x51, 0x82, 0xe5, 0x35, 0xe5, 0x20, 0xa1, 0x7f, 0x13, 0xa8, 0xe5, 0x8e, 0xb0, 0xbc, 0x52, + 0xa6, 0xcd, 0xbc, 0x32, 0xa5, 0x74, 0x64, 0x29, 0x9f, 0x36, 0xef, 0xa6, 0xa5, 0x28, 0x30, 0x9a, + 0x05, 0xdb, 0x92, 0x53, 0xe1, 0xf7, 0x04, 0x6a, 0xb9, 0x53, 0x2e, 0xaf, 0xc2, 0x69, 0x63, 0xb1, + 0xbe, 0x74, 0xe6, 0x1e, 0xbf, 0x97, 0x7c, 0xf4, 0x0f, 0x04, 0xd5, 0x28, 0x27, 0xa8, 0x3f, 0x09, + 0x2c, 0x17, 0x9c, 0x9d, 0xb4, 0xa5, 0x46, 0x5c, 0x6e, 0xf4, 0xe6, 0xe2, 0xdf, 0x92, 0xf8, 0xef, + 0x1b, 0x77, 0xcb, 0xe0, 0x5f, 0x8b, 0x91, 0x79, 0xe3, 0x99, 0xd6, 0x48, 0x83, 0x3e, 0xaf, 0xc0, + 0xb5, 0x62, 0x93, 0x94, 0x6e, 0x96, 0x79, 0xd3, 0xf3, 0xaa, 0x6a, 0x9d, 0x2f, 0x48, 0x76, 0x87, + 0x7d, 0x24, 0x39, 0xb8, 0x67, 0xdc, 0x29, 0xc5, 0x81, 0x8f, 0x42, 0x45, 0xc1, 0xaf, 0x04, 0x6a, + 0xb9, 0x93, 0x3c, 0x4f, 0x7e, 0xd3, 0x46, 0x7f, 0x99, 0x17, 0x2c, 0x9b, 0x2e, 0x86, 0x5d, 0xaa, + 0x9a, 0x23, 0x89, 0x60, 0x8d, 0x34, 0x36, 0x7e, 0x22, 0xa0, 0xb9, 0xbc, 0xaf, 0x4c, 0xb8, 0xa1, + 0x8d, 0x66, 0xcc, 0x3e, 0x28, 0xb6, 0x13, 0x45, 0x6d, 0x93, 0xcf, 0x6e, 0x67, 0x27, 0x7c, 0xde, + 0x73, 0x98, 0x6f, 0xf2, 0xc8, 0xb7, 0x7c, 0x64, 0x52, 0x6f, 0xd9, 0xff, 0xbb, 0x13, 0x06, 0xf1, + 0xe9, 0xdf, 0xeb, 0x5b, 0xc3, 0xd5, 0x8b, 0x4a, 0xfd, 0x41, 0x1a, 0x60, 0xb3, 0xc7, 0x0f, 0x3d, + 0xf3, 0xe1, 0x30, 0xf1, 0xae, 0xfd, 0xfb, 0xc0, 0xb8, 0x27, 0x8d, 0x7b, 0x43, 0xe3, 0xde, 0xae, + 0xbd, 0x3f, 0x27, 0x93, 0xd8, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x3b, 0xf3, 0x96, 0xf5, 0x27, + 0x10, 0x00, 0x00, +} diff --git a/google.golang.org/genproto/googleapis/monitoring/v3/uptime.pb.go b/google.golang.org/genproto/googleapis/monitoring/v3/uptime.pb.go index 042cddd0..9357d352 100644 --- a/google.golang.org/genproto/googleapis/monitoring/v3/uptime.pb.go +++ b/google.golang.org/genproto/googleapis/monitoring/v3/uptime.pb.go @@ -51,7 +51,7 @@ var UptimeCheckRegion_value = map[string]int32{ func (x UptimeCheckRegion) String() string { return proto.EnumName(UptimeCheckRegion_name, int32(x)) } -func (UptimeCheckRegion) EnumDescriptor() ([]byte, []int) { return fileDescriptor5, []int{0} } +func (UptimeCheckRegion) EnumDescriptor() ([]byte, []int) { return fileDescriptor10, []int{0} } // The supported resource types that can be used as values of // group_resource.resource_type. gae_app and uptime_url are not allowed @@ -81,7 +81,7 @@ var GroupResourceType_value = map[string]int32{ func (x GroupResourceType) String() string { return proto.EnumName(GroupResourceType_name, int32(x)) } -func (GroupResourceType) EnumDescriptor() ([]byte, []int) { return fileDescriptor5, []int{1} } +func (GroupResourceType) EnumDescriptor() ([]byte, []int) { return fileDescriptor10, []int{1} } // This message configures which resources and services to monitor for // availability. @@ -136,7 +136,7 @@ type UptimeCheckConfig struct { func (m *UptimeCheckConfig) Reset() { *m = UptimeCheckConfig{} } func (m *UptimeCheckConfig) String() string { return proto.CompactTextString(m) } func (*UptimeCheckConfig) ProtoMessage() {} -func (*UptimeCheckConfig) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0} } +func (*UptimeCheckConfig) Descriptor() ([]byte, []int) { return fileDescriptor10, []int{0} } type isUptimeCheckConfig_Resource interface { isUptimeCheckConfig_Resource() @@ -391,7 +391,7 @@ func (m *UptimeCheckConfig_ResourceGroup) Reset() { *m = UptimeCheckConf func (m *UptimeCheckConfig_ResourceGroup) String() string { return proto.CompactTextString(m) } func (*UptimeCheckConfig_ResourceGroup) ProtoMessage() {} func (*UptimeCheckConfig_ResourceGroup) Descriptor() ([]byte, []int) { - return fileDescriptor5, []int{0, 0} + return fileDescriptor10, []int{0, 0} } func (m *UptimeCheckConfig_ResourceGroup) GetGroupId() string { @@ -443,7 +443,7 @@ type UptimeCheckConfig_HttpCheck struct { func (m *UptimeCheckConfig_HttpCheck) Reset() { *m = UptimeCheckConfig_HttpCheck{} } func (m *UptimeCheckConfig_HttpCheck) String() string { return proto.CompactTextString(m) } func (*UptimeCheckConfig_HttpCheck) ProtoMessage() {} -func (*UptimeCheckConfig_HttpCheck) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0, 1} } +func (*UptimeCheckConfig_HttpCheck) Descriptor() ([]byte, []int) { return fileDescriptor10, []int{0, 1} } func (m *UptimeCheckConfig_HttpCheck) GetUseSsl() bool { if m != nil { @@ -505,7 +505,7 @@ func (m *UptimeCheckConfig_HttpCheck_BasicAuthentication) String() string { } func (*UptimeCheckConfig_HttpCheck_BasicAuthentication) ProtoMessage() {} func (*UptimeCheckConfig_HttpCheck_BasicAuthentication) Descriptor() ([]byte, []int) { - return fileDescriptor5, []int{0, 1, 0} + return fileDescriptor10, []int{0, 1, 0} } func (m *UptimeCheckConfig_HttpCheck_BasicAuthentication) GetUsername() string { @@ -533,7 +533,7 @@ type UptimeCheckConfig_TcpCheck struct { func (m *UptimeCheckConfig_TcpCheck) Reset() { *m = UptimeCheckConfig_TcpCheck{} } func (m *UptimeCheckConfig_TcpCheck) String() string { return proto.CompactTextString(m) } func (*UptimeCheckConfig_TcpCheck) ProtoMessage() {} -func (*UptimeCheckConfig_TcpCheck) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0, 2} } +func (*UptimeCheckConfig_TcpCheck) Descriptor() ([]byte, []int) { return fileDescriptor10, []int{0, 2} } func (m *UptimeCheckConfig_TcpCheck) GetPort() int32 { if m != nil { @@ -554,7 +554,7 @@ func (m *UptimeCheckConfig_ContentMatcher) Reset() { *m = UptimeCheckCon func (m *UptimeCheckConfig_ContentMatcher) String() string { return proto.CompactTextString(m) } func (*UptimeCheckConfig_ContentMatcher) ProtoMessage() {} func (*UptimeCheckConfig_ContentMatcher) Descriptor() ([]byte, []int) { - return fileDescriptor5, []int{0, 3} + return fileDescriptor10, []int{0, 3} } func (m *UptimeCheckConfig_ContentMatcher) GetContent() string { @@ -583,7 +583,7 @@ func (m *UptimeCheckConfig_InternalChecker) Reset() { *m = UptimeCheckCo func (m *UptimeCheckConfig_InternalChecker) String() string { return proto.CompactTextString(m) } func (*UptimeCheckConfig_InternalChecker) ProtoMessage() {} func (*UptimeCheckConfig_InternalChecker) Descriptor() ([]byte, []int) { - return fileDescriptor5, []int{0, 4} + return fileDescriptor10, []int{0, 4} } func (m *UptimeCheckConfig_InternalChecker) GetProjectId() string { @@ -641,7 +641,7 @@ type UptimeCheckIp struct { func (m *UptimeCheckIp) Reset() { *m = UptimeCheckIp{} } func (m *UptimeCheckIp) String() string { return proto.CompactTextString(m) } func (*UptimeCheckIp) ProtoMessage() {} -func (*UptimeCheckIp) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{1} } +func (*UptimeCheckIp) Descriptor() ([]byte, []int) { return fileDescriptor10, []int{1} } func (m *UptimeCheckIp) GetRegion() UptimeCheckRegion { if m != nil { @@ -677,9 +677,9 @@ func init() { proto.RegisterEnum("google.monitoring.v3.GroupResourceType", GroupResourceType_name, GroupResourceType_value) } -func init() { proto.RegisterFile("google/monitoring/v3/uptime.proto", fileDescriptor5) } +func init() { proto.RegisterFile("google/monitoring/v3/uptime.proto", fileDescriptor10) } -var fileDescriptor5 = []byte{ +var fileDescriptor10 = []byte{ // 1021 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xdd, 0x4e, 0xe3, 0x46, 0x14, 0x5e, 0x13, 0xc8, 0xcf, 0x21, 0xb0, 0x66, 0x4a, 0xdb, 0x60, 0x89, 0x15, 0xbb, 0xbd, 0x28, diff --git a/google.golang.org/genproto/googleapis/monitoring/v3/uptime_service.pb.go b/google.golang.org/genproto/googleapis/monitoring/v3/uptime_service.pb.go index 5e2fb2a7..a2ee162d 100644 --- a/google.golang.org/genproto/googleapis/monitoring/v3/uptime_service.pb.go +++ b/google.golang.org/genproto/googleapis/monitoring/v3/uptime_service.pb.go @@ -7,8 +7,8 @@ import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" import _ "google.golang.org/genproto/googleapis/api/annotations" -import google_protobuf4 "github.com/golang/protobuf/ptypes/empty" -import google_protobuf5 "google.golang.org/genproto/protobuf/field_mask" +import google_protobuf5 "github.com/golang/protobuf/ptypes/empty" +import google_protobuf6 "google.golang.org/genproto/protobuf/field_mask" import ( context "golang.org/x/net/context" @@ -40,7 +40,7 @@ type ListUptimeCheckConfigsRequest struct { func (m *ListUptimeCheckConfigsRequest) Reset() { *m = ListUptimeCheckConfigsRequest{} } func (m *ListUptimeCheckConfigsRequest) String() string { return proto.CompactTextString(m) } func (*ListUptimeCheckConfigsRequest) ProtoMessage() {} -func (*ListUptimeCheckConfigsRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{0} } +func (*ListUptimeCheckConfigsRequest) Descriptor() ([]byte, []int) { return fileDescriptor11, []int{0} } func (m *ListUptimeCheckConfigsRequest) GetParent() string { if m != nil { @@ -78,7 +78,7 @@ type ListUptimeCheckConfigsResponse struct { func (m *ListUptimeCheckConfigsResponse) Reset() { *m = ListUptimeCheckConfigsResponse{} } func (m *ListUptimeCheckConfigsResponse) String() string { return proto.CompactTextString(m) } func (*ListUptimeCheckConfigsResponse) ProtoMessage() {} -func (*ListUptimeCheckConfigsResponse) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{1} } +func (*ListUptimeCheckConfigsResponse) Descriptor() ([]byte, []int) { return fileDescriptor11, []int{1} } func (m *ListUptimeCheckConfigsResponse) GetUptimeCheckConfigs() []*UptimeCheckConfig { if m != nil { @@ -105,7 +105,7 @@ type GetUptimeCheckConfigRequest struct { func (m *GetUptimeCheckConfigRequest) Reset() { *m = GetUptimeCheckConfigRequest{} } func (m *GetUptimeCheckConfigRequest) String() string { return proto.CompactTextString(m) } func (*GetUptimeCheckConfigRequest) ProtoMessage() {} -func (*GetUptimeCheckConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{2} } +func (*GetUptimeCheckConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptor11, []int{2} } func (m *GetUptimeCheckConfigRequest) GetName() string { if m != nil { @@ -127,7 +127,7 @@ type CreateUptimeCheckConfigRequest struct { func (m *CreateUptimeCheckConfigRequest) Reset() { *m = CreateUptimeCheckConfigRequest{} } func (m *CreateUptimeCheckConfigRequest) String() string { return proto.CompactTextString(m) } func (*CreateUptimeCheckConfigRequest) ProtoMessage() {} -func (*CreateUptimeCheckConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{3} } +func (*CreateUptimeCheckConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptor11, []int{3} } func (m *CreateUptimeCheckConfigRequest) GetParent() string { if m != nil { @@ -149,7 +149,7 @@ type UpdateUptimeCheckConfigRequest struct { // configuration are updated with values from the new configuration. If this // field is empty, then the current configuration is completely replaced with // the new configuration. - UpdateMask *google_protobuf5.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` + UpdateMask *google_protobuf6.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` // Required. If an `"updateMask"` has been specified, this field gives // the values for the set of fields mentioned in the `"updateMask"`. If an // `"updateMask"` has not been given, this uptime check configuration replaces @@ -163,9 +163,9 @@ type UpdateUptimeCheckConfigRequest struct { func (m *UpdateUptimeCheckConfigRequest) Reset() { *m = UpdateUptimeCheckConfigRequest{} } func (m *UpdateUptimeCheckConfigRequest) String() string { return proto.CompactTextString(m) } func (*UpdateUptimeCheckConfigRequest) ProtoMessage() {} -func (*UpdateUptimeCheckConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{4} } +func (*UpdateUptimeCheckConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptor11, []int{4} } -func (m *UpdateUptimeCheckConfigRequest) GetUpdateMask() *google_protobuf5.FieldMask { +func (m *UpdateUptimeCheckConfigRequest) GetUpdateMask() *google_protobuf6.FieldMask { if m != nil { return m.UpdateMask } @@ -190,7 +190,7 @@ type DeleteUptimeCheckConfigRequest struct { func (m *DeleteUptimeCheckConfigRequest) Reset() { *m = DeleteUptimeCheckConfigRequest{} } func (m *DeleteUptimeCheckConfigRequest) String() string { return proto.CompactTextString(m) } func (*DeleteUptimeCheckConfigRequest) ProtoMessage() {} -func (*DeleteUptimeCheckConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{5} } +func (*DeleteUptimeCheckConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptor11, []int{5} } func (m *DeleteUptimeCheckConfigRequest) GetName() string { if m != nil { @@ -217,7 +217,7 @@ type ListUptimeCheckIpsRequest struct { func (m *ListUptimeCheckIpsRequest) Reset() { *m = ListUptimeCheckIpsRequest{} } func (m *ListUptimeCheckIpsRequest) String() string { return proto.CompactTextString(m) } func (*ListUptimeCheckIpsRequest) ProtoMessage() {} -func (*ListUptimeCheckIpsRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{6} } +func (*ListUptimeCheckIpsRequest) Descriptor() ([]byte, []int) { return fileDescriptor11, []int{6} } func (m *ListUptimeCheckIpsRequest) GetPageSize() int32 { if m != nil { @@ -250,7 +250,7 @@ type ListUptimeCheckIpsResponse struct { func (m *ListUptimeCheckIpsResponse) Reset() { *m = ListUptimeCheckIpsResponse{} } func (m *ListUptimeCheckIpsResponse) String() string { return proto.CompactTextString(m) } func (*ListUptimeCheckIpsResponse) ProtoMessage() {} -func (*ListUptimeCheckIpsResponse) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{7} } +func (*ListUptimeCheckIpsResponse) Descriptor() ([]byte, []int) { return fileDescriptor11, []int{7} } func (m *ListUptimeCheckIpsResponse) GetUptimeCheckIps() []*UptimeCheckIp { if m != nil { @@ -303,7 +303,7 @@ type UptimeCheckServiceClient interface { // Deletes an uptime check configuration. Note that this method will fail // if the uptime check configuration is referenced by an alert policy or // other dependent configs that would be rendered invalid by the deletion. - DeleteUptimeCheckConfig(ctx context.Context, in *DeleteUptimeCheckConfigRequest, opts ...grpc.CallOption) (*google_protobuf4.Empty, error) + DeleteUptimeCheckConfig(ctx context.Context, in *DeleteUptimeCheckConfigRequest, opts ...grpc.CallOption) (*google_protobuf5.Empty, error) // Returns the list of IPs that checkers run from ListUptimeCheckIps(ctx context.Context, in *ListUptimeCheckIpsRequest, opts ...grpc.CallOption) (*ListUptimeCheckIpsResponse, error) } @@ -352,8 +352,8 @@ func (c *uptimeCheckServiceClient) UpdateUptimeCheckConfig(ctx context.Context, return out, nil } -func (c *uptimeCheckServiceClient) DeleteUptimeCheckConfig(ctx context.Context, in *DeleteUptimeCheckConfigRequest, opts ...grpc.CallOption) (*google_protobuf4.Empty, error) { - out := new(google_protobuf4.Empty) +func (c *uptimeCheckServiceClient) DeleteUptimeCheckConfig(ctx context.Context, in *DeleteUptimeCheckConfigRequest, opts ...grpc.CallOption) (*google_protobuf5.Empty, error) { + out := new(google_protobuf5.Empty) err := grpc.Invoke(ctx, "/google.monitoring.v3.UptimeCheckService/DeleteUptimeCheckConfig", in, out, c.cc, opts...) if err != nil { return nil, err @@ -388,7 +388,7 @@ type UptimeCheckServiceServer interface { // Deletes an uptime check configuration. Note that this method will fail // if the uptime check configuration is referenced by an alert policy or // other dependent configs that would be rendered invalid by the deletion. - DeleteUptimeCheckConfig(context.Context, *DeleteUptimeCheckConfigRequest) (*google_protobuf4.Empty, error) + DeleteUptimeCheckConfig(context.Context, *DeleteUptimeCheckConfigRequest) (*google_protobuf5.Empty, error) // Returns the list of IPs that checkers run from ListUptimeCheckIps(context.Context, *ListUptimeCheckIpsRequest) (*ListUptimeCheckIpsResponse, error) } @@ -538,9 +538,9 @@ var _UptimeCheckService_serviceDesc = grpc.ServiceDesc{ Metadata: "google/monitoring/v3/uptime_service.proto", } -func init() { proto.RegisterFile("google/monitoring/v3/uptime_service.proto", fileDescriptor6) } +func init() { proto.RegisterFile("google/monitoring/v3/uptime_service.proto", fileDescriptor11) } -var fileDescriptor6 = []byte{ +var fileDescriptor11 = []byte{ // 735 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xdf, 0x4e, 0x13, 0x4f, 0x14, 0xce, 0xb4, 0xfc, 0x08, 0x1c, 0xf2, 0xf3, 0xcf, 0xd8, 0x40, 0x5d, 0xa4, 0xa9, 0x35, 0x51, diff --git a/google.golang.org/genproto/protobuf/field_mask/field_mask.pb.go b/google.golang.org/genproto/protobuf/field_mask/field_mask.pb.go index 42693d68..485bf006 100644 --- a/google.golang.org/genproto/protobuf/field_mask/field_mask.pb.go +++ b/google.golang.org/genproto/protobuf/field_mask/field_mask.pb.go @@ -228,12 +228,6 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package // // Note that oneof type names ("test_oneof" in this case) cannot be used in // paths. -// -// ## Field Mask Verification -// -// The implementation of the all the API methods, which have any FieldMask type -// field in the request, should verify the included field paths, and return -// `INVALID_ARGUMENT` error if any path is duplicated or unmappable. type FieldMask struct { // The set of field mask paths. Paths []string `protobuf:"bytes,1,rep,name=paths" json:"paths,omitempty"` diff --git a/google.golang.org/grpc/call.go b/google.golang.org/grpc/call.go index a66e3c2d..f73b7d55 100644 --- a/google.golang.org/grpc/call.go +++ b/google.golang.org/grpc/call.go @@ -27,12 +27,31 @@ import ( // // All errors returned by Invoke are compatible with the status package. func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...CallOption) error { + // allow interceptor to see all applicable call options, which means those + // configured as defaults from dial option as well as per-call options + opts = combine(cc.dopts.callOptions, opts) + if cc.dopts.unaryInt != nil { return cc.dopts.unaryInt(ctx, method, args, reply, cc, invoke, opts...) } return invoke(ctx, method, args, reply, cc, opts...) } +func combine(o1 []CallOption, o2 []CallOption) []CallOption { + // we don't use append because o1 could have extra capacity whose + // elements would be overwritten, which could cause inadvertent + // sharing (and race connditions) between concurrent calls + if len(o1) == 0 { + return o2 + } else if len(o2) == 0 { + return o1 + } + ret := make([]CallOption, len(o1)+len(o2)) + copy(ret, o1) + copy(ret[len(o1):], o2) + return ret +} + // Invoke sends the RPC request on the wire and returns after response is // received. This is typically called by generated code. // @@ -54,7 +73,7 @@ func invoke(ctx context.Context, method string, req, reply interface{}, cc *Clie } cs := csInt.(*clientStream) if err := cs.SendMsg(req); err != nil { - if !cs.c.failFast && cs.s.Unprocessed() && firstAttempt { + if !cs.c.failFast && cs.attempt.s.Unprocessed() && firstAttempt { // TODO: Add a field to header for grpc-transparent-retry-attempts firstAttempt = false continue @@ -62,7 +81,7 @@ func invoke(ctx context.Context, method string, req, reply interface{}, cc *Clie return err } if err := cs.RecvMsg(reply); err != nil { - if !cs.c.failFast && cs.s.Unprocessed() && firstAttempt { + if !cs.c.failFast && cs.attempt.s.Unprocessed() && firstAttempt { // TODO: Add a field to header for grpc-transparent-retry-attempts firstAttempt = false continue diff --git a/google.golang.org/grpc/clientconn.go b/google.golang.org/grpc/clientconn.go index 2c22d628..64a7982f 100644 --- a/google.golang.org/grpc/clientconn.go +++ b/google.golang.org/grpc/clientconn.go @@ -45,6 +45,11 @@ import ( "google.golang.org/grpc/transport" ) +const ( + // minimum time to give a connection to complete + minConnectTimeout = 20 * time.Second +) + var ( // ErrClientConnClosing indicates that the operation is illegal because // the ClientConn is closing. @@ -60,8 +65,11 @@ var ( errConnUnavailable = errors.New("grpc: the connection is unavailable") // errBalancerClosed indicates that the balancer is closed. errBalancerClosed = errors.New("grpc: balancer is closed") - // minimum time to give a connection to complete - minConnectTimeout = 20 * time.Second + // We use an accessor so that minConnectTimeout can be + // atomically read and updated while testing. + getMinConnectTimeout = func() time.Duration { + return minConnectTimeout + } ) // The following errors are returned from Dial and DialContext @@ -479,7 +487,25 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn * if cc.dopts.bs == nil { cc.dopts.bs = DefaultBackoffConfig } - cc.parsedTarget = parseTarget(cc.target) + if cc.dopts.resolverBuilder == nil { + // Only try to parse target when resolver builder is not already set. + cc.parsedTarget = parseTarget(cc.target) + grpclog.Infof("parsed scheme: %q", cc.parsedTarget.Scheme) + cc.dopts.resolverBuilder = resolver.Get(cc.parsedTarget.Scheme) + if cc.dopts.resolverBuilder == nil { + // If resolver builder is still nil, the parse target's scheme is + // not registered. Fallback to default resolver and set Endpoint to + // the original unparsed target. + grpclog.Infof("scheme %q not registered, fallback to default scheme", cc.parsedTarget.Scheme) + cc.parsedTarget = resolver.Target{ + Scheme: resolver.GetDefaultScheme(), + Endpoint: target, + } + cc.dopts.resolverBuilder = resolver.Get(cc.parsedTarget.Scheme) + } + } else { + cc.parsedTarget = resolver.Target{Endpoint: target} + } creds := cc.dopts.copts.TransportCredentials if creds != nil && creds.Info().ServerName != "" { cc.authority = creds.Info().ServerName @@ -865,7 +891,7 @@ func (ac *addrConn) tryUpdateAddrs(addrs []resolver.Address) bool { // the corresponding MethodConfig. // If there isn't an exact match for the input method, we look for the default config // under the service (i.e /service/). If there is a default MethodConfig for -// the serivce, we return it. +// the service, we return it. // Otherwise, we return an empty MethodConfig. func (cc *ClientConn) GetMethodConfig(method string) MethodConfig { // TODO: Avoid the locking here. @@ -926,7 +952,7 @@ func (cc *ClientConn) resolveNow(o resolver.ResolveNowOption) { // Close tears down the ClientConn and all underlying connections. func (cc *ClientConn) Close() error { - cc.cancel() + defer cc.cancel() cc.mu.Lock() if cc.conns == nil { @@ -1055,7 +1081,7 @@ func (ac *addrConn) resetTransport() error { // connection. backoffFor := ac.dopts.bs.backoff(connectRetryNum) // time.Duration. // This will be the duration that dial gets to finish. - dialDuration := minConnectTimeout + dialDuration := getMinConnectTimeout() if backoffFor > dialDuration { // Give dial more time as we keep failing to connect. dialDuration = backoffFor @@ -1129,15 +1155,7 @@ func (ac *addrConn) createTransport(connectRetryNum, ridx int, backoffDeadline, newTr, err := transport.NewClientTransport(connectCtx, ac.cc.ctx, target, copts, onPrefaceReceipt) if err != nil { cancel() - if e, ok := err.(transport.ConnectionError); ok && !e.Temporary() { - ac.mu.Lock() - if ac.state != connectivity.Shutdown { - ac.state = connectivity.TransientFailure - ac.cc.handleSubConnStateChange(ac.acbw, ac.state) - } - ac.mu.Unlock() - return false, err - } + ac.cc.blockingpicker.updateConnectionError(err) ac.mu.Lock() if ac.state == connectivity.Shutdown { // ac.tearDown(...) has been invoked. diff --git a/google.golang.org/grpc/encoding/gzip/gzip.go b/google.golang.org/grpc/encoding/gzip/gzip.go index c991a662..09564db1 100644 --- a/google.golang.org/grpc/encoding/gzip/gzip.go +++ b/google.golang.org/grpc/encoding/gzip/gzip.go @@ -23,6 +23,7 @@ package gzip import ( "compress/gzip" + "fmt" "io" "io/ioutil" "sync" @@ -46,6 +47,26 @@ type writer struct { pool *sync.Pool } +// SetLevel updates the registered gzip compressor to use the compression level specified (gzip.HuffmanOnly is not supported). +// NOTE: this function must only be called during initialization time (i.e. in an init() function), +// and is not thread-safe. +// +// The error returned will be nil if the specified level is valid. +func SetLevel(level int) error { + if level < gzip.DefaultCompression || level > gzip.BestCompression { + return fmt.Errorf("grpc: invalid gzip compression level: %d", level) + } + c := encoding.GetCompressor(Name).(*compressor) + c.poolCompressor.New = func() interface{} { + w, err := gzip.NewWriterLevel(ioutil.Discard, level) + if err != nil { + panic(err) + } + return &writer{Writer: w, pool: &c.poolCompressor} + } + return nil +} + func (c *compressor) Compress(w io.Writer) (io.WriteCloser, error) { z := c.poolCompressor.Get().(*writer) z.Writer.Reset(w) diff --git a/google.golang.org/grpc/go16.go b/google.golang.org/grpc/go16.go index 0ae4dbda..535ee935 100644 --- a/google.golang.org/grpc/go16.go +++ b/google.golang.org/grpc/go16.go @@ -25,7 +25,6 @@ import ( "io" "net" "net/http" - "os" "golang.org/x/net/context" "google.golang.org/grpc/codes" @@ -69,31 +68,3 @@ func toRPCErr(err error) error { } return status.Error(codes.Unknown, err.Error()) } - -// convertCode converts a standard Go error into its canonical code. Note that -// this is only used to translate the error returned by the server applications. -func convertCode(err error) codes.Code { - switch err { - case nil: - return codes.OK - case io.EOF: - return codes.OutOfRange - case io.ErrClosedPipe, io.ErrNoProgress, io.ErrShortBuffer, io.ErrShortWrite, io.ErrUnexpectedEOF: - return codes.FailedPrecondition - case os.ErrInvalid: - return codes.InvalidArgument - case context.Canceled: - return codes.Canceled - case context.DeadlineExceeded: - return codes.DeadlineExceeded - } - switch { - case os.IsExist(err): - return codes.AlreadyExists - case os.IsNotExist(err): - return codes.NotFound - case os.IsPermission(err): - return codes.PermissionDenied - } - return codes.Unknown -} diff --git a/google.golang.org/grpc/go17.go b/google.golang.org/grpc/go17.go index 53908828..ec676a93 100644 --- a/google.golang.org/grpc/go17.go +++ b/google.golang.org/grpc/go17.go @@ -26,7 +26,6 @@ import ( "io" "net" "net/http" - "os" netctx "golang.org/x/net/context" "google.golang.org/grpc/codes" @@ -70,31 +69,3 @@ func toRPCErr(err error) error { } return status.Error(codes.Unknown, err.Error()) } - -// convertCode converts a standard Go error into its canonical code. Note that -// this is only used to translate the error returned by the server applications. -func convertCode(err error) codes.Code { - switch err { - case nil: - return codes.OK - case io.EOF: - return codes.OutOfRange - case io.ErrClosedPipe, io.ErrNoProgress, io.ErrShortBuffer, io.ErrShortWrite, io.ErrUnexpectedEOF: - return codes.FailedPrecondition - case os.ErrInvalid: - return codes.InvalidArgument - case context.Canceled, netctx.Canceled: - return codes.Canceled - case context.DeadlineExceeded, netctx.DeadlineExceeded: - return codes.DeadlineExceeded - } - switch { - case os.IsExist(err): - return codes.AlreadyExists - case os.IsNotExist(err): - return codes.NotFound - case os.IsPermission(err): - return codes.PermissionDenied - } - return codes.Unknown -} diff --git a/google.golang.org/grpc/interceptor.go b/google.golang.org/grpc/interceptor.go index 06dc825b..1f6ef678 100644 --- a/google.golang.org/grpc/interceptor.go +++ b/google.golang.org/grpc/interceptor.go @@ -48,7 +48,9 @@ type UnaryServerInfo struct { } // UnaryHandler defines the handler invoked by UnaryServerInterceptor to complete the normal -// execution of a unary RPC. +// execution of a unary RPC. If a UnaryHandler returns an error, it should be produced by the +// status package, or else gRPC will use codes.Unknown as the status code and err.Error() as +// the status message of the RPC. type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error) // UnaryServerInterceptor provides a hook to intercept the execution of a unary RPC on the server. info diff --git a/google.golang.org/grpc/metadata/metadata.go b/google.golang.org/grpc/metadata/metadata.go index 15662b5d..e7c99467 100644 --- a/google.golang.org/grpc/metadata/metadata.go +++ b/google.golang.org/grpc/metadata/metadata.go @@ -131,7 +131,11 @@ func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context panic(fmt.Sprintf("metadata: AppendToOutgoingContext got an odd number of input pairs for metadata: %d", len(kv))) } md, _ := ctx.Value(mdOutgoingKey{}).(rawMD) - return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md.md, added: append(md.added, kv)}) + added := make([][]string, len(md.added)+1) + copy(added, md.added) + added[len(added)-1] = make([]string, len(kv)) + copy(added[len(added)-1], kv) + return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md.md, added: added}) } // FromIncomingContext returns the incoming metadata in ctx if it exists. The @@ -159,7 +163,7 @@ func FromOutgoingContextRaw(ctx context.Context) (MD, [][]string, bool) { // FromOutgoingContext returns the outgoing metadata in ctx if it exists. The // returned MD should not be modified. Writing to it may cause races. -// Modification should be made to the copies of the returned MD. +// Modification should be made to copies of the returned MD. func FromOutgoingContext(ctx context.Context) (MD, bool) { raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD) if !ok { diff --git a/google.golang.org/grpc/picker_wrapper.go b/google.golang.org/grpc/picker_wrapper.go index db82bfb3..4d008259 100644 --- a/google.golang.org/grpc/picker_wrapper.go +++ b/google.golang.org/grpc/picker_wrapper.go @@ -36,6 +36,10 @@ type pickerWrapper struct { done bool blockingCh chan struct{} picker balancer.Picker + + // The latest connection happened. + connErrMu sync.Mutex + connErr error } func newPickerWrapper() *pickerWrapper { @@ -43,6 +47,19 @@ func newPickerWrapper() *pickerWrapper { return bp } +func (bp *pickerWrapper) updateConnectionError(err error) { + bp.connErrMu.Lock() + bp.connErr = err + bp.connErrMu.Unlock() +} + +func (bp *pickerWrapper) connectionError() error { + bp.connErrMu.Lock() + err := bp.connErr + bp.connErrMu.Unlock() + return err +} + // updatePicker is called by UpdateBalancerState. It unblocks all blocked pick. func (bp *pickerWrapper) updatePicker(p balancer.Picker) { bp.mu.Lock() @@ -107,7 +124,7 @@ func (bp *pickerWrapper) pick(ctx context.Context, failfast bool, opts balancer. if !failfast { continue } - return nil, nil, status.Errorf(codes.Unavailable, "%v", err) + return nil, nil, status.Errorf(codes.Unavailable, "%v, latest connection error: %v", err, bp.connectionError()) default: // err is some other error. return nil, nil, toRPCErr(err) diff --git a/google.golang.org/grpc/reflection/serverreflection.go b/google.golang.org/grpc/reflection/serverreflection.go index 1bfbf3e7..dd22a2da 100644 --- a/google.golang.org/grpc/reflection/serverreflection.go +++ b/google.golang.org/grpc/reflection/serverreflection.go @@ -45,7 +45,8 @@ import ( "io" "io/ioutil" "reflect" - "strings" + "sort" + "sync" "github.com/golang/protobuf/proto" dpb "github.com/golang/protobuf/protoc-gen-go/descriptor" @@ -57,8 +58,10 @@ import ( type serverReflectionServer struct { s *grpc.Server - // TODO add more cache if necessary - serviceInfo map[string]grpc.ServiceInfo // cache for s.GetServiceInfo() + + initSymbols sync.Once + serviceNames []string + symbols map[string]*dpb.FileDescriptorProto // map of fully-qualified names to files } // Register registers the server reflection service on the given gRPC server. @@ -76,6 +79,112 @@ type protoMessage interface { Descriptor() ([]byte, []int) } +func (s *serverReflectionServer) getSymbols() (svcNames []string, symbolIndex map[string]*dpb.FileDescriptorProto) { + s.initSymbols.Do(func() { + serviceInfo := s.s.GetServiceInfo() + + s.symbols = map[string]*dpb.FileDescriptorProto{} + s.serviceNames = make([]string, 0, len(serviceInfo)) + processed := map[string]struct{}{} + for svc, info := range serviceInfo { + s.serviceNames = append(s.serviceNames, svc) + fdenc, ok := parseMetadata(info.Metadata) + if !ok { + continue + } + fd, err := decodeFileDesc(fdenc) + if err != nil { + continue + } + s.processFile(fd, processed) + } + sort.Strings(s.serviceNames) + }) + + return s.serviceNames, s.symbols +} + +func (s *serverReflectionServer) processFile(fd *dpb.FileDescriptorProto, processed map[string]struct{}) { + filename := fd.GetName() + if _, ok := processed[filename]; ok { + return + } + processed[filename] = struct{}{} + + prefix := fd.GetPackage() + + for _, msg := range fd.MessageType { + s.processMessage(fd, prefix, msg) + } + for _, en := range fd.EnumType { + s.processEnum(fd, prefix, en) + } + for _, ext := range fd.Extension { + s.processField(fd, prefix, ext) + } + for _, svc := range fd.Service { + svcName := fqn(prefix, svc.GetName()) + s.symbols[svcName] = fd + for _, meth := range svc.Method { + name := fqn(svcName, meth.GetName()) + s.symbols[name] = fd + } + } + + for _, dep := range fd.Dependency { + fdenc := proto.FileDescriptor(dep) + fdDep, err := decodeFileDesc(fdenc) + if err != nil { + continue + } + s.processFile(fdDep, processed) + } +} + +func (s *serverReflectionServer) processMessage(fd *dpb.FileDescriptorProto, prefix string, msg *dpb.DescriptorProto) { + msgName := fqn(prefix, msg.GetName()) + s.symbols[msgName] = fd + + for _, nested := range msg.NestedType { + s.processMessage(fd, msgName, nested) + } + for _, en := range msg.EnumType { + s.processEnum(fd, msgName, en) + } + for _, ext := range msg.Extension { + s.processField(fd, msgName, ext) + } + for _, fld := range msg.Field { + s.processField(fd, msgName, fld) + } + for _, oneof := range msg.OneofDecl { + oneofName := fqn(msgName, oneof.GetName()) + s.symbols[oneofName] = fd + } +} + +func (s *serverReflectionServer) processEnum(fd *dpb.FileDescriptorProto, prefix string, en *dpb.EnumDescriptorProto) { + enName := fqn(prefix, en.GetName()) + s.symbols[enName] = fd + + for _, val := range en.Value { + valName := fqn(enName, val.GetName()) + s.symbols[valName] = fd + } +} + +func (s *serverReflectionServer) processField(fd *dpb.FileDescriptorProto, prefix string, fld *dpb.FieldDescriptorProto) { + fldName := fqn(prefix, fld.GetName()) + s.symbols[fldName] = fd +} + +func fqn(prefix, name string) string { + if prefix == "" { + return name + } + return prefix + "." + name +} + // fileDescForType gets the file descriptor for the given type. // The given type should be a proto message. func (s *serverReflectionServer) fileDescForType(st reflect.Type) (*dpb.FileDescriptorProto, error) { @@ -85,12 +194,12 @@ func (s *serverReflectionServer) fileDescForType(st reflect.Type) (*dpb.FileDesc } enc, _ := m.Descriptor() - return s.decodeFileDesc(enc) + return decodeFileDesc(enc) } // decodeFileDesc does decompression and unmarshalling on the given // file descriptor byte slice. -func (s *serverReflectionServer) decodeFileDesc(enc []byte) (*dpb.FileDescriptorProto, error) { +func decodeFileDesc(enc []byte) (*dpb.FileDescriptorProto, error) { raw, err := decompress(enc) if err != nil { return nil, fmt.Errorf("failed to decompress enc: %v", err) @@ -116,7 +225,7 @@ func decompress(b []byte) ([]byte, error) { return out, nil } -func (s *serverReflectionServer) typeForName(name string) (reflect.Type, error) { +func typeForName(name string) (reflect.Type, error) { pt := proto.MessageType(name) if pt == nil { return nil, fmt.Errorf("unknown type: %q", name) @@ -126,7 +235,7 @@ func (s *serverReflectionServer) typeForName(name string) (reflect.Type, error) return st, nil } -func (s *serverReflectionServer) fileDescContainingExtension(st reflect.Type, ext int32) (*dpb.FileDescriptorProto, error) { +func fileDescContainingExtension(st reflect.Type, ext int32) (*dpb.FileDescriptorProto, error) { m, ok := reflect.Zero(reflect.PtrTo(st)).Interface().(proto.Message) if !ok { return nil, fmt.Errorf("failed to create message from type: %v", st) @@ -144,7 +253,7 @@ func (s *serverReflectionServer) fileDescContainingExtension(st reflect.Type, ex return nil, fmt.Errorf("failed to find registered extension for extension number %v", ext) } - return s.decodeFileDesc(proto.FileDescriptor(extDesc.Filename)) + return decodeFileDesc(proto.FileDescriptor(extDesc.Filename)) } func (s *serverReflectionServer) allExtensionNumbersForType(st reflect.Type) ([]int32, error) { @@ -168,53 +277,13 @@ func (s *serverReflectionServer) fileDescEncodingByFilename(name string) ([]byte if enc == nil { return nil, fmt.Errorf("unknown file: %v", name) } - fd, err := s.decodeFileDesc(enc) + fd, err := decodeFileDesc(enc) if err != nil { return nil, err } return proto.Marshal(fd) } -// serviceMetadataForSymbol finds the metadata for name in s.serviceInfo. -// name should be a service name or a method name. -func (s *serverReflectionServer) serviceMetadataForSymbol(name string) (interface{}, error) { - if s.serviceInfo == nil { - s.serviceInfo = s.s.GetServiceInfo() - } - - // Check if it's a service name. - if info, ok := s.serviceInfo[name]; ok { - return info.Metadata, nil - } - - // Check if it's a method name. - pos := strings.LastIndex(name, ".") - // Not a valid method name. - if pos == -1 { - return nil, fmt.Errorf("unknown symbol: %v", name) - } - - info, ok := s.serviceInfo[name[:pos]] - // Substring before last "." is not a service name. - if !ok { - return nil, fmt.Errorf("unknown symbol: %v", name) - } - - // Search the method name in info.Methods. - var found bool - for _, m := range info.Methods { - if m.Name == name[pos+1:] { - found = true - break - } - } - if found { - return info.Metadata, nil - } - - return nil, fmt.Errorf("unknown symbol: %v", name) -} - // parseMetadata finds the file descriptor bytes specified meta. // For SupportPackageIsVersion4, m is the name of the proto file, we // call proto.FileDescriptor to get the byte slice. @@ -237,33 +306,21 @@ func parseMetadata(meta interface{}) ([]byte, bool) { // does marshalling on it and returns the marshalled result. // The given symbol can be a type, a service or a method. func (s *serverReflectionServer) fileDescEncodingContainingSymbol(name string) ([]byte, error) { - var ( - fd *dpb.FileDescriptorProto - ) - // Check if it's a type name. - if st, err := s.typeForName(name); err == nil { - fd, err = s.fileDescForType(st) - if err != nil { - return nil, err - } - } else { // Check if it's a service name or a method name. - meta, err := s.serviceMetadataForSymbol(name) - - // Metadata not found. - if err != nil { - return nil, err - } - - // Metadata not valid. - enc, ok := parseMetadata(meta) - if !ok { - return nil, fmt.Errorf("invalid file descriptor for symbol: %v", name) + _, symbols := s.getSymbols() + fd := symbols[name] + if fd == nil { + // Check if it's a type name that was not present in the + // transitive dependencies of the registered services. + if st, err := typeForName(name); err == nil { + fd, err = s.fileDescForType(st) + if err != nil { + return nil, err + } } + } - fd, err = s.decodeFileDesc(enc) - if err != nil { - return nil, err - } + if fd == nil { + return nil, fmt.Errorf("unknown symbol: %v", name) } return proto.Marshal(fd) @@ -272,11 +329,11 @@ func (s *serverReflectionServer) fileDescEncodingContainingSymbol(name string) ( // fileDescEncodingContainingExtension finds the file descriptor containing given extension, // does marshalling on it and returns the marshalled result. func (s *serverReflectionServer) fileDescEncodingContainingExtension(typeName string, extNum int32) ([]byte, error) { - st, err := s.typeForName(typeName) + st, err := typeForName(typeName) if err != nil { return nil, err } - fd, err := s.fileDescContainingExtension(st, extNum) + fd, err := fileDescContainingExtension(st, extNum) if err != nil { return nil, err } @@ -285,7 +342,7 @@ func (s *serverReflectionServer) fileDescEncodingContainingExtension(typeName st // allExtensionNumbersForTypeName returns all extension numbers for the given type. func (s *serverReflectionServer) allExtensionNumbersForTypeName(name string) ([]int32, error) { - st, err := s.typeForName(name) + st, err := typeForName(name) if err != nil { return nil, err } @@ -374,14 +431,12 @@ func (s *serverReflectionServer) ServerReflectionInfo(stream rpb.ServerReflectio } } case *rpb.ServerReflectionRequest_ListServices: - if s.serviceInfo == nil { - s.serviceInfo = s.s.GetServiceInfo() - } - serviceResponses := make([]*rpb.ServiceResponse, 0, len(s.serviceInfo)) - for n := range s.serviceInfo { - serviceResponses = append(serviceResponses, &rpb.ServiceResponse{ + svcNames, _ := s.getSymbols() + serviceResponses := make([]*rpb.ServiceResponse, len(svcNames)) + for i, n := range svcNames { + serviceResponses[i] = &rpb.ServiceResponse{ Name: n, - }) + } } out.MessageResponse = &rpb.ServerReflectionResponse_ListServicesResponse{ ListServicesResponse: &rpb.ListServiceResponse{ diff --git a/google.golang.org/grpc/resolver/resolver.go b/google.golang.org/grpc/resolver/resolver.go index 9efcffb3..775ee4d0 100644 --- a/google.golang.org/grpc/resolver/resolver.go +++ b/google.golang.org/grpc/resolver/resolver.go @@ -36,21 +36,12 @@ func Register(b Builder) { } // Get returns the resolver builder registered with the given scheme. -// If no builder is register with the scheme, the default scheme will -// be used. -// If the default scheme is not modified, "passthrough" will be the default -// scheme, and the preinstalled dns resolver will be used. -// If the default scheme is modified, and a resolver is registered with -// the scheme, that resolver will be returned. -// If the default scheme is modified, and no resolver is registered with -// the scheme, nil will be returned. +// +// If no builder is register with the scheme, nil will be returned. func Get(scheme string) Builder { if b, ok := m[scheme]; ok { return b } - if b, ok := m[defaultScheme]; ok { - return b - } return nil } @@ -60,6 +51,11 @@ func SetDefaultScheme(scheme string) { defaultScheme = scheme } +// GetDefaultScheme gets the default scheme that will be used. +func GetDefaultScheme() string { + return defaultScheme +} + // AddressType indicates the address type returned by name resolution. type AddressType uint8 diff --git a/google.golang.org/grpc/resolver_conn_wrapper.go b/google.golang.org/grpc/resolver_conn_wrapper.go index 1a1591e8..75b8ce1e 100644 --- a/google.golang.org/grpc/resolver_conn_wrapper.go +++ b/google.golang.org/grpc/resolver_conn_wrapper.go @@ -48,13 +48,19 @@ func split2(s, sep string) (string, string, bool) { // parseTarget splits target into a struct containing scheme, authority and // endpoint. +// +// If target is not a valid scheme://authority/endpoint, it returns {Endpoint: +// target}. func parseTarget(target string) (ret resolver.Target) { var ok bool ret.Scheme, ret.Endpoint, ok = split2(target, "://") if !ok { return resolver.Target{Endpoint: target} } - ret.Authority, ret.Endpoint, _ = split2(ret.Endpoint, "/") + ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, "/") + if !ok { + return resolver.Target{Endpoint: target} + } return ret } @@ -65,14 +71,9 @@ func parseTarget(target string) (ret resolver.Target) { // If withResolverBuilder dial option is set, the specified resolver will be // used instead. func newCCResolverWrapper(cc *ClientConn) (*ccResolverWrapper, error) { - grpclog.Infof("dialing to target with scheme: %q", cc.parsedTarget.Scheme) - rb := cc.dopts.resolverBuilder if rb == nil { - rb = resolver.Get(cc.parsedTarget.Scheme) - if rb == nil { - return nil, fmt.Errorf("could not get resolver for scheme: %q", cc.parsedTarget.Scheme) - } + return nil, fmt.Errorf("could not get resolver for scheme: %q", cc.parsedTarget.Scheme) } ccr := &ccResolverWrapper{ diff --git a/google.golang.org/grpc/rpc_util.go b/google.golang.org/grpc/rpc_util.go index 09245e0d..5ef9cb2f 100644 --- a/google.golang.org/grpc/rpc_util.go +++ b/google.golang.org/grpc/rpc_util.go @@ -22,6 +22,7 @@ import ( "bytes" "compress/gzip" "encoding/binary" + "fmt" "io" "io/ioutil" "math" @@ -55,13 +56,29 @@ type gzipCompressor struct { // NewGZIPCompressor creates a Compressor based on GZIP. func NewGZIPCompressor() Compressor { + c, _ := NewGZIPCompressorWithLevel(gzip.DefaultCompression) + return c +} + +// NewGZIPCompressorWithLevel is like NewGZIPCompressor but specifies the gzip compression level instead +// of assuming DefaultCompression. +// +// The error returned will be nil if the level is valid. +func NewGZIPCompressorWithLevel(level int) (Compressor, error) { + if level < gzip.DefaultCompression || level > gzip.BestCompression { + return nil, fmt.Errorf("grpc: invalid compression level: %d", level) + } return &gzipCompressor{ pool: sync.Pool{ New: func() interface{} { - return gzip.NewWriter(ioutil.Discard) + w, err := gzip.NewWriterLevel(ioutil.Discard, level) + if err != nil { + panic(err) + } + return w }, }, - } + }, nil } func (c *gzipCompressor) Do(w io.Writer, p []byte) error { @@ -127,7 +144,7 @@ func (d *gzipDecompressor) Type() string { type callInfo struct { compressorType string failFast bool - stream *transport.Stream + stream *clientStream traceInfo traceInfo // in trace.go maxReceiveMessageSize *int maxSendMessageSize *int @@ -160,46 +177,66 @@ type EmptyCallOption struct{} func (EmptyCallOption) before(*callInfo) error { return nil } func (EmptyCallOption) after(*callInfo) {} -type beforeCall func(c *callInfo) error - -func (o beforeCall) before(c *callInfo) error { return o(c) } -func (o beforeCall) after(c *callInfo) {} - -type afterCall func(c *callInfo) - -func (o afterCall) before(c *callInfo) error { return nil } -func (o afterCall) after(c *callInfo) { o(c) } - // Header returns a CallOptions that retrieves the header metadata // for a unary RPC. func Header(md *metadata.MD) CallOption { - return afterCall(func(c *callInfo) { - if c.stream != nil { - *md, _ = c.stream.Header() - } - }) + return HeaderCallOption{HeaderAddr: md} +} + +// HeaderCallOption is a CallOption for collecting response header metadata. +// The metadata field will be populated *after* the RPC completes. +// This is an EXPERIMENTAL API. +type HeaderCallOption struct { + HeaderAddr *metadata.MD +} + +func (o HeaderCallOption) before(c *callInfo) error { return nil } +func (o HeaderCallOption) after(c *callInfo) { + if c.stream != nil { + *o.HeaderAddr, _ = c.stream.Header() + } } // Trailer returns a CallOptions that retrieves the trailer metadata // for a unary RPC. func Trailer(md *metadata.MD) CallOption { - return afterCall(func(c *callInfo) { - if c.stream != nil { - *md = c.stream.Trailer() - } - }) + return TrailerCallOption{TrailerAddr: md} +} + +// TrailerCallOption is a CallOption for collecting response trailer metadata. +// The metadata field will be populated *after* the RPC completes. +// This is an EXPERIMENTAL API. +type TrailerCallOption struct { + TrailerAddr *metadata.MD +} + +func (o TrailerCallOption) before(c *callInfo) error { return nil } +func (o TrailerCallOption) after(c *callInfo) { + if c.stream != nil { + *o.TrailerAddr = c.stream.Trailer() + } } // Peer returns a CallOption that retrieves peer information for a // unary RPC. func Peer(p *peer.Peer) CallOption { - return afterCall(func(c *callInfo) { - if c.stream != nil { - if x, ok := peer.FromContext(c.stream.Context()); ok { - *p = *x - } + return PeerCallOption{PeerAddr: p} +} + +// PeerCallOption is a CallOption for collecting the identity of the remote +// peer. The peer field will be populated *after* the RPC completes. +// This is an EXPERIMENTAL API. +type PeerCallOption struct { + PeerAddr *peer.Peer +} + +func (o PeerCallOption) before(c *callInfo) error { return nil } +func (o PeerCallOption) after(c *callInfo) { + if c.stream != nil { + if x, ok := peer.FromContext(c.stream.Context()); ok { + *o.PeerAddr = *x } - }) + } } // FailFast configures the action to take when an RPC is attempted on broken @@ -213,49 +250,98 @@ func Peer(p *peer.Peer) CallOption { // // By default, RPCs are "Fail Fast". func FailFast(failFast bool) CallOption { - return beforeCall(func(c *callInfo) error { - c.failFast = failFast - return nil - }) + return FailFastCallOption{FailFast: failFast} +} + +// FailFastCallOption is a CallOption for indicating whether an RPC should fail +// fast or not. +// This is an EXPERIMENTAL API. +type FailFastCallOption struct { + FailFast bool } +func (o FailFastCallOption) before(c *callInfo) error { + c.failFast = o.FailFast + return nil +} +func (o FailFastCallOption) after(c *callInfo) { return } + // MaxCallRecvMsgSize returns a CallOption which sets the maximum message size the client can receive. func MaxCallRecvMsgSize(s int) CallOption { - return beforeCall(func(o *callInfo) error { - o.maxReceiveMessageSize = &s - return nil - }) + return MaxRecvMsgSizeCallOption{MaxRecvMsgSize: s} } +// MaxRecvMsgSizeCallOption is a CallOption that indicates the maximum message +// size the client can receive. +// This is an EXPERIMENTAL API. +type MaxRecvMsgSizeCallOption struct { + MaxRecvMsgSize int +} + +func (o MaxRecvMsgSizeCallOption) before(c *callInfo) error { + c.maxReceiveMessageSize = &o.MaxRecvMsgSize + return nil +} +func (o MaxRecvMsgSizeCallOption) after(c *callInfo) { return } + // MaxCallSendMsgSize returns a CallOption which sets the maximum message size the client can send. func MaxCallSendMsgSize(s int) CallOption { - return beforeCall(func(o *callInfo) error { - o.maxSendMessageSize = &s - return nil - }) + return MaxSendMsgSizeCallOption{MaxSendMsgSize: s} +} + +// MaxSendMsgSizeCallOption is a CallOption that indicates the maximum message +// size the client can send. +// This is an EXPERIMENTAL API. +type MaxSendMsgSizeCallOption struct { + MaxSendMsgSize int +} + +func (o MaxSendMsgSizeCallOption) before(c *callInfo) error { + c.maxSendMessageSize = &o.MaxSendMsgSize + return nil } +func (o MaxSendMsgSizeCallOption) after(c *callInfo) { return } // PerRPCCredentials returns a CallOption that sets credentials.PerRPCCredentials // for a call. func PerRPCCredentials(creds credentials.PerRPCCredentials) CallOption { - return beforeCall(func(c *callInfo) error { - c.creds = creds - return nil - }) + return PerRPCCredsCallOption{Creds: creds} +} + +// PerRPCCredsCallOption is a CallOption that indicates the per-RPC +// credentials to use for the call. +// This is an EXPERIMENTAL API. +type PerRPCCredsCallOption struct { + Creds credentials.PerRPCCredentials } +func (o PerRPCCredsCallOption) before(c *callInfo) error { + c.creds = o.Creds + return nil +} +func (o PerRPCCredsCallOption) after(c *callInfo) { return } + // UseCompressor returns a CallOption which sets the compressor used when // sending the request. If WithCompressor is also set, UseCompressor has // higher priority. // // This API is EXPERIMENTAL. func UseCompressor(name string) CallOption { - return beforeCall(func(c *callInfo) error { - c.compressorType = name - return nil - }) + return CompressorCallOption{CompressorType: name} } +// CompressorCallOption is a CallOption that indicates the compressor to use. +// This is an EXPERIMENTAL API. +type CompressorCallOption struct { + CompressorType string +} + +func (o CompressorCallOption) before(c *callInfo) error { + c.compressorType = o.CompressorType + return nil +} +func (o CompressorCallOption) after(c *callInfo) { return } + // CallContentSubtype returns a CallOption that will set the content-subtype // for a call. For example, if content-subtype is "json", the Content-Type over // the wire will be "application/grpc+json". The content-subtype is converted @@ -273,13 +359,22 @@ func UseCompressor(name string) CallOption { // response messages, with the content-subtype set to the given contentSubtype // here for requests. func CallContentSubtype(contentSubtype string) CallOption { - contentSubtype = strings.ToLower(contentSubtype) - return beforeCall(func(c *callInfo) error { - c.contentSubtype = contentSubtype - return nil - }) + return ContentSubtypeCallOption{ContentSubtype: strings.ToLower(contentSubtype)} +} + +// ContentSubtypeCallOption is a CallOption that indicates the content-subtype +// used for marshaling messages. +// This is an EXPERIMENTAL API. +type ContentSubtypeCallOption struct { + ContentSubtype string } +func (o ContentSubtypeCallOption) before(c *callInfo) error { + c.contentSubtype = o.ContentSubtype + return nil +} +func (o ContentSubtypeCallOption) after(c *callInfo) { return } + // CallCustomCodec returns a CallOption that will set the given Codec to be // used for all request and response messages for a call. The result of calling // String() will be used as the content-subtype in a case-insensitive manner. @@ -293,11 +388,21 @@ func CallContentSubtype(contentSubtype string) CallOption { // This function is provided for advanced users; prefer to use only // CallContentSubtype to select a registered codec instead. func CallCustomCodec(codec Codec) CallOption { - return beforeCall(func(c *callInfo) error { - c.codec = codec - return nil - }) + return CustomCodecCallOption{Codec: codec} +} + +// CustomCodecCallOption is a CallOption that indicates the codec used for +// marshaling messages. +// This is an EXPERIMENTAL API. +type CustomCodecCallOption struct { + Codec Codec +} + +func (o CustomCodecCallOption) before(c *callInfo) error { + c.codec = o.Codec + return nil } +func (o CustomCodecCallOption) after(c *callInfo) { return } // The format of the payload: compressed or not? type payloadFormat uint8 @@ -572,6 +677,6 @@ const ( ) // Version is the current grpc version. -const Version = "1.10.0" +const Version = "1.11.1" const grpcUA = "grpc-go/" + Version diff --git a/google.golang.org/grpc/server.go b/google.golang.org/grpc/server.go index 0f7ff5d6..0063906e 100644 --- a/google.golang.org/grpc/server.go +++ b/google.golang.org/grpc/server.go @@ -777,13 +777,15 @@ func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Str func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, md *MethodDesc, trInfo *traceInfo) (err error) { sh := s.opts.statsHandler if sh != nil { + beginTime := time.Now() begin := &stats.Begin{ - BeginTime: time.Now(), + BeginTime: beginTime, } sh.HandleRPC(stream.Context(), begin) defer func() { end := &stats.End{ - EndTime: time.Now(), + BeginTime: beginTime, + EndTime: time.Now(), } if err != nil && err != io.EOF { end.Error = toRPCErr(err) @@ -917,12 +919,13 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. } return nil } - reply, appErr := md.Handler(srv.server, stream.Context(), df, s.opts.unaryInt) + ctx := NewContextWithServerTransportStream(stream.Context(), stream) + reply, appErr := md.Handler(srv.server, ctx, df, s.opts.unaryInt) if appErr != nil { appStatus, ok := status.FromError(appErr) if !ok { // Convert appErr if it is not a grpc status error. - appErr = status.Error(convertCode(appErr), appErr.Error()) + appErr = status.Error(codes.Unknown, appErr.Error()) appStatus, _ = status.FromError(appErr) } if trInfo != nil { @@ -977,13 +980,15 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, sd *StreamDesc, trInfo *traceInfo) (err error) { sh := s.opts.statsHandler if sh != nil { + beginTime := time.Now() begin := &stats.Begin{ - BeginTime: time.Now(), + BeginTime: beginTime, } sh.HandleRPC(stream.Context(), begin) defer func() { end := &stats.End{ - EndTime: time.Now(), + BeginTime: beginTime, + EndTime: time.Now(), } if err != nil && err != io.EOF { end.Error = toRPCErr(err) @@ -991,7 +996,9 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp sh.HandleRPC(stream.Context(), end) }() } + ctx := NewContextWithServerTransportStream(stream.Context(), stream) ss := &serverStream{ + ctx: ctx, t: t, s: stream, p: &parser{r: stream}, @@ -1065,7 +1072,7 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp case transport.StreamError: appStatus = status.New(err.Code, err.Desc) default: - appStatus = status.New(convertCode(appErr), appErr.Error()) + appStatus = status.New(codes.Unknown, appErr.Error()) } appErr = appStatus.Err() } @@ -1085,7 +1092,6 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp ss.mu.Unlock() } return t.WriteStatus(ss.s, status.New(codes.OK, "")) - } func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream, trInfo *traceInfo) { @@ -1167,6 +1173,40 @@ func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Str } } +// The key to save ServerTransportStream in the context. +type streamKey struct{} + +// NewContextWithServerTransportStream creates a new context from ctx and +// attaches stream to it. +// +// This API is EXPERIMENTAL. +func NewContextWithServerTransportStream(ctx context.Context, stream ServerTransportStream) context.Context { + return context.WithValue(ctx, streamKey{}, stream) +} + +// ServerTransportStream is a minimal interface that a transport stream must +// implement. This can be used to mock an actual transport stream for tests of +// handler code that use, for example, grpc.SetHeader (which requires some +// stream to be in context). +// +// See also NewContextWithServerTransportStream. +// +// This API is EXPERIMENTAL. +type ServerTransportStream interface { + Method() string + SetHeader(md metadata.MD) error + SendHeader(md metadata.MD) error + SetTrailer(md metadata.MD) error +} + +// serverStreamFromContext returns the server stream saved in ctx. Returns +// nil if the given context has no stream associated with it (which implies +// it is not an RPC invocation context). +func serverTransportStreamFromContext(ctx context.Context) ServerTransportStream { + s, _ := ctx.Value(streamKey{}).(ServerTransportStream) + return s +} + // Stop stops the gRPC server. It immediately closes all open // connections and listeners. // It cancels all active RPCs on the server side and the corresponding @@ -1287,8 +1327,8 @@ func SetHeader(ctx context.Context, md metadata.MD) error { if md.Len() == 0 { return nil } - stream, ok := transport.StreamFromContext(ctx) - if !ok { + stream := serverTransportStreamFromContext(ctx) + if stream == nil { return status.Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx) } return stream.SetHeader(md) @@ -1297,15 +1337,11 @@ func SetHeader(ctx context.Context, md metadata.MD) error { // SendHeader sends header metadata. It may be called at most once. // The provided md and headers set by SetHeader() will be sent. func SendHeader(ctx context.Context, md metadata.MD) error { - stream, ok := transport.StreamFromContext(ctx) - if !ok { + stream := serverTransportStreamFromContext(ctx) + if stream == nil { return status.Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx) } - t := stream.ServerTransport() - if t == nil { - grpclog.Fatalf("grpc: SendHeader: %v has no ServerTransport to send header metadata.", stream) - } - if err := t.WriteHeader(stream, md); err != nil { + if err := stream.SendHeader(md); err != nil { return toRPCErr(err) } return nil @@ -1317,8 +1353,8 @@ func SetTrailer(ctx context.Context, md metadata.MD) error { if md.Len() == 0 { return nil } - stream, ok := transport.StreamFromContext(ctx) - if !ok { + stream := serverTransportStreamFromContext(ctx) + if stream == nil { return status.Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx) } return stream.SetTrailer(md) diff --git a/google.golang.org/grpc/stats/stats.go b/google.golang.org/grpc/stats/stats.go index d5aa2f79..3f13190a 100644 --- a/google.golang.org/grpc/stats/stats.go +++ b/google.golang.org/grpc/stats/stats.go @@ -169,6 +169,8 @@ func (s *OutTrailer) isRPCStats() {} type End struct { // Client is true if this End is from client side. Client bool + // BeginTime is the time when the RPC began. + BeginTime time.Time // EndTime is the time when the RPC ends. EndTime time.Time // Error is the error the RPC ended with. It is an error generated from diff --git a/google.golang.org/grpc/status/status.go b/google.golang.org/grpc/status/status.go index 3a42dc6d..9c61b094 100644 --- a/google.golang.org/grpc/status/status.go +++ b/google.golang.org/grpc/status/status.go @@ -46,7 +46,7 @@ func (se *statusError) Error() string { return fmt.Sprintf("rpc error: code = %s desc = %s", codes.Code(p.GetCode()), p.GetMessage()) } -func (se *statusError) status() *Status { +func (se *statusError) GRPCStatus() *Status { return &Status{s: (*spb.Status)(se)} } @@ -120,14 +120,14 @@ func FromProto(s *spb.Status) *Status { } // FromError returns a Status representing err if it was produced from this -// package. Otherwise, ok is false and a Status is returned with codes.Unknown -// and the original error message. +// package or has a method `GRPCStatus() *Status`. Otherwise, ok is false and a +// Status is returned with codes.Unknown and the original error message. func FromError(err error) (s *Status, ok bool) { if err == nil { return &Status{s: &spb.Status{Code: int32(codes.OK)}}, true } - if se, ok := err.(*statusError); ok { - return se.status(), true + if se, ok := err.(interface{ GRPCStatus() *Status }); ok { + return se.GRPCStatus(), true } return New(codes.Unknown, err.Error()), false } @@ -182,8 +182,8 @@ func Code(err error) codes.Code { if err == nil { return codes.OK } - if se, ok := err.(*statusError); ok { - return se.status().Code() + if se, ok := err.(interface{ GRPCStatus() *Status }); ok { + return se.GRPCStatus().Code() } return codes.Unknown } diff --git a/google.golang.org/grpc/stream.go b/google.golang.org/grpc/stream.go index deb73592..a79f385a 100644 --- a/google.golang.org/grpc/stream.go +++ b/google.golang.org/grpc/stream.go @@ -36,7 +36,10 @@ import ( ) // StreamHandler defines the handler called by gRPC server to complete the -// execution of a streaming RPC. +// execution of a streaming RPC. If a StreamHandler returns an error, it +// should be produced by the status package, or else gRPC will use +// codes.Unknown as the status code and err.Error() as the status message +// of the RPC. type StreamHandler func(srv interface{}, stream ServerStream) error // StreamDesc represents a streaming RPC service's method specification. @@ -99,6 +102,10 @@ type ClientStream interface { // NewStream creates a new Stream for the client side. This is typically // called by generated code. func (cc *ClientConn) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) { + // allow interceptor to see all applicable call options, which means those + // configured as defaults from dial option as well as per-call options + opts = combine(cc.dopts.callOptions, opts) + if cc.dopts.streamInt != nil { return cc.dopts.streamInt(ctx, desc, cc, method, newClientStream, opts...) } @@ -137,7 +144,6 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth } }() - opts = append(cc.dopts.callOptions, opts...) for _, o := range opts { if err := o.before(c); err != nil { return nil, toRPCErr(err) @@ -202,11 +208,13 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth } ctx = newContextWithRPCInfo(ctx, c.failFast) sh := cc.dopts.copts.StatsHandler + var beginTime time.Time if sh != nil { ctx = sh.TagRPC(ctx, &stats.RPCTagInfo{FullMethodName: method, FailFast: c.failFast}) + beginTime = time.Now() begin := &stats.Begin{ Client: true, - BeginTime: time.Now(), + BeginTime: beginTime, FailFast: c.failFast, } sh.HandleRPC(ctx, begin) @@ -214,8 +222,10 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth if err != nil { // Only handle end stats if err != nil. end := &stats.End{ - Client: true, - Error: err, + Client: true, + Error: err, + BeginTime: beginTime, + EndTime: time.Now(), } sh.HandleRPC(ctx, end) } @@ -259,28 +269,28 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth break } - c.stream = s cs := &clientStream{ opts: opts, c: c, desc: desc, codec: c.codec, cp: cp, - dc: cc.dopts.dc, comp: comp, cancel: cancel, - - done: done, - t: t, - s: s, - p: &parser{r: s}, - - tracing: EnableTracing, - trInfo: trInfo, - - statsCtx: ctx, - statsHandler: cc.dopts.copts.StatsHandler, - } + attempt: &csAttempt{ + t: t, + s: s, + p: &parser{r: s}, + done: done, + dc: cc.dopts.dc, + ctx: ctx, + trInfo: trInfo, + statsHandler: sh, + beginTime: beginTime, + }, + } + cs.c.stream = cs + cs.attempt.cs = cs if desc != unaryStreamDesc { // Listen on cc and stream contexts to cleanup when the user closes the // ClientConn or cancels the stream context. In all other cases, an error @@ -292,7 +302,7 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth case <-cc.ctx.Done(): cs.finish(ErrClientConnClosing) case <-ctx.Done(): - cs.finish(toRPCErr(s.Context().Err())) + cs.finish(toRPCErr(ctx.Err())) } }() } @@ -303,46 +313,56 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth type clientStream struct { opts []CallOption c *callInfo + desc *StreamDesc + + codec baseCodec + cp Compressor + comp encoding.Compressor + + cancel context.CancelFunc // cancels all attempts + + sentLast bool // sent an end stream + + mu sync.Mutex // guards finished + finished bool // TODO: replace with atomic cmpxchg or sync.Once? + + attempt *csAttempt // the active client stream attempt + // TODO(hedging): hedging will have multiple attempts simultaneously. +} + +// csAttempt implements a single transport stream attempt within a +// clientStream. +type csAttempt struct { + cs *clientStream t transport.ClientTransport s *transport.Stream p *parser - desc *StreamDesc + done func(balancer.DoneInfo) - codec baseCodec - cp Compressor dc Decompressor - comp encoding.Compressor decomp encoding.Compressor decompSet bool - // cancel is only called when RecvMsg() returns non-nil error, which means - // the stream finishes with error or with io.EOF. - cancel context.CancelFunc - - tracing bool // set to EnableTracing when the clientStream is created. + ctx context.Context // the application's context, wrapped by stats/tracing - mu sync.Mutex - done func(balancer.DoneInfo) - sentLast bool // sent an end stream - finished bool - // trInfo.tr is set when the clientStream is created (if EnableTracing is true), - // and is set to nil when the clientStream's finish method is called. + mu sync.Mutex // guards trInfo.tr + // trInfo.tr is set when created (if EnableTracing is true), + // and cleared when the finish method is called. trInfo traceInfo - // statsCtx keeps the user context for stats handling. - // All stats collection should use the statsCtx (instead of the stream context) - // so that all the generated stats for a particular RPC can be associated in the processing phase. - statsCtx context.Context statsHandler stats.Handler + beginTime time.Time } func (cs *clientStream) Context() context.Context { - return cs.s.Context() + // TODO(retry): commit the current attempt (the context has peer-aware data). + return cs.attempt.context() } func (cs *clientStream) Header() (metadata.MD, error) { - m, err := cs.s.Header() + m, err := cs.attempt.header() if err != nil { + // TODO(retry): maybe retry on error or commit attempt on success. err = toRPCErr(err) cs.finish(err) } @@ -350,20 +370,61 @@ func (cs *clientStream) Header() (metadata.MD, error) { } func (cs *clientStream) Trailer() metadata.MD { - return cs.s.Trailer() + // TODO(retry): on error, maybe retry (trailers-only). + return cs.attempt.trailer() } func (cs *clientStream) SendMsg(m interface{}) (err error) { - // TODO: Check cs.sentLast and error if we already ended the stream. - if cs.tracing { - cs.mu.Lock() - if cs.trInfo.tr != nil { - cs.trInfo.tr.LazyLog(&payload{sent: true, msg: m}, true) - } + // TODO(retry): buffer message for replaying if not committed. + return cs.attempt.sendMsg(m) +} + +func (cs *clientStream) RecvMsg(m interface{}) (err error) { + // TODO(retry): maybe retry on error or commit attempt on success. + return cs.attempt.recvMsg(m) +} + +func (cs *clientStream) CloseSend() error { + cs.attempt.closeSend() + return nil +} + +func (cs *clientStream) finish(err error) { + if err == io.EOF { + // Ending a stream with EOF indicates a success. + err = nil + } + cs.mu.Lock() + if cs.finished { cs.mu.Unlock() + return } + cs.finished = true + cs.mu.Unlock() + // TODO(retry): commit current attempt if necessary. + cs.attempt.finish(err) + for _, o := range cs.opts { + o.after(cs.c) + } + cs.cancel() +} + +func (a *csAttempt) context() context.Context { + return a.s.Context() +} + +func (a *csAttempt) header() (metadata.MD, error) { + return a.s.Header() +} + +func (a *csAttempt) trailer() metadata.MD { + return a.s.Trailer() +} + +func (a *csAttempt) sendMsg(m interface{}) (err error) { // TODO Investigate how to signal the stats handling party. // generate error stats if err != nil && err != io.EOF? + cs := a.cs defer func() { // For non-client-streaming RPCs, we return nil instead of EOF on success // because the generated code requires it. finish is not called; RecvMsg() @@ -372,14 +433,23 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) { err = nil } if err != nil && err != io.EOF { - // Call finish for errors generated by this SendMsg call. (Transport + // Call finish on the client stream for errors generated by this SendMsg + // call, as these indicate problems created by this client. (Transport // errors are converted to an io.EOF error below; the real error will be - // returned from RecvMsg eventually in that case.) + // returned from RecvMsg eventually in that case, or be retried.) cs.finish(err) } }() + // TODO: Check cs.sentLast and error if we already ended the stream. + if EnableTracing { + a.mu.Lock() + if a.trInfo.tr != nil { + a.trInfo.tr.LazyLog(&payload{sent: true, msg: m}, true) + } + a.mu.Unlock() + } var outPayload *stats.OutPayload - if cs.statsHandler != nil { + if a.statsHandler != nil { outPayload = &stats.OutPayload{ Client: true, } @@ -394,18 +464,19 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) { if !cs.desc.ClientStreams { cs.sentLast = true } - err = cs.t.Write(cs.s, hdr, data, &transport.Options{Last: !cs.desc.ClientStreams}) + err = a.t.Write(a.s, hdr, data, &transport.Options{Last: !cs.desc.ClientStreams}) if err == nil { if outPayload != nil { outPayload.SentTime = time.Now() - cs.statsHandler.HandleRPC(cs.statsCtx, outPayload) + a.statsHandler.HandleRPC(a.ctx, outPayload) } return nil } return io.EOF } -func (cs *clientStream) RecvMsg(m interface{}) (err error) { +func (a *csAttempt) recvMsg(m interface{}) (err error) { + cs := a.cs defer func() { if err != nil || !cs.desc.ServerStreams { // err != nil or non-server-streaming indicates end of stream. @@ -413,46 +484,46 @@ func (cs *clientStream) RecvMsg(m interface{}) (err error) { } }() var inPayload *stats.InPayload - if cs.statsHandler != nil { + if a.statsHandler != nil { inPayload = &stats.InPayload{ Client: true, } } - if !cs.decompSet { + if !a.decompSet { // Block until we receive headers containing received message encoding. - if ct := cs.s.RecvCompress(); ct != "" && ct != encoding.Identity { - if cs.dc == nil || cs.dc.Type() != ct { + if ct := a.s.RecvCompress(); ct != "" && ct != encoding.Identity { + if a.dc == nil || a.dc.Type() != ct { // No configured decompressor, or it does not match the incoming // message encoding; attempt to find a registered compressor that does. - cs.dc = nil - cs.decomp = encoding.GetCompressor(ct) + a.dc = nil + a.decomp = encoding.GetCompressor(ct) } } else { // No compression is used; disable our decompressor. - cs.dc = nil + a.dc = nil } // Only initialize this state once per stream. - cs.decompSet = true + a.decompSet = true } - err = recv(cs.p, cs.codec, cs.s, cs.dc, m, *cs.c.maxReceiveMessageSize, inPayload, cs.decomp) + err = recv(a.p, cs.codec, a.s, a.dc, m, *cs.c.maxReceiveMessageSize, inPayload, a.decomp) if err != nil { if err == io.EOF { - if statusErr := cs.s.Status().Err(); statusErr != nil { + if statusErr := a.s.Status().Err(); statusErr != nil { return statusErr } return io.EOF // indicates successful end of stream. } return toRPCErr(err) } - if cs.tracing { - cs.mu.Lock() - if cs.trInfo.tr != nil { - cs.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true) + if EnableTracing { + a.mu.Lock() + if a.trInfo.tr != nil { + a.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true) } - cs.mu.Unlock() + a.mu.Unlock() } if inPayload != nil { - cs.statsHandler.HandleRPC(cs.statsCtx, inPayload) + a.statsHandler.HandleRPC(a.ctx, inPayload) } if cs.desc.ServerStreams { // Subsequent messages should be received by subsequent RecvMsg calls. @@ -461,74 +532,59 @@ func (cs *clientStream) RecvMsg(m interface{}) (err error) { // Special handling for non-server-stream rpcs. // This recv expects EOF or errors, so we don't collect inPayload. - err = recv(cs.p, cs.codec, cs.s, cs.dc, m, *cs.c.maxReceiveMessageSize, nil, cs.decomp) + err = recv(a.p, cs.codec, a.s, a.dc, m, *cs.c.maxReceiveMessageSize, nil, a.decomp) if err == nil { return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want ")) } if err == io.EOF { - return cs.s.Status().Err() // non-server streaming Recv returns nil on success + return a.s.Status().Err() // non-server streaming Recv returns nil on success } return toRPCErr(err) } -func (cs *clientStream) CloseSend() error { +func (a *csAttempt) closeSend() { + cs := a.cs if cs.sentLast { - return nil + return } cs.sentLast = true - cs.t.Write(cs.s, nil, nil, &transport.Options{Last: true}) - // We ignore errors from Write and always return nil here. Any error it - // would return would also be returned by a subsequent RecvMsg call, and the - // user is supposed to always finish the stream by calling RecvMsg until it - // returns err != nil. - return nil + cs.attempt.t.Write(cs.attempt.s, nil, nil, &transport.Options{Last: true}) + // We ignore errors from Write. Any error it would return would also be + // returned by a subsequent RecvMsg call, and the user is supposed to always + // finish the stream by calling RecvMsg until it returns err != nil. } -func (cs *clientStream) finish(err error) { - if err == io.EOF { - // Ending a stream with EOF indicates a success. - err = nil - } - cs.mu.Lock() - defer cs.mu.Unlock() - if cs.finished { - return - } - cs.finished = true - cs.t.CloseStream(cs.s, err) - for _, o := range cs.opts { - o.after(cs.c) - } - if cs.done != nil { - cs.done(balancer.DoneInfo{ +func (a *csAttempt) finish(err error) { + a.mu.Lock() + a.t.CloseStream(a.s, err) + + if a.done != nil { + a.done(balancer.DoneInfo{ Err: err, BytesSent: true, - BytesReceived: cs.s.BytesReceived(), + BytesReceived: a.s.BytesReceived(), }) - cs.done = nil } - if cs.statsHandler != nil { + if a.statsHandler != nil { end := &stats.End{ - Client: true, - EndTime: time.Now(), - Error: err, + Client: true, + BeginTime: a.beginTime, + EndTime: time.Now(), + Error: err, } - cs.statsHandler.HandleRPC(cs.statsCtx, end) - } - cs.cancel() - if !cs.tracing { - return + a.statsHandler.HandleRPC(a.ctx, end) } - if cs.trInfo.tr != nil { + if a.trInfo.tr != nil { if err == nil { - cs.trInfo.tr.LazyPrintf("RPC: [OK]") + a.trInfo.tr.LazyPrintf("RPC: [OK]") } else { - cs.trInfo.tr.LazyPrintf("RPC: [%v]", err) - cs.trInfo.tr.SetError() + a.trInfo.tr.LazyPrintf("RPC: [%v]", err) + a.trInfo.tr.SetError() } - cs.trInfo.tr.Finish() - cs.trInfo.tr = nil + a.trInfo.tr.Finish() + a.trInfo.tr = nil } + a.mu.Unlock() } // ServerStream defines the interface a server stream has to satisfy. @@ -552,6 +608,7 @@ type ServerStream interface { // serverStream implements a server side Stream. type serverStream struct { + ctx context.Context t transport.ServerTransport s *transport.Stream p *parser @@ -572,7 +629,7 @@ type serverStream struct { } func (ss *serverStream) Context() context.Context { - return ss.s.Context() + return ss.ctx } func (ss *serverStream) SetHeader(md metadata.MD) error { @@ -675,9 +732,9 @@ func (ss *serverStream) RecvMsg(m interface{}) (err error) { // MethodFromServerStream returns the method string for the input stream. // The returned string is in the format of "/service/method". func MethodFromServerStream(stream ServerStream) (string, bool) { - s, ok := transport.StreamFromContext(stream.Context()) - if !ok { - return "", ok + s := serverTransportStreamFromContext(stream.Context()) + if s == nil { + return "", false } - return s.Method(), ok + return s.Method(), true } diff --git a/google.golang.org/grpc/transport/handler_server.go b/google.golang.org/grpc/transport/handler_server.go index 451d7e62..1a5e96c5 100644 --- a/google.golang.org/grpc/transport/handler_server.go +++ b/google.golang.org/grpc/transport/handler_server.go @@ -98,7 +98,7 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats sta for _, v := range vv { v, err := decodeMetadataHeader(k, v) if err != nil { - return nil, streamErrorf(codes.InvalidArgument, "malformed binary metadata: %v", err) + return nil, streamErrorf(codes.Internal, "malformed binary metadata: %v", err) } metakv = append(metakv, k, v) } @@ -354,8 +354,7 @@ func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), trace pr.AuthInfo = credentials.TLSInfo{State: *req.TLS} } ctx = metadata.NewIncomingContext(ctx, ht.headerMD) - ctx = peer.NewContext(ctx, pr) - s.ctx = newContextWithStream(ctx, s) + s.ctx = peer.NewContext(ctx, pr) if ht.stats != nil { s.ctx = ht.stats.TagRPC(s.ctx, &stats.RPCTagInfo{FullMethodName: s.method}) inHeader := &stats.InHeader{ diff --git a/google.golang.org/grpc/transport/http2_client.go b/google.golang.org/grpc/transport/http2_client.go index 56b434ef..8b5be0d6 100644 --- a/google.golang.org/grpc/transport/http2_client.go +++ b/google.golang.org/grpc/transport/http2_client.go @@ -121,18 +121,6 @@ func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error } func isTemporary(err error) bool { - switch err { - case io.EOF: - // Connection closures may be resolved upon retry, and are thus - // treated as temporary. - return true - case context.DeadlineExceeded: - // In Go 1.7, context.DeadlineExceeded implements Timeout(), and this - // special case is not needed. Until then, we need to keep this - // clause. - return true - } - switch err := err.(type) { case interface { Temporary() bool @@ -145,7 +133,7 @@ func isTemporary(err error) bool { // temporary. return err.Timeout() } - return false + return true } // newHTTP2Client constructs a connected ClientTransport to addr based on HTTP2 @@ -181,10 +169,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr TargetInfo, opts Conne scheme = "https" conn, authInfo, err = creds.ClientHandshake(connectCtx, addr.Authority, conn) if err != nil { - // Credentials handshake errors are typically considered permanent - // to avoid retrying on e.g. bad certificates. - temp := isTemporary(err) - return nil, connectionErrorf(temp, err, "transport: authentication handshake failed: %v", err) + return nil, connectionErrorf(isTemporary(err), err, "transport: authentication handshake failed: %v", err) } isSecure = true } diff --git a/google.golang.org/grpc/transport/http2_server.go b/google.golang.org/grpc/transport/http2_server.go index 24c2c7e1..97b214c6 100644 --- a/google.golang.org/grpc/transport/http2_server.go +++ b/google.golang.org/grpc/transport/http2_server.go @@ -307,10 +307,6 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( pr.AuthInfo = t.authInfo } s.ctx = peer.NewContext(s.ctx, pr) - // Cache the current stream to the context so that the server application - // can find out. Required when the server wants to send some metadata - // back to the client (unary call only). - s.ctx = newContextWithStream(s.ctx, s) // Attach the received metadata to the context. if len(state.mdata) > 0 { s.ctx = metadata.NewIncomingContext(s.ctx, state.mdata) @@ -896,9 +892,6 @@ func (t *http2Server) Write(s *Stream, hdr []byte, data []byte, opts *Options) e // ltq is only a soft limit. streamQuota -= size p := r[:size] - // Reset ping strikes when sending data since this might cause - // the peer to send ping. - atomic.StoreUint32(&t.resetPingStrikes, 1) success := func() { ltq := ltq t.controlBuf.put(&dataFrame{streamID: s.id, endStream: false, d: p, f: func() { @@ -1013,6 +1006,9 @@ var goAwayPing = &ping{data: [8]byte{1, 6, 1, 8, 0, 3, 3, 9}} func (t *http2Server) itemHandler(i item) error { switch i := i.(type) { case *dataFrame: + // Reset ping strikes when sending data since this might cause + // the peer to send ping. + atomic.StoreUint32(&t.resetPingStrikes, 1) if err := t.framer.fr.WriteData(i.streamID, i.endStream, i.d); err != nil { return err } diff --git a/google.golang.org/grpc/transport/http_util.go b/google.golang.org/grpc/transport/http_util.go index 34476773..de37e38e 100644 --- a/google.golang.org/grpc/transport/http_util.go +++ b/google.golang.org/grpc/transport/http_util.go @@ -70,7 +70,7 @@ var ( http2.ErrCodeConnect: codes.Internal, http2.ErrCodeEnhanceYourCalm: codes.ResourceExhausted, http2.ErrCodeInadequateSecurity: codes.PermissionDenied, - http2.ErrCodeHTTP11Required: codes.FailedPrecondition, + http2.ErrCodeHTTP11Required: codes.Internal, } statusCodeConvTab = map[codes.Code]http2.ErrCode{ codes.Internal: http2.ErrCodeInternal, @@ -283,7 +283,7 @@ func (d *decodeState) processHeaderField(f hpack.HeaderField) error { case "content-type": contentSubtype, validContentType := contentSubtype(f.Value) if !validContentType { - return streamErrorf(codes.FailedPrecondition, "transport: received the unexpected content-type %q", f.Value) + return streamErrorf(codes.Internal, "transport: received the unexpected content-type %q", f.Value) } d.contentSubtype = contentSubtype // TODO: do we want to propagate the whole content-type in the metadata, diff --git a/google.golang.org/grpc/transport/transport.go b/google.golang.org/grpc/transport/transport.go index e68f89ec..e0c1e343 100644 --- a/google.golang.org/grpc/transport/transport.go +++ b/google.golang.org/grpc/transport/transport.go @@ -366,6 +366,14 @@ func (s *Stream) SetHeader(md metadata.MD) error { return nil } +// SendHeader sends the given header metadata. The given metadata is +// combined with any metadata set by previous calls to SetHeader and +// then written to the transport stream. +func (s *Stream) SendHeader(md metadata.MD) error { + t := s.ServerTransport() + return t.WriteHeader(s, md) +} + // SetTrailer sets the trailer metadata which will be sent with the RPC status // by the server. This can be called multiple times. Server side only. func (s *Stream) SetTrailer(md metadata.MD) error { @@ -445,21 +453,6 @@ func (s *Stream) GoString() string { return fmt.Sprintf("", s, s.method) } -// The key to save transport.Stream in the context. -type streamKey struct{} - -// newContextWithStream creates a new context from ctx and attaches stream -// to it. -func newContextWithStream(ctx context.Context, stream *Stream) context.Context { - return context.WithValue(ctx, streamKey{}, stream) -} - -// StreamFromContext returns the stream saved in ctx. -func StreamFromContext(ctx context.Context) (s *Stream, ok bool) { - s, ok = ctx.Value(streamKey{}).(*Stream) - return -} - // state of transport type transportState int diff --git a/gopkg.in/inf.v0/dec.go b/gopkg.in/inf.v0/dec.go index 3b4afedf..26548b63 100644 --- a/gopkg.in/inf.v0/dec.go +++ b/gopkg.in/inf.v0/dec.go @@ -104,7 +104,7 @@ var bigInt = [...]*big.Int{ var exp10cache [64]big.Int = func() [64]big.Int { e10, e10i := [64]big.Int{}, bigInt[1] - for i, _ := range e10 { + for i := range e10 { e10[i].Set(e10i) e10i = new(big.Int).Mul(e10i, bigInt[10]) } diff --git a/gopkg.in/square/go-jose.v2/jwk.go b/gopkg.in/square/go-jose.v2/jwk.go index d81bc407..d89046a0 100644 --- a/gopkg.in/square/go-jose.v2/jwk.go +++ b/gopkg.in/square/go-jose.v2/jwk.go @@ -148,17 +148,10 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) { if err == nil { *k = JSONWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use} - } - k.Certificates = make([]*x509.Certificate, len(raw.X5c)) - for i, cert := range raw.X5c { - raw, err := base64.StdEncoding.DecodeString(cert) - if err != nil { - return err - } - k.Certificates[i], err = x509.ParseCertificate(raw) + k.Certificates, err = parseCertificateChain(raw.X5c) if err != nil { - return err + return fmt.Errorf("failed to unmarshal x5c field: %s", err) } } diff --git a/gopkg.in/square/go-jose.v2/jws.go b/gopkg.in/square/go-jose.v2/jws.go index d7d3d600..8b59b6ab 100644 --- a/gopkg.in/square/go-jose.v2/jws.go +++ b/gopkg.in/square/go-jose.v2/jws.go @@ -93,7 +93,7 @@ func (sig Signature) mergedHeaders() rawHeader { } // Compute data to be signed -func (obj JSONWebSignature) computeAuthData(signature *Signature) []byte { +func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature) []byte { var serializedProtected string if signature.original != nil && signature.original.Protected != nil { @@ -106,7 +106,7 @@ func (obj JSONWebSignature) computeAuthData(signature *Signature) []byte { return []byte(fmt.Sprintf("%s.%s", serializedProtected, - base64.RawURLEncoding.EncodeToString(obj.payload))) + base64.RawURLEncoding.EncodeToString(payload))) } // parseSignedFull parses a message in full format. diff --git a/gopkg.in/square/go-jose.v2/shared.go b/gopkg.in/square/go-jose.v2/shared.go index 4c19dc38..e6ab91da 100644 --- a/gopkg.in/square/go-jose.v2/shared.go +++ b/gopkg.in/square/go-jose.v2/shared.go @@ -18,6 +18,8 @@ package jose import ( "crypto/elliptic" + "crypto/x509" + "encoding/base64" "errors" "fmt" @@ -141,6 +143,7 @@ const ( headerEPK = "epk" // *JSONWebKey headerIV = "iv" // *byteBuffer headerTag = "tag" // *byteBuffer + headerX5c = "x5c" // []*x509.Certificate headerJWK = "jwk" // *JSONWebKey headerKeyID = "kid" // string @@ -162,11 +165,34 @@ type Header struct { Algorithm string Nonce string - // Any headers not recognised above get unmarshaled from JSON in a generic - // manner and placed in this map. + // Unverified certificate chain parsed from x5c header. + certificates []*x509.Certificate + + // Any headers not recognised above get unmarshaled + // from JSON in a generic manner and placed in this map. ExtraHeaders map[HeaderKey]interface{} } +// Certificates verifies & returns the certificate chain present +// in the x5c header field of a message, if one was present. Returns +// an error if there was no x5c header present or the chain could +// not be validated with the given verify options. +func (h Header) Certificates(opts x509.VerifyOptions) ([][]*x509.Certificate, error) { + if len(h.certificates) == 0 { + return nil, errors.New("square/go-jose: no x5c header present in message") + } + + leaf := h.certificates[0] + if opts.Intermediates == nil { + opts.Intermediates = x509.NewCertPool() + for _, intermediate := range h.certificates[1:] { + opts.Intermediates.AddCert(intermediate) + } + } + + return leaf.Verify(opts) +} + func (parsed rawHeader) set(k HeaderKey, v interface{}) error { b, err := json.Marshal(v) if err != nil { @@ -333,6 +359,18 @@ func (parsed rawHeader) sanitized() (h Header, err error) { return } h.Nonce = s + case headerX5c: + c := []string{} + err = json.Unmarshal(*v, &c) + if err != nil { + err = fmt.Errorf("failed to unmarshal x5c header: %v: %#v", err, string(*v)) + return + } + h.certificates, err = parseCertificateChain(c) + if err != nil { + err = fmt.Errorf("failed to unmarshal x5c header: %v: %#v", err, string(*v)) + return + } default: if h.ExtraHeaders == nil { h.ExtraHeaders = map[HeaderKey]interface{}{} @@ -349,6 +387,21 @@ func (parsed rawHeader) sanitized() (h Header, err error) { return } +func parseCertificateChain(chain []string) ([]*x509.Certificate, error) { + out := make([]*x509.Certificate, len(chain)) + for i, cert := range chain { + raw, err := base64.StdEncoding.DecodeString(cert) + if err != nil { + return nil, err + } + out[i], err = x509.ParseCertificate(raw) + if err != nil { + return nil, err + } + } + return out, nil +} + func (dst rawHeader) isSet(k HeaderKey) bool { dvr := dst[k] if dvr == nil { diff --git a/gopkg.in/square/go-jose.v2/signing.go b/gopkg.in/square/go-jose.v2/signing.go index 13e956d6..bedfac73 100644 --- a/gopkg.in/square/go-jose.v2/signing.go +++ b/gopkg.in/square/go-jose.v2/signing.go @@ -280,34 +280,46 @@ func (ctx *genericSigner) Options() SignerOptions { // payload header. You cannot assume that the key received in a payload is // trusted. func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) { - verifier, err := newVerifier(verificationKey) + err := obj.DetachedVerify(obj.payload, verificationKey) if err != nil { return nil, err } + return obj.payload, nil +} + +// DetachedVerify validates a detached signature on the given payload. In +// most cases, you will probably want to use Verify instead. DetachedVerify +// is only useful if you have a payload and signature that are separated from +// each other. +func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey interface{}) error { + verifier, err := newVerifier(verificationKey) + if err != nil { + return err + } if len(obj.Signatures) > 1 { - return nil, errors.New("square/go-jose: too many signatures in payload; expecting only one") + return errors.New("square/go-jose: too many signatures in payload; expecting only one") } signature := obj.Signatures[0] headers := signature.mergedHeaders() critical, err := headers.getCritical() if err != nil { - return nil, err + return err } if len(critical) > 0 { // Unsupported crit header - return nil, ErrCryptoFailure + return ErrCryptoFailure } - input := obj.computeAuthData(&signature) + input := obj.computeAuthData(payload, &signature) alg := headers.getSignatureAlgorithm() err = verifier.verifyPayload(input, signature.Signature, alg) if err == nil { - return obj.payload, nil + return nil } - return nil, ErrCryptoFailure + return ErrCryptoFailure } // VerifyMulti validates (one of the multiple) signatures on the object and @@ -315,10 +327,27 @@ func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) // object and the payload. We return the signature and index to guarantee that // callers are getting the verified value. func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signature, []byte, error) { - verifier, err := newVerifier(verificationKey) + idx, sig, err := obj.DetachedVerifyMulti(obj.payload, verificationKey) if err != nil { return -1, Signature{}, nil, err } + return idx, sig, obj.payload, nil +} + +// DetachedVerifyMulti validates a detached signature on the given payload with +// a signature/object that has potentially multiple signers. This returns the index +// of the signature that was verified, along with the signature object. We return +// the signature and index to guarantee that callers are getting the verified value. +// +// In most cases, you will probably want to use Verify or VerifyMulti instead. +// DetachedVerifyMulti is only useful if you have a payload and signature that are +// separated from each other, and the signature can have multiple signers at the +// same time. +func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey interface{}) (int, Signature, error) { + verifier, err := newVerifier(verificationKey) + if err != nil { + return -1, Signature{}, err + } for i, signature := range obj.Signatures { headers := signature.mergedHeaders() @@ -331,13 +360,13 @@ func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signa continue } - input := obj.computeAuthData(&signature) + input := obj.computeAuthData(payload, &signature) alg := headers.getSignatureAlgorithm() err = verifier.verifyPayload(input, signature.Signature, alg) if err == nil { - return i, signature, obj.payload, nil + return i, signature, nil } } - return -1, Signature{}, nil, ErrCryptoFailure + return -1, Signature{}, ErrCryptoFailure } diff --git a/gopkg.in/yaml.v2/apic.go b/gopkg.in/yaml.v2/apic.go index 3e24a0d7..1f7e87e6 100644 --- a/gopkg.in/yaml.v2/apic.go +++ b/gopkg.in/yaml.v2/apic.go @@ -468,7 +468,7 @@ func yaml_event_delete(event *yaml_event_t) { // } context // tag_directive *yaml_tag_directive_t // -// context.error = YAML_NO_ERROR // Eliminate a compliler warning. +// context.error = YAML_NO_ERROR // Eliminate a compiler warning. // // assert(document) // Non-NULL document object is expected. // diff --git a/gopkg.in/yaml.v2/decode.go b/gopkg.in/yaml.v2/decode.go index c8eac164..e4e56e28 100644 --- a/gopkg.in/yaml.v2/decode.go +++ b/gopkg.in/yaml.v2/decode.go @@ -113,6 +113,10 @@ func (p *parser) fail() { var line int if p.parser.problem_mark.line != 0 { line = p.parser.problem_mark.line + // Scanner errors don't iterate line before returning error + if p.parser.error == yaml_SCANNER_ERROR { + line++ + } } else if p.parser.context_mark.line != 0 { line = p.parser.context_mark.line } @@ -430,6 +434,7 @@ func (d *decoder) scalar(n *node, out reflect.Value) bool { // reasons we set it as a string, so that code that unmarshals // timestamp-like values into interface{} will continue to // see a string and not a time.Time. + // TODO(v3) Drop this. out.Set(reflect.ValueOf(n.value)) } else { out.Set(reflect.ValueOf(resolved)) @@ -542,6 +547,10 @@ func (d *decoder) sequence(n *node, out reflect.Value) (good bool) { switch out.Kind() { case reflect.Slice: out.Set(reflect.MakeSlice(out.Type(), l, l)) + case reflect.Array: + if l != out.Len() { + failf("invalid array: want %d elements but got %d", out.Len(), l) + } case reflect.Interface: // No type hints. Will have to use a generic sequence. iface = out @@ -560,7 +569,9 @@ func (d *decoder) sequence(n *node, out reflect.Value) (good bool) { j++ } } - out.Set(out.Slice(0, j)) + if out.Kind() != reflect.Array { + out.Set(out.Slice(0, j)) + } if iface.IsValid() { iface.Set(out) } diff --git a/gopkg.in/yaml.v2/emitterc.go b/gopkg.in/yaml.v2/emitterc.go index cf0db118..a1c2cc52 100644 --- a/gopkg.in/yaml.v2/emitterc.go +++ b/gopkg.in/yaml.v2/emitterc.go @@ -843,7 +843,7 @@ func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event return true } -// Write an achor. +// Write an anchor. func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool { if emitter.anchor_data.anchor == nil { return true diff --git a/gopkg.in/yaml.v2/encode.go b/gopkg.in/yaml.v2/encode.go index 1e730eff..a14435e8 100644 --- a/gopkg.in/yaml.v2/encode.go +++ b/gopkg.in/yaml.v2/encode.go @@ -131,7 +131,7 @@ func (e *encoder) marshal(tag string, in reflect.Value) { } else { e.structv(tag, in) } - case reflect.Slice: + case reflect.Slice, reflect.Array: if in.Type().Elem() == mapItemType { e.itemsv(tag, in) } else { @@ -328,14 +328,18 @@ func (e *encoder) uintv(tag string, in reflect.Value) { func (e *encoder) timev(tag string, in reflect.Value) { t := in.Interface().(time.Time) - if tag == "" { - tag = yaml_TIMESTAMP_TAG - } - e.emitScalar(t.Format(time.RFC3339Nano), "", tag, yaml_PLAIN_SCALAR_STYLE) + s := t.Format(time.RFC3339Nano) + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) } func (e *encoder) floatv(tag string, in reflect.Value) { - s := strconv.FormatFloat(in.Float(), 'g', -1, 64) + // Issue #352: When formatting, use the precision of the underlying value + precision := 64 + if in.Kind() == reflect.Float32 { + precision = 32 + } + + s := strconv.FormatFloat(in.Float(), 'g', -1, precision) switch s { case "+Inf": s = ".inf" diff --git a/gopkg.in/yaml.v2/readerc.go b/gopkg.in/yaml.v2/readerc.go index f4507917..7c1f5fac 100644 --- a/gopkg.in/yaml.v2/readerc.go +++ b/gopkg.in/yaml.v2/readerc.go @@ -93,9 +93,18 @@ func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { panic("read handler must be set") } + // [Go] This function was changed to guarantee the requested length size at EOF. + // The fact we need to do this is pretty awful, but the description above implies + // for that to be the case, and there are tests + // If the EOF flag is set and the raw buffer is empty, do nothing. if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { - return true + // [Go] ACTUALLY! Read the documentation of this function above. + // This is just broken. To return true, we need to have the + // given length in the buffer. Not doing that means every single + // check that calls this function to make sure the buffer has a + // given length is Go) panicking; or C) accessing invalid memory. + //return true } // Return if the buffer contains enough characters. @@ -389,6 +398,15 @@ func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { break } } + // [Go] Read the documentation of this function above. To return true, + // we need to have the given length in the buffer. Not doing that means + // every single check that calls this function to make sure the buffer + // has a given length is Go) panicking; or C) accessing invalid memory. + // This happens here due to the EOF above breaking early. + for buffer_len < length { + parser.buffer[buffer_len] = 0 + buffer_len++ + } parser.buffer = parser.buffer[:buffer_len] return true } diff --git a/gopkg.in/yaml.v2/resolve.go b/gopkg.in/yaml.v2/resolve.go index ea90bd5e..6c151db6 100644 --- a/gopkg.in/yaml.v2/resolve.go +++ b/gopkg.in/yaml.v2/resolve.go @@ -92,6 +92,19 @@ func resolve(tag string, in string) (rtag string, out interface{}) { switch tag { case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG: return + case yaml_FLOAT_TAG: + if rtag == yaml_INT_TAG { + switch v := out.(type) { + case int64: + rtag = yaml_FLOAT_TAG + out = float64(v) + return + case int: + rtag = yaml_FLOAT_TAG + out = float64(v) + return + } + } } failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) }() @@ -167,12 +180,12 @@ func resolve(tag string, in string) (rtag string, out interface{}) { return yaml_INT_TAG, uintv } } else if strings.HasPrefix(plain, "-0b") { - intv, err := strconv.ParseInt(plain[3:], 2, 64) + intv, err := strconv.ParseInt("-" + plain[3:], 2, 64) if err == nil { - if intv == int64(int(intv)) { - return yaml_INT_TAG, -int(intv) + if true || intv == int64(int(intv)) { + return yaml_INT_TAG, int(intv) } else { - return yaml_INT_TAG, -intv + return yaml_INT_TAG, intv } } } @@ -211,10 +224,10 @@ func encodeBase64(s string) string { // This is a subset of the formats allowed by the regular expression // defined at http://yaml.org/type/timestamp.html. var allowedTimestampFormats = []string{ - "2006-1-2T15:4:5Z07:00", - "2006-1-2t15:4:5Z07:00", // RFC3339 with lower-case "t". - "2006-1-2 15:4:5", // space separated with no time zone - "2006-1-2", // date only + "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields. + "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t". + "2006-1-2 15:4:5.999999999", // space separated with no time zone + "2006-1-2", // date only // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" // from the set of examples. } diff --git a/gopkg.in/yaml.v2/scannerc.go b/gopkg.in/yaml.v2/scannerc.go index 492a9845..077fd1dd 100644 --- a/gopkg.in/yaml.v2/scannerc.go +++ b/gopkg.in/yaml.v2/scannerc.go @@ -871,12 +871,6 @@ func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { required := parser.flow_level == 0 && parser.indent == parser.mark.column - // A simple key is required only when it is the first token in the current - // line. Therefore it is always allowed. But we add a check anyway. - if required && !parser.simple_key_allowed { - panic("should not happen") - } - // // If the current position may start a simple key, save it. // @@ -2475,6 +2469,10 @@ func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, si } } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + // Check if we are at the end of the scalar. if single { if parser.buffer[parser.buffer_pos] == '\'' { @@ -2487,10 +2485,6 @@ func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, si } // Consume blank characters. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { if is_blank(parser.buffer, parser.buffer_pos) { // Consume a space or a tab character. @@ -2647,10 +2641,10 @@ func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) b for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { if is_blank(parser.buffer, parser.buffer_pos) { - // Check for tab character that abuse indentation. + // Check for tab characters that abuse indentation. if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) { yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", - start_mark, "found a tab character that violate indentation") + start_mark, "found a tab character that violates indentation") return false } diff --git a/gopkg.in/yaml.v2/sorter.go b/gopkg.in/yaml.v2/sorter.go index 5958822f..4c45e660 100644 --- a/gopkg.in/yaml.v2/sorter.go +++ b/gopkg.in/yaml.v2/sorter.go @@ -51,6 +51,15 @@ func (l keyList) Less(i, j int) bool { } var ai, bi int var an, bn int64 + if ar[i] == '0' || br[i] == '0' { + for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- { + if ar[j] != '0' { + an = 1 + bn = 1 + break + } + } + } for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { an = an*10 + int64(ar[ai]-'0') } diff --git a/gopkg.in/yaml.v2/yaml.go b/gopkg.in/yaml.v2/yaml.go index 483aae58..de85aa4c 100644 --- a/gopkg.in/yaml.v2/yaml.go +++ b/gopkg.in/yaml.v2/yaml.go @@ -157,8 +157,8 @@ func unmarshal(in []byte, out interface{}, strict bool) (err error) { // of the generated document will reflect the structure of the value itself. // Maps and pointers (to struct, string, int, etc) are accepted as the in value. // -// Struct fields are only unmarshalled if they are exported (have an upper case -// first letter), and are unmarshalled using the field name lowercased as the +// Struct fields are only marshalled if they are exported (have an upper case +// first letter), and are marshalled using the field name lowercased as the // default key. Custom keys may be defined via the "yaml" name in the field // tag: the content preceding the first comma is used as the key, and the // following comma-separated options are used to tweak the marshalling process. diff --git a/istio.io/api/networking/v1alpha3/external_service.pb.go b/istio.io/api/networking/v1alpha3/external_service.pb.go index c20f6426..32089906 100644 --- a/istio.io/api/networking/v1alpha3/external_service.pb.go +++ b/istio.io/api/networking/v1alpha3/external_service.pb.go @@ -19,18 +19,18 @@ var _ = math.Inf type ExternalService_Discovery int32 const ( - // If set to "none", the proxy will assume that incoming connections + // If set to "NONE", the proxy will assume that incoming connections // have already been resolved (to a specific destination IP // address). Such connections are typically routed via the proxy using // mechanisms such as IP table REDIRECT/ eBPF. After performing any // routing related transformations, the proxy will forward the // connection to the IP address to which the connection was bound. ExternalService_NONE ExternalService_Discovery = 0 - // If set to "static", the proxy will use the IP addresses specified in + // If set to "STATIC", the proxy will use the IP addresses specified in // endpoints (See below) as the backing nodes associated with the // external service. ExternalService_STATIC ExternalService_Discovery = 1 - // If set to "dns", the proxy will attempt to resolve the DNS address + // If set to "DNS", the proxy will attempt to resolve the DNS address // during request processing. If no endpoints are specified, the proxy // will resolve the DNS address specified in the hosts field, if // wildcards are not used. If endpoints are specified, the DNS @@ -76,7 +76,7 @@ func (ExternalService_Discovery) EnumDescriptor() ([]byte, []int) { // ports: // - number: 443 // name: example-http -// protocol: http # not HTTPS. +// protocol: HTTP # not HTTPS. // discovery: DNS // // and a destination rule to initiate TLS connections to the external service. @@ -105,7 +105,7 @@ func (ExternalService_Discovery) EnumDescriptor() ([]byte, []int) { // ports: // - number: 27018 // name: mongodb -// protocol: mongo +// protocol: MONGO // discovery: STATIC // endpoints: // - address: 2.2.2.2 @@ -141,7 +141,7 @@ func (ExternalService_Discovery) EnumDescriptor() ([]byte, []int) { // ports: // - number: 80 // name: http -// protocol: http +// protocol: HTTP // discovery: NONE // // For HTTP based services, it is possible to create a virtual service @@ -162,7 +162,7 @@ func (ExternalService_Discovery) EnumDescriptor() ([]byte, []int) { // ports: // - number: 443 // name: https -// protocol: http +// protocol: HTTP // discovery: DNS // endpoints: // - address: us.foo.bar.com diff --git a/istio.io/api/networking/v1alpha3/external_service.proto b/istio.io/api/networking/v1alpha3/external_service.proto index 397aaa22..0c66941c 100644 --- a/istio.io/api/networking/v1alpha3/external_service.proto +++ b/istio.io/api/networking/v1alpha3/external_service.proto @@ -39,7 +39,7 @@ option go_package = "istio.io/api/networking/v1alpha3"; // ports: // - number: 443 // name: example-http -// protocol: http # not HTTPS. +// protocol: HTTP # not HTTPS. // discovery: DNS // // and a destination rule to initiate TLS connections to the external service. @@ -68,7 +68,7 @@ option go_package = "istio.io/api/networking/v1alpha3"; // ports: // - number: 27018 // name: mongodb -// protocol: mongo +// protocol: MONGO // discovery: STATIC // endpoints: // - address: 2.2.2.2 @@ -104,7 +104,7 @@ option go_package = "istio.io/api/networking/v1alpha3"; // ports: // - number: 80 // name: http -// protocol: http +// protocol: HTTP // discovery: NONE // // For HTTP based services, it is possible to create a virtual service @@ -125,7 +125,7 @@ option go_package = "istio.io/api/networking/v1alpha3"; // ports: // - number: 443 // name: https -// protocol: http +// protocol: HTTP // discovery: DNS // endpoints: // - address: us.foo.bar.com @@ -180,7 +180,7 @@ message ExternalService { // Different ways of discovering the IP addresses associated with the // service. enum Discovery { - // If set to "none", the proxy will assume that incoming connections + // If set to "NONE", the proxy will assume that incoming connections // have already been resolved (to a specific destination IP // address). Such connections are typically routed via the proxy using // mechanisms such as IP table REDIRECT/ eBPF. After performing any @@ -188,12 +188,12 @@ message ExternalService { // connection to the IP address to which the connection was bound. NONE = 0; - // If set to "static", the proxy will use the IP addresses specified in + // If set to "STATIC", the proxy will use the IP addresses specified in // endpoints (See below) as the backing nodes associated with the // external service. STATIC = 1; - // If set to "dns", the proxy will attempt to resolve the DNS address + // If set to "DNS", the proxy will attempt to resolve the DNS address // during request processing. If no endpoints are specified, the proxy // will resolve the DNS address specified in the hosts field, if // wildcards are not used. If endpoints are specified, the DNS diff --git a/istio.io/api/networking/v1alpha3/gateway.pb.go b/istio.io/api/networking/v1alpha3/gateway.pb.go index 9c23f6e9..ea5a5b85 100644 --- a/istio.io/api/networking/v1alpha3/gateway.pb.go +++ b/istio.io/api/networking/v1alpha3/gateway.pb.go @@ -18,14 +18,14 @@ var _ = math.Inf type Server_TLSOptions_TLSmode int32 const ( - // If set to "passthrough", the proxy will forward the connection + // If set to "PASSTHROUGH", the proxy will forward the connection // to the upstream server selected based on the SNI string presented // by the client. Server_TLSOptions_PASSTHROUGH Server_TLSOptions_TLSmode = 0 - // If set to "simple", the proxy will secure connections with + // If set to "SIMPLE", the proxy will secure connections with // standard TLS semantics. Server_TLSOptions_SIMPLE Server_TLSOptions_TLSmode = 1 - // If set to "mutual", the proxy will secure connections to the + // If set to "MUTUAL", the proxy will secure connections to the // upstream using mutual TLS by presenting client certificates for // authentication. Server_TLSOptions_MUTUAL Server_TLSOptions_TLSmode = 2 @@ -72,6 +72,7 @@ func (Server_TLSOptions_TLSmode) EnumDescriptor() ([]byte, []int) { // - port: // number: 80 // name: http +// protocol: HTTP // hosts: // - uk.bookinfo.com // - eu.bookinfo.com @@ -80,20 +81,22 @@ func (Server_TLSOptions_TLSmode) EnumDescriptor() ([]byte, []int) { // - port: // number: 443 // name: https +// protocol: HTTPS // hosts: // - uk.bookinfo.com // - eu.bookinfo.com // tls: -// mode: simple #enables HTTPS on this port +// mode: SIMPLE #enables HTTPS on this port // serverCertificate: /etc/certs/servercert.pem // privateKey: /etc/certs/privatekey.pem // - port: // number: 9080 // name: http-wildcard +// protocol: HTTP // # no hosts implies wildcard match // - port: // number: 2379 #to expose internal service via external port 2379 -// name: Mongo +// name: mongo // protocol: MONGO // // The gateway specification above describes the L4-L6 properties of a load @@ -157,7 +160,7 @@ func (Server_TLSOptions_TLSmode) EnumDescriptor() ([]byte, []int) { // name: bookinfo-Mongo // spec: // hosts: -// - Mongosvr #name of Mongo service +// - mongosvr #name of Mongo service // gateways: // - my-gateway // tcp: @@ -211,6 +214,7 @@ func (m *Gateway) GetSelector() map[string]string { // servers: // - port: // number: 80 +// name: http2 // protocol: HTTP2 // // Another example @@ -225,6 +229,7 @@ func (m *Gateway) GetSelector() map[string]string { // servers: // - port: // number: 27018 +// name: mongo // protocol: MONGO // // The following is an example of TLS configuration for port 443 @@ -239,9 +244,10 @@ func (m *Gateway) GetSelector() map[string]string { // servers: // - port: // number: 443 -// protocol: HTTP +// name: https +// protocol: HTTPS // tls: -// mode: simple +// mode: SIMPLE // serverCertificate: /etc/certs/server.pem // privateKey: /etc/certs/privatekey.pem // @@ -299,13 +305,13 @@ type Server_TLSOptions struct { // secured using TLS. The value of this field determines how TLS is // enforced. Mode Server_TLSOptions_TLSmode `protobuf:"varint,2,opt,name=mode,proto3,enum=istio.networking.v1alpha3.Server_TLSOptions_TLSmode" json:"mode,omitempty"` - // REQUIRED if mode is "simple" or "mutual". The path to the file + // REQUIRED if mode is "SIMPLE" or "MUTUAL". The path to the file // holding the server-side TLS certificate to use. ServerCertificate string `protobuf:"bytes,3,opt,name=server_certificate,json=serverCertificate,proto3" json:"server_certificate,omitempty"` - // REQUIRED if mode is "simple" or "mutual". The path to the file + // REQUIRED if mode is "SIMPLE" or "MUTUAL". The path to the file // holding the server's private key. PrivateKey string `protobuf:"bytes,4,opt,name=private_key,json=privateKey,proto3" json:"private_key,omitempty"` - // REQUIRED if mode is "mutual". The path to a file containing + // REQUIRED if mode is "MUTUAL". The path to a file containing // certificate authority certificates to use in verifying a presented // client side certificate. CaCertificates string `protobuf:"bytes,5,opt,name=ca_certificates,json=caCertificates,proto3" json:"ca_certificates,omitempty"` @@ -365,7 +371,7 @@ func (m *Server_TLSOptions) GetSubjectAltNames() []string { type Port struct { // REQUIRED: A valid non-negative integer port number. Number uint32 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"` - // The protocol exposed on the port. + // REQUIRED: The protocol exposed on the port. // MUST BE one of HTTP|HTTPS|GRPC|HTTP2|MONGO|TCP. Protocol string `protobuf:"bytes,2,opt,name=protocol,proto3" json:"protocol,omitempty"` // Label assigned to the port. diff --git a/istio.io/api/networking/v1alpha3/gateway.proto b/istio.io/api/networking/v1alpha3/gateway.proto index a16bad6f..05f73a9b 100644 --- a/istio.io/api/networking/v1alpha3/gateway.proto +++ b/istio.io/api/networking/v1alpha3/gateway.proto @@ -41,6 +41,7 @@ option go_package = "istio.io/api/networking/v1alpha3"; // - port: // number: 80 // name: http +// protocol: HTTP // hosts: // - uk.bookinfo.com // - eu.bookinfo.com @@ -49,20 +50,22 @@ option go_package = "istio.io/api/networking/v1alpha3"; // - port: // number: 443 // name: https +// protocol: HTTPS // hosts: // - uk.bookinfo.com // - eu.bookinfo.com // tls: -// mode: simple #enables HTTPS on this port +// mode: SIMPLE #enables HTTPS on this port // serverCertificate: /etc/certs/servercert.pem // privateKey: /etc/certs/privatekey.pem // - port: // number: 9080 // name: http-wildcard +// protocol: HTTP // # no hosts implies wildcard match // - port: // number: 2379 #to expose internal service via external port 2379 -// name: Mongo +// name: mongo // protocol: MONGO // // The gateway specification above describes the L4-L6 properties of a load @@ -126,7 +129,7 @@ option go_package = "istio.io/api/networking/v1alpha3"; // name: bookinfo-Mongo // spec: // hosts: -// - Mongosvr #name of Mongo service +// - mongosvr #name of Mongo service // gateways: // - my-gateway // tcp: @@ -162,6 +165,7 @@ message Gateway { // servers: // - port: // number: 80 +// name: http2 // protocol: HTTP2 // // Another example @@ -176,6 +180,7 @@ message Gateway { // servers: // - port: // number: 27018 +// name: mongo // protocol: MONGO // // The following is an example of TLS configuration for port 443 @@ -190,9 +195,10 @@ message Gateway { // servers: // - port: // number: 443 -// protocol: HTTP +// name: https +// protocol: HTTPS // tls: -// mode: simple +// mode: SIMPLE // serverCertificate: /etc/certs/server.pem // privateKey: /etc/certs/privatekey.pem // @@ -219,16 +225,16 @@ message Server { // TLS modes enforced by the proxy enum TLSmode { - // If set to "passthrough", the proxy will forward the connection + // If set to "PASSTHROUGH", the proxy will forward the connection // to the upstream server selected based on the SNI string presented // by the client. PASSTHROUGH = 0; - // If set to "simple", the proxy will secure connections with + // If set to "SIMPLE", the proxy will secure connections with // standard TLS semantics. SIMPLE = 1; - // If set to "mutual", the proxy will secure connections to the + // If set to "MUTUAL", the proxy will secure connections to the // upstream using mutual TLS by presenting client certificates for // authentication. MUTUAL = 2; @@ -239,15 +245,15 @@ message Server { // enforced. TLSmode mode = 2; - // REQUIRED if mode is "simple" or "mutual". The path to the file + // REQUIRED if mode is "SIMPLE" or "MUTUAL". The path to the file // holding the server-side TLS certificate to use. string server_certificate = 3; - // REQUIRED if mode is "simple" or "mutual". The path to the file + // REQUIRED if mode is "SIMPLE" or "MUTUAL". The path to the file // holding the server's private key. string private_key = 4; - // REQUIRED if mode is "mutual". The path to a file containing + // REQUIRED if mode is "MUTUAL". The path to a file containing // certificate authority certificates to use in verifying a presented // client side certificate. string ca_certificates = 5; @@ -268,7 +274,7 @@ message Port { // REQUIRED: A valid non-negative integer port number. uint32 number = 1; - // The protocol exposed on the port. + // REQUIRED: The protocol exposed on the port. // MUST BE one of HTTP|HTTPS|GRPC|HTTP2|MONGO|TCP. string protocol = 2; diff --git a/istio.io/api/networking/v1alpha3/istio.networking.v1alpha3.pb.html b/istio.io/api/networking/v1alpha3/istio.networking.v1alpha3.pb.html index 71b55cf6..958f3958 100644 --- a/istio.io/api/networking/v1alpha3/istio.networking.v1alpha3.pb.html +++ b/istio.io/api/networking/v1alpha3/istio.networking.v1alpha3.pb.html @@ -643,7 +643,7 @@

ExternalService

ports: - number: 443 name: example-http - protocol: http # not HTTPS. + protocol: HTTP # not HTTPS. discovery: DNS @@ -674,7 +674,7 @@

ExternalService

ports: - number: 27018 name: mongodb - protocol: mongo + protocol: MONGO discovery: STATIC endpoints: - address: 2.2.2.2 @@ -712,7 +712,7 @@

ExternalService

ports: - number: 80 name: http - protocol: http + protocol: HTTP discovery: NONE @@ -734,7 +734,7 @@

ExternalService

ports: - number: 443 name: https - protocol: http + protocol: HTTP discovery: DNS endpoints: - address: us.foo.bar.com @@ -843,7 +843,7 @@

ExternalService.Discovery

NONE -

If set to “none”, the proxy will assume that incoming connections +

If set to “NONE”, the proxy will assume that incoming connections have already been resolved (to a specific destination IP address). Such connections are typically routed via the proxy using mechanisms such as IP table REDIRECT/ eBPF. After performing any @@ -855,7 +855,7 @@

ExternalService.Discovery

STATIC -

If set to “static”, the proxy will use the IP addresses specified in +

If set to “STATIC”, the proxy will use the IP addresses specified in endpoints (See below) as the backing nodes associated with the external service.

@@ -864,7 +864,7 @@

ExternalService.Discovery

DNS -

If set to “dns”, the proxy will attempt to resolve the DNS address +

If set to “DNS”, the proxy will attempt to resolve the DNS address during request processing. If no endpoints are specified, the proxy will resolve the DNS address specified in the hosts field, if wildcards are not used. If endpoints are specified, the DNS @@ -945,6 +945,7 @@

Gateway

- port: number: 80 name: http + protocol: HTTP hosts: - uk.bookinfo.com - eu.bookinfo.com @@ -953,20 +954,22 @@

Gateway

- port: number: 443 name: https + protocol: HTTPS hosts: - uk.bookinfo.com - eu.bookinfo.com tls: - mode: simple #enables HTTPS on this port + mode: SIMPLE #enables HTTPS on this port serverCertificate: /etc/certs/servercert.pem privateKey: /etc/certs/privatekey.pem - port: number: 9080 name: http-wildcard + protocol: HTTP # no hosts implies wildcard match - port: number: 2379 #to expose internal service via external port 2379 - name: Mongo + name: mongo protocol: MONGO @@ -1032,7 +1035,7 @@

Gateway

name: bookinfo-Mongo spec: hosts: - - Mongosvr #name of Mongo service + - mongosvr #name of Mongo service gateways: - my-gateway tcp: @@ -2028,7 +2031,7 @@

Port

protocol string -

The protocol exposed on the port. +

REQUIRED: The protocol exposed on the port. MUST BE one of HTTP|HTTPS|GRPC|HTTP2|MONGO|TCP.

@@ -2092,6 +2095,7 @@

Server

servers: - port: number: 80 + name: http2 protocol: HTTP2 @@ -2107,6 +2111,7 @@

Server

servers: - port: number: 27018 + name: mongo protocol: MONGO @@ -2122,9 +2127,10 @@

Server

servers: - port: number: 443 - protocol: HTTP + name: https + protocol: HTTPS tls: - mode: simple + mode: SIMPLE serverCertificate: /etc/certs/server.pem privateKey: /etc/certs/privatekey.pem @@ -2210,7 +2216,7 @@

Server.TLSOptions

serverCertificate string -

REQUIRED if mode is “simple” or “mutual”. The path to the file +

REQUIRED if mode is “SIMPLE” or “MUTUAL”. The path to the file holding the server-side TLS certificate to use.

@@ -2219,7 +2225,7 @@

Server.TLSOptions

privateKey string -

REQUIRED if mode is “simple” or “mutual”. The path to the file +

REQUIRED if mode is “SIMPLE” or “MUTUAL”. The path to the file holding the server’s private key.

@@ -2228,7 +2234,7 @@

Server.TLSOptions

caCertificates string -

REQUIRED if mode is “mutual”. The path to a file containing +

REQUIRED if mode is “MUTUAL”. The path to a file containing certificate authority certificates to use in verifying a presented client side certificate.

@@ -2261,7 +2267,7 @@

Server.TLSOptions.TLSmode

PASSTHROUGH -

If set to “passthrough”, the proxy will forward the connection +

If set to “PASSTHROUGH”, the proxy will forward the connection to the upstream server selected based on the SNI string presented by the client.

@@ -2270,7 +2276,7 @@

Server.TLSOptions.TLSmode

SIMPLE -

If set to “simple”, the proxy will secure connections with +

If set to “SIMPLE”, the proxy will secure connections with standard TLS semantics.

@@ -2278,7 +2284,7 @@

Server.TLSOptions.TLSmode

MUTUAL -

If set to “mutual”, the proxy will secure connections to the +

If set to “MUTUAL”, the proxy will secure connections to the upstream using mutual TLS by presenting client certificates for authentication.

diff --git a/k8s.io/api/admissionregistration/v1beta1/types.go b/k8s.io/api/admissionregistration/v1beta1/types.go index aead73a5..30d2750c 100644 --- a/k8s.io/api/admissionregistration/v1beta1/types.go +++ b/k8s.io/api/admissionregistration/v1beta1/types.go @@ -147,8 +147,8 @@ type Webhook struct { // NamespaceSelector decides whether to run the webhook on an object based // on whether the namespace for that object matches the selector. If the // object itself is a namespace, the matching is performed on - // object.metadata.labels. If the object is another cluster scoped resource, - // it never skips the webhook. + // object.metadata.labels. If the object is other cluster scoped resource, + // it is not subjected to the webhook. // // For example, to run the webhook on any objects whose namespace is not // associated with "runlevel" of "0" or "1"; you will set the selector as diff --git a/k8s.io/api/admissionregistration/v1beta1/types_swagger_doc_generated.go b/k8s.io/api/admissionregistration/v1beta1/types_swagger_doc_generated.go index 6dd18e97..ea8c1e37 100644 --- a/k8s.io/api/admissionregistration/v1beta1/types_swagger_doc_generated.go +++ b/k8s.io/api/admissionregistration/v1beta1/types_swagger_doc_generated.go @@ -104,7 +104,7 @@ var map_Webhook = map[string]string{ "clientConfig": "ClientConfig defines how to communicate with the hook. Required", "rules": "Rules describes what operations on what resources/subresources the webhook cares about. The webhook cares about an operation if it matches _any_ Rule.", "failurePolicy": "FailurePolicy defines how unrecognized errors from the admission endpoint are handled - allowed values are Ignore or Fail. Defaults to Ignore.", - "namespaceSelector": "NamespaceSelector decides whether to run the webhook on an object based on whether the namespace for that object matches the selector. If the object itself is a namespace, the matching is performed on object.metadata.labels. If the object is another cluster scoped resource, it never skips the webhook.\n\nFor example, to run the webhook on any objects whose namespace is not associated with \"runlevel\" of \"0\" or \"1\"; you will set the selector as follows: \"namespaceSelector\": {\n \"matchExpressions\": [\n {\n \"key\": \"runlevel\",\n \"operator\": \"NotIn\",\n \"values\": [\n \"0\",\n \"1\"\n ]\n }\n ]\n}\n\nIf instead you want to only run the webhook on any objects whose namespace is associated with the \"environment\" of \"prod\" or \"staging\"; you will set the selector as follows: \"namespaceSelector\": {\n \"matchExpressions\": [\n {\n \"key\": \"environment\",\n \"operator\": \"In\",\n \"values\": [\n \"prod\",\n \"staging\"\n ]\n }\n ]\n}\n\nSee https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ for more examples of label selectors.\n\nDefault to the empty LabelSelector, which matches everything.", + "namespaceSelector": "NamespaceSelector decides whether to run the webhook on an object based on whether the namespace for that object matches the selector. If the object itself is a namespace, the matching is performed on object.metadata.labels. If the object is other cluster scoped resource, it is not subjected to the webhook.\n\nFor example, to run the webhook on any objects whose namespace is not associated with \"runlevel\" of \"0\" or \"1\"; you will set the selector as follows: \"namespaceSelector\": {\n \"matchExpressions\": [\n {\n \"key\": \"runlevel\",\n \"operator\": \"NotIn\",\n \"values\": [\n \"0\",\n \"1\"\n ]\n }\n ]\n}\n\nIf instead you want to only run the webhook on any objects whose namespace is associated with the \"environment\" of \"prod\" or \"staging\"; you will set the selector as follows: \"namespaceSelector\": {\n \"matchExpressions\": [\n {\n \"key\": \"environment\",\n \"operator\": \"In\",\n \"values\": [\n \"prod\",\n \"staging\"\n ]\n }\n ]\n}\n\nSee https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ for more examples of label selectors.\n\nDefault to the empty LabelSelector, which matches everything.", } func (Webhook) SwaggerDoc() map[string]string { diff --git a/k8s.io/apimachinery/pkg/api/equality/semantic.go b/k8s.io/apimachinery/pkg/api/equality/semantic.go new file mode 100644 index 00000000..f02fa8e4 --- /dev/null +++ b/k8s.io/apimachinery/pkg/api/equality/semantic.go @@ -0,0 +1,49 @@ +/* +Copyright 2014 The Kubernetes 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 equality + +import ( + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/conversion" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" +) + +// Semantic can do semantic deep equality checks for api objects. +// Example: apiequality.Semantic.DeepEqual(aPod, aPodWithNonNilButEmptyMaps) == true +var Semantic = conversion.EqualitiesOrDie( + func(a, b resource.Quantity) bool { + // Ignore formatting, only care that numeric value stayed the same. + // TODO: if we decide it's important, it should be safe to start comparing the format. + // + // Uninitialized quantities are equivalent to 0 quantities. + return a.Cmp(b) == 0 + }, + func(a, b metav1.MicroTime) bool { + return a.UTC() == b.UTC() + }, + func(a, b metav1.Time) bool { + return a.UTC() == b.UTC() + }, + func(a, b labels.Selector) bool { + return a.String() == b.String() + }, + func(a, b fields.Selector) bool { + return a.String() == b.String() + }, +) diff --git a/k8s.io/apimachinery/pkg/api/errors/errors.go b/k8s.io/apimachinery/pkg/api/errors/errors.go index 9960600b..d5503fac 100644 --- a/k8s.io/apimachinery/pkg/api/errors/errors.go +++ b/k8s.io/apimachinery/pkg/api/errors/errors.go @@ -405,84 +405,84 @@ func NewGenericServerResponse(code int, verb string, qualifiedResource schema.Gr // IsNotFound returns true if the specified error was created by NewNotFound. func IsNotFound(err error) bool { - return ReasonForError(err) == metav1.StatusReasonNotFound + return reasonForError(err) == metav1.StatusReasonNotFound } // IsAlreadyExists determines if the err is an error which indicates that a specified resource already exists. func IsAlreadyExists(err error) bool { - return ReasonForError(err) == metav1.StatusReasonAlreadyExists + return reasonForError(err) == metav1.StatusReasonAlreadyExists } // IsConflict determines if the err is an error which indicates the provided update conflicts. func IsConflict(err error) bool { - return ReasonForError(err) == metav1.StatusReasonConflict + return reasonForError(err) == metav1.StatusReasonConflict } // IsInvalid determines if the err is an error which indicates the provided resource is not valid. func IsInvalid(err error) bool { - return ReasonForError(err) == metav1.StatusReasonInvalid + return reasonForError(err) == metav1.StatusReasonInvalid } // IsGone is true if the error indicates the requested resource is no longer available. func IsGone(err error) bool { - return ReasonForError(err) == metav1.StatusReasonGone + return reasonForError(err) == metav1.StatusReasonGone } // IsResourceExpired is true if the error indicates the resource has expired and the current action is // no longer possible. func IsResourceExpired(err error) bool { - return ReasonForError(err) == metav1.StatusReasonExpired + return reasonForError(err) == metav1.StatusReasonExpired } // IsMethodNotSupported determines if the err is an error which indicates the provided action could not // be performed because it is not supported by the server. func IsMethodNotSupported(err error) bool { - return ReasonForError(err) == metav1.StatusReasonMethodNotAllowed + return reasonForError(err) == metav1.StatusReasonMethodNotAllowed } // IsServiceUnavailable is true if the error indicates the underlying service is no longer available. func IsServiceUnavailable(err error) bool { - return ReasonForError(err) == metav1.StatusReasonServiceUnavailable + return reasonForError(err) == metav1.StatusReasonServiceUnavailable } // IsBadRequest determines if err is an error which indicates that the request is invalid. func IsBadRequest(err error) bool { - return ReasonForError(err) == metav1.StatusReasonBadRequest + return reasonForError(err) == metav1.StatusReasonBadRequest } // IsUnauthorized determines if err is an error which indicates that the request is unauthorized and // requires authentication by the user. func IsUnauthorized(err error) bool { - return ReasonForError(err) == metav1.StatusReasonUnauthorized + return reasonForError(err) == metav1.StatusReasonUnauthorized } // IsForbidden determines if err is an error which indicates that the request is forbidden and cannot // be completed as requested. func IsForbidden(err error) bool { - return ReasonForError(err) == metav1.StatusReasonForbidden + return reasonForError(err) == metav1.StatusReasonForbidden } // IsTimeout determines if err is an error which indicates that request times out due to long // processing. func IsTimeout(err error) bool { - return ReasonForError(err) == metav1.StatusReasonTimeout + return reasonForError(err) == metav1.StatusReasonTimeout } // IsServerTimeout determines if err is an error which indicates that the request needs to be retried // by the client. func IsServerTimeout(err error) bool { - return ReasonForError(err) == metav1.StatusReasonServerTimeout + return reasonForError(err) == metav1.StatusReasonServerTimeout } // IsInternalError determines if err is an error which indicates an internal server error. func IsInternalError(err error) bool { - return ReasonForError(err) == metav1.StatusReasonInternalError + return reasonForError(err) == metav1.StatusReasonInternalError } // IsTooManyRequests determines if err is an error which indicates that there are too many requests // that the server cannot handle. func IsTooManyRequests(err error) bool { - if ReasonForError(err) == metav1.StatusReasonTooManyRequests { + if reasonForError(err) == metav1.StatusReasonTooManyRequests { return true } switch t := err.(type) { @@ -536,8 +536,7 @@ func SuggestsClientDelay(err error) (int, bool) { return 0, false } -// ReasonForError returns the HTTP status for a particular error. -func ReasonForError(err error) metav1.StatusReason { +func reasonForError(err error) metav1.StatusReason { switch t := err.(type) { case APIStatus: return t.Status().Reason diff --git a/k8s.io/apimachinery/pkg/api/meta/interfaces.go b/k8s.io/apimachinery/pkg/api/meta/interfaces.go index 5dc9d89e..bf172369 100644 --- a/k8s.io/apimachinery/pkg/api/meta/interfaces.go +++ b/k8s.io/apimachinery/pkg/api/meta/interfaces.go @@ -75,9 +75,6 @@ type MetadataAccessor interface { Annotations(obj runtime.Object) (map[string]string, error) SetAnnotations(obj runtime.Object, annotations map[string]string) error - Continue(obj runtime.Object) (string, error) - SetContinue(obj runtime.Object, c string) error - runtime.ResourceVersioner } diff --git a/k8s.io/apimachinery/pkg/api/meta/lazy.go b/k8s.io/apimachinery/pkg/api/meta/lazy.go deleted file mode 100644 index 7f92f39a..00000000 --- a/k8s.io/apimachinery/pkg/api/meta/lazy.go +++ /dev/null @@ -1,121 +0,0 @@ -/* -Copyright 2017 The Kubernetes 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 meta - -import ( - "sync" - - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -// lazyObject defers loading the mapper and typer until necessary. -type lazyObject struct { - loader func() (RESTMapper, runtime.ObjectTyper, error) - - lock sync.Mutex - loaded bool - err error - mapper RESTMapper - typer runtime.ObjectTyper -} - -// NewLazyObjectLoader handles unrecoverable errors when creating a RESTMapper / ObjectTyper by -// returning those initialization errors when the interface methods are invoked. This defers the -// initialization and any server calls until a client actually needs to perform the action. -func NewLazyObjectLoader(fn func() (RESTMapper, runtime.ObjectTyper, error)) (RESTMapper, runtime.ObjectTyper) { - obj := &lazyObject{loader: fn} - return obj, obj -} - -// init lazily loads the mapper and typer, returning an error if initialization has failed. -func (o *lazyObject) init() error { - o.lock.Lock() - defer o.lock.Unlock() - if o.loaded { - return o.err - } - o.mapper, o.typer, o.err = o.loader() - o.loaded = true - return o.err -} - -var _ RESTMapper = &lazyObject{} -var _ runtime.ObjectTyper = &lazyObject{} - -func (o *lazyObject) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { - if err := o.init(); err != nil { - return schema.GroupVersionKind{}, err - } - return o.mapper.KindFor(resource) -} - -func (o *lazyObject) KindsFor(resource schema.GroupVersionResource) ([]schema.GroupVersionKind, error) { - if err := o.init(); err != nil { - return []schema.GroupVersionKind{}, err - } - return o.mapper.KindsFor(resource) -} - -func (o *lazyObject) ResourceFor(input schema.GroupVersionResource) (schema.GroupVersionResource, error) { - if err := o.init(); err != nil { - return schema.GroupVersionResource{}, err - } - return o.mapper.ResourceFor(input) -} - -func (o *lazyObject) ResourcesFor(input schema.GroupVersionResource) ([]schema.GroupVersionResource, error) { - if err := o.init(); err != nil { - return []schema.GroupVersionResource{}, err - } - return o.mapper.ResourcesFor(input) -} - -func (o *lazyObject) RESTMapping(gk schema.GroupKind, versions ...string) (*RESTMapping, error) { - if err := o.init(); err != nil { - return nil, err - } - return o.mapper.RESTMapping(gk, versions...) -} - -func (o *lazyObject) RESTMappings(gk schema.GroupKind, versions ...string) ([]*RESTMapping, error) { - if err := o.init(); err != nil { - return nil, err - } - return o.mapper.RESTMappings(gk, versions...) -} - -func (o *lazyObject) ResourceSingularizer(resource string) (singular string, err error) { - if err := o.init(); err != nil { - return "", err - } - return o.mapper.ResourceSingularizer(resource) -} - -func (o *lazyObject) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) { - if err := o.init(); err != nil { - return nil, false, err - } - return o.typer.ObjectKinds(obj) -} - -func (o *lazyObject) Recognizes(gvk schema.GroupVersionKind) bool { - if err := o.init(); err != nil { - return false - } - return o.typer.Recognizes(gvk) -} diff --git a/k8s.io/apimachinery/pkg/api/meta/meta.go b/k8s.io/apimachinery/pkg/api/meta/meta.go index c2d51b43..1889b951 100644 --- a/k8s.io/apimachinery/pkg/api/meta/meta.go +++ b/k8s.io/apimachinery/pkg/api/meta/meta.go @@ -89,7 +89,7 @@ func ListAccessor(obj interface{}) (List, error) { } return nil, errNotList default: - return nil, errNotList + panic(fmt.Errorf("%T does not implement the List interface", obj)) } } @@ -367,23 +367,6 @@ func (resourceAccessor) SetResourceVersion(obj runtime.Object, version string) e return nil } -func (resourceAccessor) Continue(obj runtime.Object) (string, error) { - accessor, err := ListAccessor(obj) - if err != nil { - return "", err - } - return accessor.GetContinue(), nil -} - -func (resourceAccessor) SetContinue(obj runtime.Object, version string) error { - accessor, err := ListAccessor(obj) - if err != nil { - return err - } - accessor.SetContinue(version) - return nil -} - // extractFromOwnerReference extracts v to o. v is the OwnerReferences field of an object. func extractFromOwnerReference(v reflect.Value, o *metav1.OwnerReference) error { if err := runtime.Field(v, "APIVersion", &o.APIVersion); err != nil { diff --git a/k8s.io/apimachinery/pkg/api/meta/unstructured.go b/k8s.io/apimachinery/pkg/api/meta/unstructured.go index 4e13efea..3ebf2481 100644 --- a/k8s.io/apimachinery/pkg/api/meta/unstructured.go +++ b/k8s.io/apimachinery/pkg/api/meta/unstructured.go @@ -21,24 +21,8 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" ) -// InterfacesForUnstructuredConversion returns VersionInterfaces suitable for -// dealing with unstructured.Unstructured objects and supports conversion -// from typed objects (provided by parent) to untyped objects. -func InterfacesForUnstructuredConversion(parent VersionInterfacesFunc) VersionInterfacesFunc { - return func(version schema.GroupVersion) (*VersionInterfaces, error) { - if i, err := parent(version); err == nil { - return &VersionInterfaces{ - ObjectConvertor: i.ObjectConvertor, - MetadataAccessor: NewAccessor(), - }, nil - } - return InterfacesForUnstructured(version) - } -} - // InterfacesForUnstructured returns VersionInterfaces suitable for -// dealing with unstructured.Unstructured objects. It will return errors for -// other conversions. +// dealing with unstructured.Unstructured objects. func InterfacesForUnstructured(schema.GroupVersion) (*VersionInterfaces, error) { return &VersionInterfaces{ ObjectConvertor: &unstructured.UnstructuredObjectConverter{}, diff --git a/k8s.io/apimachinery/pkg/api/resource/generated.pb.go b/k8s.io/apimachinery/pkg/api/resource/generated.pb.go index 6de71e50..8b2e338a 100644 --- a/k8s.io/apimachinery/pkg/api/resource/generated.pb.go +++ b/k8s.io/apimachinery/pkg/api/resource/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/k8s.io/apimachinery/pkg/api/resource/zz_generated.deepcopy.go b/k8s.io/apimachinery/pkg/api/resource/zz_generated.deepcopy.go index 186d9007..118dfca0 100644 --- a/k8s.io/apimachinery/pkg/api/resource/zz_generated.deepcopy.go +++ b/k8s.io/apimachinery/pkg/api/resource/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -20,6 +20,23 @@ limitations under the License. package resource +import ( + conversion "k8s.io/apimachinery/pkg/conversion" + reflect "reflect" +) + +// GetGeneratedDeepCopyFuncs returns the generated funcs, since we aren't registering them. +// +// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented. +func GetGeneratedDeepCopyFuncs() []conversion.GeneratedDeepCopyFunc { + return []conversion.GeneratedDeepCopyFunc{ + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*Quantity).DeepCopyInto(out.(*Quantity)) + return nil + }, InType: reflect.TypeOf(&Quantity{})}, + } +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Quantity) DeepCopyInto(out *Quantity) { *out = in.DeepCopy() diff --git a/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.deepcopy.go b/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.deepcopy.go index 2bc1c3f9..f13ff9fc 100644 --- a/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.deepcopy.go +++ b/k8s.io/apimachinery/pkg/apis/meta/internalversion/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -21,9 +21,27 @@ limitations under the License. package internalversion import ( + conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" + reflect "reflect" ) +// GetGeneratedDeepCopyFuncs returns the generated funcs, since we aren't registering them. +// +// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented. +func GetGeneratedDeepCopyFuncs() []conversion.GeneratedDeepCopyFunc { + return []conversion.GeneratedDeepCopyFunc{ + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*List).DeepCopyInto(out.(*List)) + return nil + }, InType: reflect.TypeOf(&List{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*ListOptions).DeepCopyInto(out.(*ListOptions)) + return nil + }, InType: reflect.TypeOf(&ListOptions{})}, + } +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *List) DeepCopyInto(out *List) { *out = *in diff --git a/k8s.io/apimachinery/pkg/apis/meta/v1/conversion.go b/k8s.io/apimachinery/pkg/apis/meta/v1/conversion.go index c62f8533..a96f38ee 100644 --- a/k8s.io/apimachinery/pkg/apis/meta/v1/conversion.go +++ b/k8s.io/apimachinery/pkg/apis/meta/v1/conversion.go @@ -38,7 +38,6 @@ func AddConversionFuncs(scheme *runtime.Scheme) error { Convert_intstr_IntOrString_To_intstr_IntOrString, Convert_unversioned_Time_To_unversioned_Time, - Convert_unversioned_MicroTime_To_unversioned_MicroTime, Convert_Pointer_v1_Duration_To_v1_Duration, Convert_v1_Duration_To_Pointer_v1_Duration, @@ -200,12 +199,6 @@ func Convert_v1_Duration_To_Pointer_v1_Duration(in *Duration, out **Duration, s return nil } -func Convert_unversioned_MicroTime_To_unversioned_MicroTime(in *MicroTime, out *MicroTime, s conversion.Scope) error { - // Cannot deep copy these, because time.Time has unexported fields. - *out = *in - return nil -} - // Convert_Slice_string_To_unversioned_Time allows converting a URL query parameter value func Convert_Slice_string_To_unversioned_Time(input *[]string, out *Time, s conversion.Scope) error { str := "" diff --git a/k8s.io/apimachinery/pkg/apis/meta/v1/generated.pb.go b/k8s.io/apimachinery/pkg/apis/meta/v1/generated.pb.go index 1fa478f5..653b3023 100644 --- a/k8s.io/apimachinery/pkg/apis/meta/v1/generated.pb.go +++ b/k8s.io/apimachinery/pkg/apis/meta/v1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -50,7 +50,6 @@ limitations under the License. MicroTime ObjectMeta OwnerReference - Patch Preconditions RootPaths ServerAddressByClientCIDR @@ -197,55 +196,51 @@ func (m *OwnerReference) Reset() { *m = OwnerReference{} } func (*OwnerReference) ProtoMessage() {} func (*OwnerReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} } -func (m *Patch) Reset() { *m = Patch{} } -func (*Patch) ProtoMessage() {} -func (*Patch) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} } - func (m *Preconditions) Reset() { *m = Preconditions{} } func (*Preconditions) ProtoMessage() {} -func (*Preconditions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} } +func (*Preconditions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} } func (m *RootPaths) Reset() { *m = RootPaths{} } func (*RootPaths) ProtoMessage() {} -func (*RootPaths) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{27} } +func (*RootPaths) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} } func (m *ServerAddressByClientCIDR) Reset() { *m = ServerAddressByClientCIDR{} } func (*ServerAddressByClientCIDR) ProtoMessage() {} func (*ServerAddressByClientCIDR) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{28} + return fileDescriptorGenerated, []int{27} } func (m *Status) Reset() { *m = Status{} } func (*Status) ProtoMessage() {} -func (*Status) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{29} } +func (*Status) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{28} } func (m *StatusCause) Reset() { *m = StatusCause{} } func (*StatusCause) ProtoMessage() {} -func (*StatusCause) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{30} } +func (*StatusCause) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{29} } func (m *StatusDetails) Reset() { *m = StatusDetails{} } func (*StatusDetails) ProtoMessage() {} -func (*StatusDetails) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{31} } +func (*StatusDetails) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{30} } func (m *Time) Reset() { *m = Time{} } func (*Time) ProtoMessage() {} -func (*Time) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{32} } +func (*Time) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{31} } func (m *Timestamp) Reset() { *m = Timestamp{} } func (*Timestamp) ProtoMessage() {} -func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{33} } +func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{32} } func (m *TypeMeta) Reset() { *m = TypeMeta{} } func (*TypeMeta) ProtoMessage() {} -func (*TypeMeta) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{34} } +func (*TypeMeta) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{33} } func (m *Verbs) Reset() { *m = Verbs{} } func (*Verbs) ProtoMessage() {} -func (*Verbs) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{35} } +func (*Verbs) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{34} } func (m *WatchEvent) Reset() { *m = WatchEvent{} } func (*WatchEvent) ProtoMessage() {} -func (*WatchEvent) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{36} } +func (*WatchEvent) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{35} } func init() { proto.RegisterType((*APIGroup)(nil), "k8s.io.apimachinery.pkg.apis.meta.v1.APIGroup") @@ -273,7 +268,6 @@ func init() { proto.RegisterType((*MicroTime)(nil), "k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime") proto.RegisterType((*ObjectMeta)(nil), "k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta") proto.RegisterType((*OwnerReference)(nil), "k8s.io.apimachinery.pkg.apis.meta.v1.OwnerReference") - proto.RegisterType((*Patch)(nil), "k8s.io.apimachinery.pkg.apis.meta.v1.Patch") proto.RegisterType((*Preconditions)(nil), "k8s.io.apimachinery.pkg.apis.meta.v1.Preconditions") proto.RegisterType((*RootPaths)(nil), "k8s.io.apimachinery.pkg.apis.meta.v1.RootPaths") proto.RegisterType((*ServerAddressByClientCIDR)(nil), "k8s.io.apimachinery.pkg.apis.meta.v1.ServerAddressByClientCIDR") @@ -1323,24 +1317,6 @@ func (m *OwnerReference) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func (m *Patch) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *Patch) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - return i, nil -} - func (m *Preconditions) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -2089,12 +2065,6 @@ func (m *OwnerReference) Size() (n int) { return n } -func (m *Patch) Size() (n int) { - var l int - _ = l - return n -} - func (m *Preconditions) Size() (n int) { var l int _ = l @@ -2494,15 +2464,6 @@ func (this *OwnerReference) String() string { }, "") return s } -func (this *Patch) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&Patch{`, - `}`, - }, "") - return s -} func (this *Preconditions) String() string { if this == nil { return "nil" @@ -6421,56 +6382,6 @@ func (m *OwnerReference) Unmarshal(dAtA []byte) error { } return nil } -func (m *Patch) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Patch: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Patch: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipGenerated(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthGenerated - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *Preconditions) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -7804,7 +7715,7 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 2435 bytes of a gzipped FileDescriptorProto + // 2428 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x59, 0x4d, 0x6c, 0x23, 0x49, 0x15, 0x4e, 0xdb, 0xb1, 0x63, 0x3f, 0xc7, 0xf9, 0xa9, 0xcd, 0x80, 0x37, 0x02, 0x3b, 0xdb, 0x8b, 0x56, 0x59, 0x98, 0xb5, 0x49, 0x16, 0x56, 0xc3, 0x00, 0x03, 0xe9, 0x38, 0x33, 0x8a, 0x76, 0x32, @@ -7812,7 +7723,7 @@ var fileDescriptorGenerated = []byte{ 0x33, 0x09, 0x1c, 0xd8, 0x03, 0x48, 0x1c, 0x10, 0x9a, 0x23, 0x27, 0xb4, 0x23, 0xb8, 0x70, 0xe5, 0xc4, 0x05, 0x4e, 0x48, 0xcc, 0x71, 0x24, 0x2e, 0x7b, 0x40, 0xd6, 0x8e, 0xf7, 0xc0, 0x09, 0x71, 0xcf, 0x09, 0x55, 0x75, 0xf5, 0x9f, 0x1d, 0x4f, 0xda, 0x3b, 0x0b, 0xe2, 0x14, 0xf7, 0xfb, 0xf9, - 0xde, 0xab, 0x57, 0xaf, 0x5e, 0xbd, 0x7a, 0x81, 0xbd, 0xe3, 0x6b, 0xac, 0x6e, 0x7b, 0x8d, 0xe3, + 0xde, 0xab, 0xaa, 0xf7, 0x5e, 0xbd, 0x7a, 0x81, 0xbd, 0xe3, 0x6b, 0xac, 0x6e, 0x7b, 0x8d, 0xe3, 0xfe, 0x01, 0xa1, 0x2e, 0xe1, 0x84, 0x35, 0x4e, 0x88, 0xdb, 0xf6, 0x68, 0x43, 0x31, 0xcc, 0x9e, 0xdd, 0x35, 0xad, 0x23, 0xdb, 0x25, 0xf4, 0xac, 0xd1, 0x3b, 0xee, 0x08, 0x02, 0x6b, 0x74, 0x09, 0x37, 0x1b, 0x27, 0x1b, 0x8d, 0x0e, 0x71, 0x09, 0x35, 0x39, 0x69, 0xd7, 0x7b, 0xd4, 0xe3, 0x1e, @@ -7824,138 +7735,137 @@ var fileDescriptorGenerated = []byte{ 0xff, 0x96, 0x85, 0xc2, 0x56, 0x6b, 0xf7, 0x16, 0xf5, 0xfa, 0x3d, 0xb4, 0x06, 0xb3, 0xae, 0xd9, 0x25, 0x15, 0x6d, 0x4d, 0x5b, 0x2f, 0x1a, 0xf3, 0x4f, 0x07, 0xb5, 0x99, 0xe1, 0xa0, 0x36, 0x7b, 0xc7, 0xec, 0x12, 0x2c, 0x39, 0xc8, 0x81, 0xc2, 0x09, 0xa1, 0xcc, 0xf6, 0x5c, 0x56, 0xc9, 0xac, - 0x65, 0xd7, 0x4b, 0x9b, 0x37, 0xea, 0x69, 0x82, 0x56, 0x97, 0x06, 0xee, 0xfb, 0xaa, 0x37, 0x3d, - 0xda, 0xb4, 0x99, 0xe5, 0x9d, 0x10, 0x7a, 0x66, 0x2c, 0x29, 0x2b, 0x05, 0xc5, 0x64, 0x38, 0xb4, - 0x80, 0x7e, 0xae, 0xc1, 0x52, 0x8f, 0x92, 0x43, 0x42, 0x29, 0x69, 0x2b, 0x7e, 0x25, 0xbb, 0xa6, - 0x7d, 0x06, 0x66, 0x2b, 0xca, 0xec, 0x52, 0x6b, 0x04, 0x1f, 0x8f, 0x59, 0x44, 0xbf, 0xd3, 0x60, - 0x95, 0x11, 0x7a, 0x42, 0xe8, 0x56, 0xbb, 0x4d, 0x09, 0x63, 0xc6, 0xd9, 0xb6, 0x63, 0x13, 0x97, - 0x6f, 0xef, 0x36, 0x31, 0xab, 0xcc, 0xca, 0x38, 0x7c, 0x27, 0x9d, 0x43, 0xfb, 0x93, 0x70, 0x0c, - 0x5d, 0x79, 0xb4, 0x3a, 0x51, 0x84, 0xe1, 0x17, 0xb8, 0xa1, 0x1f, 0xc2, 0x7c, 0xb0, 0x91, 0xb7, - 0x6d, 0xc6, 0xd1, 0x7d, 0xc8, 0x77, 0xc4, 0x07, 0xab, 0x68, 0xd2, 0xc1, 0x7a, 0x3a, 0x07, 0x03, - 0x0c, 0x63, 0x41, 0xf9, 0x93, 0x97, 0x9f, 0x0c, 0x2b, 0x34, 0xfd, 0xcf, 0x59, 0x28, 0x6d, 0xb5, - 0x76, 0x31, 0x61, 0x5e, 0x9f, 0x5a, 0x24, 0x45, 0xd2, 0x6c, 0x02, 0x88, 0xbf, 0xac, 0x67, 0x5a, - 0xa4, 0x5d, 0xc9, 0xac, 0x69, 0xeb, 0x05, 0x03, 0x29, 0x39, 0xb8, 0x13, 0x72, 0x70, 0x4c, 0x4a, - 0xa0, 0x1e, 0xdb, 0x6e, 0x5b, 0xee, 0x76, 0x0c, 0xf5, 0x5d, 0xdb, 0x6d, 0x63, 0xc9, 0x41, 0xb7, - 0x21, 0x77, 0x42, 0xe8, 0x81, 0x88, 0xbf, 0x48, 0x88, 0xaf, 0xa4, 0x5b, 0xde, 0x7d, 0xa1, 0x62, - 0x14, 0x87, 0x83, 0x5a, 0x4e, 0xfe, 0xc4, 0x3e, 0x08, 0xaa, 0x03, 0xb0, 0x23, 0x8f, 0x72, 0xe9, - 0x4e, 0x25, 0xb7, 0x96, 0x5d, 0x2f, 0x1a, 0x0b, 0xc2, 0xbf, 0xfd, 0x90, 0x8a, 0x63, 0x12, 0xe8, - 0x1a, 0xcc, 0x33, 0xdb, 0xed, 0xf4, 0x1d, 0x93, 0x0a, 0x42, 0x25, 0x2f, 0xfd, 0x5c, 0x51, 0x7e, - 0xce, 0xef, 0xc7, 0x78, 0x38, 0x21, 0x29, 0x2c, 0x59, 0x26, 0x27, 0x1d, 0x8f, 0xda, 0x84, 0x55, - 0xe6, 0x22, 0x4b, 0xdb, 0x21, 0x15, 0xc7, 0x24, 0xd0, 0xeb, 0x90, 0x93, 0x91, 0xaf, 0x14, 0xa4, - 0x89, 0xb2, 0x32, 0x91, 0x93, 0xdb, 0x82, 0x7d, 0x1e, 0x7a, 0x13, 0xe6, 0xd4, 0xa9, 0xa9, 0x14, - 0xa5, 0xd8, 0xa2, 0x12, 0x9b, 0x0b, 0xd2, 0x3a, 0xe0, 0xeb, 0x7f, 0xd4, 0x60, 0x31, 0xb6, 0x7f, - 0x32, 0x57, 0xae, 0xc1, 0x7c, 0x27, 0x76, 0x52, 0xd4, 0x5e, 0x86, 0xab, 0x89, 0x9f, 0x22, 0x9c, - 0x90, 0x44, 0x04, 0x8a, 0x54, 0x21, 0x05, 0x15, 0x61, 0x23, 0x75, 0xa2, 0x05, 0x3e, 0x44, 0x96, - 0x62, 0x44, 0x86, 0x23, 0x64, 0xfd, 0x9f, 0x9a, 0x4c, 0xba, 0xa0, 0x46, 0xa0, 0xf5, 0x58, 0x1d, - 0xd2, 0x64, 0x08, 0xe7, 0x27, 0xd4, 0x90, 0x4b, 0x0e, 0x6f, 0xe6, 0xff, 0xe2, 0xf0, 0x5e, 0x2f, + 0x65, 0xd7, 0x4b, 0x9b, 0x37, 0xea, 0x69, 0x36, 0xad, 0x2e, 0x0d, 0xdc, 0xf7, 0x55, 0x6f, 0x7a, + 0xb4, 0x69, 0x33, 0xcb, 0x3b, 0x21, 0xf4, 0xcc, 0x58, 0x52, 0x56, 0x0a, 0x8a, 0xc9, 0x70, 0x68, + 0x01, 0xfd, 0x5c, 0x83, 0xa5, 0x1e, 0x25, 0x87, 0x84, 0x52, 0xd2, 0x56, 0xfc, 0x4a, 0x76, 0x4d, + 0xfb, 0x0c, 0xcc, 0x56, 0x94, 0xd9, 0xa5, 0xd6, 0x08, 0x3e, 0x1e, 0xb3, 0x88, 0x7e, 0xa7, 0xc1, + 0x2a, 0x23, 0xf4, 0x84, 0xd0, 0xad, 0x76, 0x9b, 0x12, 0xc6, 0x8c, 0xb3, 0x6d, 0xc7, 0x26, 0x2e, + 0xdf, 0xde, 0x6d, 0x62, 0x56, 0x99, 0x95, 0xfb, 0xf0, 0x9d, 0x74, 0x0e, 0xed, 0x4f, 0xc2, 0x31, + 0x74, 0xe5, 0xd1, 0xea, 0x44, 0x11, 0x86, 0x5f, 0xe0, 0x86, 0x7e, 0x08, 0xf3, 0xc1, 0x41, 0xde, + 0xb6, 0x19, 0x47, 0xf7, 0x21, 0xdf, 0x11, 0x1f, 0xac, 0xa2, 0x49, 0x07, 0xeb, 0xe9, 0x1c, 0x0c, + 0x30, 0x8c, 0x05, 0xe5, 0x4f, 0x5e, 0x7e, 0x32, 0xac, 0xd0, 0xf4, 0x3f, 0x67, 0xa1, 0xb4, 0xd5, + 0xda, 0xc5, 0x84, 0x79, 0x7d, 0x6a, 0x91, 0x14, 0x41, 0xb3, 0x09, 0x20, 0xfe, 0xb2, 0x9e, 0x69, + 0x91, 0x76, 0x25, 0xb3, 0xa6, 0xad, 0x17, 0x0c, 0xa4, 0xe4, 0xe0, 0x4e, 0xc8, 0xc1, 0x31, 0x29, + 0x81, 0x7a, 0x6c, 0xbb, 0x6d, 0x79, 0xda, 0x31, 0xd4, 0x77, 0x6d, 0xb7, 0x8d, 0x25, 0x07, 0xdd, + 0x86, 0xdc, 0x09, 0xa1, 0x07, 0x62, 0xff, 0x45, 0x40, 0x7c, 0x25, 0xdd, 0xf2, 0xee, 0x0b, 0x15, + 0xa3, 0x38, 0x1c, 0xd4, 0x72, 0xf2, 0x27, 0xf6, 0x41, 0x50, 0x1d, 0x80, 0x1d, 0x79, 0x94, 0x4b, + 0x77, 0x2a, 0xb9, 0xb5, 0xec, 0x7a, 0xd1, 0x58, 0x10, 0xfe, 0xed, 0x87, 0x54, 0x1c, 0x93, 0x40, + 0xd7, 0x60, 0x9e, 0xd9, 0x6e, 0xa7, 0xef, 0x98, 0x54, 0x10, 0x2a, 0x79, 0xe9, 0xe7, 0x8a, 0xf2, + 0x73, 0x7e, 0x3f, 0xc6, 0xc3, 0x09, 0x49, 0x61, 0xc9, 0x32, 0x39, 0xe9, 0x78, 0xd4, 0x26, 0xac, + 0x32, 0x17, 0x59, 0xda, 0x0e, 0xa9, 0x38, 0x26, 0x81, 0x5e, 0x87, 0x9c, 0xdc, 0xf9, 0x4a, 0x41, + 0x9a, 0x28, 0x2b, 0x13, 0x39, 0x79, 0x2c, 0xd8, 0xe7, 0xa1, 0x37, 0x61, 0x4e, 0x65, 0x4d, 0xa5, + 0x28, 0xc5, 0x16, 0x95, 0xd8, 0x5c, 0x10, 0xd6, 0x01, 0x5f, 0xff, 0xa3, 0x06, 0x8b, 0xb1, 0xf3, + 0x93, 0xb1, 0x72, 0x0d, 0xe6, 0x3b, 0xb1, 0x4c, 0x51, 0x67, 0x19, 0xae, 0x26, 0x9e, 0x45, 0x38, + 0x21, 0x89, 0x08, 0x14, 0xa9, 0x42, 0x0a, 0x2a, 0xc2, 0x46, 0xea, 0x40, 0x0b, 0x7c, 0x88, 0x2c, + 0xc5, 0x88, 0x0c, 0x47, 0xc8, 0xfa, 0x3f, 0x35, 0x19, 0x74, 0x41, 0x8d, 0x40, 0xeb, 0xb1, 0x3a, + 0xa4, 0xc9, 0x2d, 0x9c, 0x9f, 0x50, 0x43, 0x2e, 0x49, 0xde, 0xcc, 0xff, 0x45, 0xf2, 0x5e, 0x2f, 0xfc, 0xe6, 0xc3, 0xda, 0xcc, 0x07, 0xff, 0x58, 0x9b, 0xd1, 0x3f, 0xc9, 0x40, 0xb9, 0x49, 0x1c, 0xc2, 0xc9, 0xdd, 0x1e, 0x97, 0x2b, 0xb8, 0x09, 0xa8, 0x43, 0x4d, 0x8b, 0xb4, 0x08, 0xb5, 0xbd, - 0xf6, 0x3e, 0xb1, 0x3c, 0xb7, 0xcd, 0xe4, 0x16, 0x65, 0x8d, 0xcf, 0x0d, 0x07, 0x35, 0x74, 0x6b, - 0x8c, 0x8b, 0x2f, 0xd0, 0x40, 0x0e, 0x94, 0x7b, 0x54, 0xfe, 0xb6, 0xb9, 0x2a, 0xe0, 0xe2, 0xe0, - 0xbc, 0x9d, 0x6e, 0xed, 0xad, 0xb8, 0xaa, 0xb1, 0x3c, 0x1c, 0xd4, 0xca, 0x09, 0x12, 0x4e, 0x82, - 0xa3, 0xef, 0xc2, 0x92, 0x47, 0x7b, 0x47, 0xa6, 0xdb, 0x24, 0x3d, 0xe2, 0xb6, 0x89, 0xcb, 0x99, - 0x3c, 0xcc, 0x05, 0x63, 0x45, 0x94, 0xdd, 0xbb, 0x23, 0x3c, 0x3c, 0x26, 0x8d, 0x1e, 0xc0, 0x72, - 0x8f, 0x7a, 0x3d, 0xb3, 0x63, 0x0a, 0xc4, 0x96, 0xe7, 0xd8, 0xd6, 0x99, 0x3c, 0xec, 0x45, 0xe3, - 0xea, 0x70, 0x50, 0x5b, 0x6e, 0x8d, 0x32, 0xcf, 0x07, 0xb5, 0x57, 0x64, 0xe8, 0x04, 0x25, 0x62, - 0xe2, 0x71, 0x18, 0x7d, 0x17, 0x0a, 0xcd, 0x3e, 0x95, 0x14, 0xf4, 0x6d, 0x28, 0xb4, 0xd5, 0x6f, - 0x15, 0xd5, 0xd7, 0x82, 0x3b, 0x29, 0x90, 0x39, 0x1f, 0xd4, 0xca, 0xe2, 0xea, 0xad, 0x07, 0x04, - 0x1c, 0xaa, 0xe8, 0x0f, 0xa1, 0xbc, 0x73, 0xda, 0xf3, 0x28, 0x0f, 0xf6, 0xeb, 0x0d, 0xc8, 0x13, - 0x49, 0x90, 0x68, 0x85, 0xa8, 0x90, 0xfa, 0x62, 0x58, 0x71, 0xc5, 0xc1, 0x26, 0xa7, 0xa6, 0xc5, - 0x55, 0x45, 0x0c, 0x0f, 0xf6, 0x8e, 0x20, 0x62, 0x9f, 0xa7, 0x3f, 0xd1, 0x00, 0x6e, 0x91, 0x10, - 0x7b, 0x0b, 0x16, 0x83, 0x43, 0x91, 0x3c, 0xab, 0x9f, 0x57, 0xda, 0x8b, 0x38, 0xc9, 0xc6, 0xa3, - 0xf2, 0xa8, 0x05, 0x2b, 0xb6, 0x6b, 0x39, 0xfd, 0x36, 0xb9, 0xe7, 0xda, 0xae, 0xcd, 0x6d, 0xd3, - 0xb1, 0x7f, 0x12, 0xd6, 0xe5, 0x2f, 0x28, 0x9c, 0x95, 0xdd, 0x0b, 0x64, 0xf0, 0x85, 0x9a, 0xfa, - 0x43, 0x28, 0xca, 0x0a, 0x21, 0x8a, 0x73, 0x54, 0xae, 0xb4, 0x17, 0x94, 0xab, 0xa0, 0xba, 0x67, - 0x26, 0x55, 0xf7, 0xd8, 0x81, 0x70, 0xa0, 0xec, 0xeb, 0x06, 0x17, 0x4e, 0x2a, 0x0b, 0x57, 0xa1, - 0x10, 0x2c, 0x5c, 0x59, 0x09, 0x1b, 0x8d, 0x00, 0x08, 0x87, 0x12, 0x31, 0x6b, 0x47, 0x90, 0xa8, - 0x76, 0xe9, 0x8c, 0xc5, 0xaa, 0x6f, 0xe6, 0xc5, 0xd5, 0x37, 0x66, 0xe9, 0x67, 0x50, 0x99, 0xd4, - 0x9d, 0xbc, 0x44, 0x3d, 0x4e, 0xef, 0x8a, 0xfe, 0x6b, 0x0d, 0x96, 0xe2, 0x48, 0xe9, 0xb7, 0x2f, - 0xbd, 0x91, 0xcb, 0xef, 0xf1, 0x58, 0x44, 0x7e, 0xab, 0xc1, 0x4a, 0x62, 0x69, 0x53, 0xed, 0xf8, - 0x14, 0x4e, 0xc5, 0x93, 0x23, 0x3b, 0x45, 0x72, 0x34, 0xa0, 0xb4, 0x1b, 0xe6, 0x3d, 0xbd, 0xbc, - 0xf3, 0xd1, 0xff, 0xa2, 0xc1, 0x7c, 0x4c, 0x83, 0xa1, 0x87, 0x30, 0x27, 0xea, 0x9b, 0xed, 0x76, - 0x54, 0x57, 0x96, 0xf2, 0xb2, 0x8c, 0x81, 0x44, 0xeb, 0x6a, 0xf9, 0x48, 0x38, 0x80, 0x44, 0x2d, - 0xc8, 0x53, 0xc2, 0xfa, 0x0e, 0x57, 0xa5, 0xfd, 0x6a, 0xca, 0x6b, 0x8d, 0x9b, 0xbc, 0xcf, 0x0c, - 0x10, 0x35, 0x0a, 0x4b, 0x7d, 0xac, 0x70, 0xf4, 0xbf, 0x67, 0xa0, 0x7c, 0xdb, 0x3c, 0x20, 0xce, - 0x3e, 0x71, 0x88, 0xc5, 0x3d, 0x8a, 0x7e, 0x0a, 0xa5, 0xae, 0xc9, 0xad, 0x23, 0x49, 0x0d, 0x7a, - 0xcb, 0x66, 0x3a, 0x43, 0x09, 0xa4, 0xfa, 0x5e, 0x04, 0xb3, 0xe3, 0x72, 0x7a, 0x66, 0xbc, 0xa2, - 0x16, 0x56, 0x8a, 0x71, 0x70, 0xdc, 0x9a, 0x7c, 0x10, 0xc8, 0xef, 0x9d, 0xd3, 0x9e, 0xb8, 0x44, - 0xa7, 0x7f, 0x87, 0x24, 0x5c, 0xc0, 0xe4, 0xfd, 0xbe, 0x4d, 0x49, 0x97, 0xb8, 0x3c, 0x7a, 0x10, - 0xec, 0x8d, 0xe0, 0xe3, 0x31, 0x8b, 0xab, 0x37, 0x60, 0x69, 0xd4, 0x79, 0xb4, 0x04, 0xd9, 0x63, - 0x72, 0xe6, 0xe7, 0x02, 0x16, 0x3f, 0xd1, 0x0a, 0xe4, 0x4e, 0x4c, 0xa7, 0xaf, 0xea, 0x0f, 0xf6, - 0x3f, 0xae, 0x67, 0xae, 0x69, 0xfa, 0xef, 0x35, 0xa8, 0x4c, 0x72, 0x04, 0x7d, 0x31, 0x06, 0x64, - 0x94, 0x94, 0x57, 0xd9, 0x77, 0xc9, 0x99, 0x8f, 0xba, 0x03, 0x05, 0xaf, 0x27, 0x9e, 0x70, 0x1e, - 0x55, 0x79, 0xfe, 0x66, 0x90, 0xbb, 0x77, 0x15, 0xfd, 0x7c, 0x50, 0xbb, 0x92, 0x80, 0x0f, 0x18, - 0x38, 0x54, 0x45, 0x3a, 0xe4, 0xa5, 0x3f, 0xe2, 0x52, 0x16, 0xed, 0x93, 0xdc, 0xfc, 0xfb, 0x92, - 0x82, 0x15, 0x47, 0xff, 0x93, 0x06, 0xb3, 0xb2, 0x3d, 0x7c, 0x08, 0x05, 0x11, 0xbf, 0xb6, 0xc9, - 0x4d, 0xe9, 0x57, 0xea, 0xc7, 0x84, 0xd0, 0xde, 0x23, 0xdc, 0x8c, 0xce, 0x57, 0x40, 0xc1, 0x21, - 0x22, 0xc2, 0x90, 0xb3, 0x39, 0xe9, 0x06, 0x1b, 0xf9, 0xd6, 0x44, 0x68, 0xf5, 0xfe, 0xad, 0x63, - 0xf3, 0xd1, 0xce, 0x29, 0x27, 0xae, 0xd8, 0x8c, 0xa8, 0x18, 0xec, 0x0a, 0x0c, 0xec, 0x43, 0xe9, - 0x7f, 0xd0, 0x20, 0x34, 0x25, 0x8e, 0x3b, 0x23, 0xce, 0xe1, 0x6d, 0xdb, 0x3d, 0x56, 0x61, 0x0d, - 0xdd, 0xd9, 0x57, 0x74, 0x1c, 0x4a, 0x5c, 0x74, 0xc5, 0x66, 0xa6, 0xbc, 0x62, 0xaf, 0x42, 0xc1, - 0xf2, 0x5c, 0x6e, 0xbb, 0xfd, 0xb1, 0xfa, 0xb2, 0xad, 0xe8, 0x38, 0x94, 0xd0, 0x9f, 0x65, 0xa1, - 0x24, 0x7c, 0x0d, 0xee, 0xf8, 0x6f, 0x42, 0xd9, 0x89, 0xef, 0x9e, 0xf2, 0xf9, 0x8a, 0x82, 0x48, - 0x9e, 0x47, 0x9c, 0x94, 0x15, 0xca, 0x87, 0x36, 0x71, 0xda, 0xa1, 0x72, 0x26, 0xa9, 0x7c, 0x33, - 0xce, 0xc4, 0x49, 0x59, 0x51, 0x67, 0x1f, 0x89, 0xbc, 0x56, 0x8d, 0x5a, 0x18, 0xda, 0xef, 0x09, - 0x22, 0xf6, 0x79, 0x17, 0xc5, 0x67, 0x76, 0xca, 0xf8, 0x5c, 0x87, 0x05, 0xb1, 0x91, 0x5e, 0x9f, - 0x07, 0xdd, 0x6c, 0x4e, 0xf6, 0x5d, 0x68, 0x38, 0xa8, 0x2d, 0xbc, 0x97, 0xe0, 0xe0, 0x11, 0xc9, - 0x89, 0xed, 0x4b, 0xfe, 0xd3, 0xb6, 0x2f, 0x62, 0xd5, 0x8e, 0xdd, 0xb5, 0x79, 0x65, 0x4e, 0x3a, - 0x11, 0xae, 0xfa, 0xb6, 0x20, 0x62, 0x9f, 0x97, 0xd8, 0xd2, 0xc2, 0xa5, 0x5b, 0xfa, 0x3e, 0x14, - 0xf7, 0x6c, 0x8b, 0x7a, 0x62, 0x2d, 0xe2, 0x62, 0x62, 0x89, 0xa6, 0x3d, 0x2c, 0xe0, 0xc1, 0x1a, - 0x03, 0xbe, 0x70, 0xc5, 0x35, 0x5d, 0xcf, 0x6f, 0xcd, 0x73, 0x91, 0x2b, 0x77, 0x04, 0x11, 0xfb, - 0xbc, 0xeb, 0x2b, 0xe2, 0x3e, 0xfa, 0xe5, 0x93, 0xda, 0xcc, 0xe3, 0x27, 0xb5, 0x99, 0x0f, 0x9f, - 0xa8, 0xbb, 0xe9, 0x5f, 0x00, 0x70, 0xf7, 0xe0, 0xc7, 0xc4, 0xf2, 0x73, 0xfe, 0xf2, 0x57, 0xb9, - 0xe8, 0x31, 0xd4, 0x30, 0x48, 0xbe, 0x60, 0x33, 0x23, 0x3d, 0x46, 0x8c, 0x87, 0x13, 0x92, 0xa8, - 0x01, 0xc5, 0xf0, 0xa5, 0xae, 0xf2, 0x7b, 0x59, 0xa9, 0x15, 0xc3, 0xe7, 0x3c, 0x8e, 0x64, 0x12, - 0x07, 0x70, 0xf6, 0xd2, 0x03, 0x68, 0x40, 0xb6, 0x6f, 0xb7, 0x65, 0x4a, 0x14, 0x8d, 0xaf, 0x06, - 0x05, 0xf0, 0xde, 0x6e, 0xf3, 0x7c, 0x50, 0x7b, 0x6d, 0xd2, 0x8c, 0x8b, 0x9f, 0xf5, 0x08, 0xab, - 0xdf, 0xdb, 0x6d, 0x62, 0xa1, 0x7c, 0x51, 0x92, 0xe6, 0xa7, 0x4c, 0xd2, 0x4d, 0x00, 0xb5, 0x6a, - 0xa1, 0xed, 0xe7, 0x46, 0x38, 0xb5, 0xb8, 0x15, 0x72, 0x70, 0x4c, 0x0a, 0x31, 0x58, 0xb6, 0x28, - 0x91, 0xbf, 0xc5, 0xd6, 0x33, 0x6e, 0x76, 0xfd, 0x77, 0x7b, 0x69, 0xf3, 0xcb, 0xe9, 0x2a, 0xa6, - 0x50, 0x33, 0x5e, 0x55, 0x66, 0x96, 0xb7, 0x47, 0xc1, 0xf0, 0x38, 0x3e, 0xf2, 0x60, 0xb9, 0xad, - 0x5e, 0x3d, 0x91, 0xd1, 0xe2, 0xd4, 0x46, 0xaf, 0x08, 0x83, 0xcd, 0x51, 0x20, 0x3c, 0x8e, 0x8d, - 0x7e, 0x08, 0xab, 0x01, 0x71, 0xfc, 0xe9, 0x59, 0x01, 0x19, 0xa9, 0xaa, 0x78, 0x0c, 0x37, 0x27, - 0x4a, 0xe1, 0x17, 0x20, 0xa0, 0x36, 0xe4, 0x1d, 0xbf, 0xbb, 0x28, 0xc9, 0x1b, 0xe1, 0x5b, 0xe9, - 0x56, 0x11, 0x65, 0x7f, 0x3d, 0xde, 0x55, 0x84, 0xcf, 0x2f, 0xd5, 0x50, 0x28, 0x6c, 0x74, 0x0a, - 0x25, 0xd3, 0x75, 0x3d, 0x6e, 0xfa, 0x8f, 0xe1, 0x79, 0x69, 0x6a, 0x6b, 0x6a, 0x53, 0x5b, 0x11, - 0xc6, 0x48, 0x17, 0x13, 0xe3, 0xe0, 0xb8, 0x29, 0xf4, 0x08, 0x16, 0xbd, 0x47, 0x2e, 0xa1, 0x98, - 0x1c, 0x12, 0x4a, 0x5c, 0x8b, 0xb0, 0x4a, 0x59, 0x5a, 0xff, 0x5a, 0x4a, 0xeb, 0x09, 0xe5, 0x28, - 0xa5, 0x93, 0x74, 0x86, 0x47, 0xad, 0xa0, 0x3a, 0xc0, 0xa1, 0xed, 0xaa, 0x5e, 0xb4, 0xb2, 0x10, - 0x8d, 0x9e, 0x6e, 0x86, 0x54, 0x1c, 0x93, 0x40, 0x5f, 0x87, 0x92, 0xe5, 0xf4, 0x19, 0x27, 0xfe, - 0x8c, 0x6b, 0x51, 0x9e, 0xa0, 0x70, 0x7d, 0xdb, 0x11, 0x0b, 0xc7, 0xe5, 0xd0, 0x11, 0xcc, 0xdb, - 0xb1, 0xa6, 0xb7, 0xb2, 0x24, 0x73, 0x71, 0x73, 0xea, 0x4e, 0x97, 0x19, 0x4b, 0xa2, 0x12, 0xc5, - 0x29, 0x38, 0x81, 0xbc, 0xfa, 0x0d, 0x28, 0x7d, 0xca, 0x1e, 0x4c, 0xf4, 0x70, 0xa3, 0x5b, 0x37, - 0x55, 0x0f, 0xf7, 0xd7, 0x0c, 0x2c, 0x24, 0x03, 0x1e, 0xbe, 0x75, 0xb4, 0x89, 0x33, 0xcb, 0xa0, - 0x2a, 0x67, 0x27, 0x56, 0x65, 0x55, 0xfc, 0x66, 0x5f, 0xa6, 0xf8, 0x6d, 0x02, 0x98, 0x3d, 0x3b, - 0xa8, 0x7b, 0x7e, 0x1d, 0x0d, 0x2b, 0x57, 0x34, 0x45, 0xc3, 0x31, 0x29, 0x39, 0x95, 0xf4, 0x5c, - 0x4e, 0x3d, 0xc7, 0x21, 0x54, 0x5d, 0xa6, 0xfe, 0x54, 0x32, 0xa4, 0xe2, 0x98, 0x04, 0xba, 0x09, - 0xe8, 0xc0, 0xf1, 0xac, 0x63, 0x19, 0x82, 0xe0, 0x9c, 0xcb, 0x2a, 0x59, 0xf0, 0x87, 0x52, 0xc6, - 0x18, 0x17, 0x5f, 0xa0, 0xa1, 0xcf, 0x41, 0xae, 0x25, 0xda, 0x0a, 0xfd, 0x2e, 0x24, 0xe7, 0x49, - 0xe8, 0x86, 0x1f, 0x09, 0x2d, 0x1c, 0xf8, 0x4c, 0x17, 0x05, 0xfd, 0x2a, 0x14, 0xb1, 0xe7, 0xf1, - 0x96, 0xc9, 0x8f, 0x18, 0xaa, 0x41, 0xae, 0x27, 0x7e, 0xa8, 0x61, 0xa1, 0x9c, 0xff, 0x4a, 0x0e, - 0xf6, 0xe9, 0xfa, 0xaf, 0x34, 0x78, 0x75, 0xe2, 0xec, 0x4e, 0x44, 0xd4, 0x0a, 0xbf, 0x94, 0x4b, - 0x61, 0x44, 0x23, 0x39, 0x1c, 0x93, 0x12, 0x9d, 0x58, 0x62, 0xe0, 0x37, 0xda, 0x89, 0x25, 0xac, - 0xe1, 0xa4, 0xac, 0xfe, 0xef, 0x0c, 0xe4, 0xfd, 0x67, 0xd9, 0x7f, 0xb9, 0xf9, 0x7e, 0x03, 0xf2, - 0x4c, 0xda, 0x51, 0xee, 0x85, 0xd5, 0xd2, 0xb7, 0x8e, 0x15, 0x57, 0x34, 0x31, 0x5d, 0xc2, 0x98, - 0xd9, 0x09, 0x92, 0x37, 0x6c, 0x62, 0xf6, 0x7c, 0x32, 0x0e, 0xf8, 0xe8, 0x1d, 0xf1, 0x0a, 0x35, - 0x59, 0xd8, 0x17, 0x56, 0x03, 0x48, 0x2c, 0xa9, 0xe7, 0x83, 0xda, 0xbc, 0x02, 0x97, 0xdf, 0x58, - 0x49, 0xa3, 0x07, 0x30, 0xd7, 0x26, 0xdc, 0xb4, 0x1d, 0xbf, 0x1d, 0x4c, 0x3d, 0x99, 0xf4, 0xc1, - 0x9a, 0xbe, 0xaa, 0x51, 0x12, 0x3e, 0xa9, 0x0f, 0x1c, 0x00, 0x8a, 0x83, 0x67, 0x79, 0x6d, 0x7f, - 0x4c, 0x9f, 0x8b, 0x0e, 0xde, 0xb6, 0xd7, 0x26, 0x58, 0x72, 0xf4, 0xc7, 0x1a, 0x94, 0x7c, 0xa4, - 0x6d, 0xb3, 0xcf, 0x08, 0xda, 0x08, 0x57, 0xe1, 0x6f, 0x77, 0x70, 0x27, 0xcf, 0xbe, 0x77, 0xd6, - 0x23, 0xe7, 0x83, 0x5a, 0x51, 0x8a, 0x89, 0x8f, 0x70, 0x01, 0xb1, 0x18, 0x65, 0x2e, 0x89, 0xd1, - 0xeb, 0x90, 0x93, 0xad, 0xb7, 0x0a, 0x66, 0xd8, 0xe8, 0xc9, 0xf6, 0x1c, 0xfb, 0x3c, 0xfd, 0xe3, - 0x0c, 0x94, 0x13, 0x8b, 0x4b, 0xd1, 0xd5, 0x85, 0xa3, 0x92, 0x4c, 0x8a, 0xf1, 0xdb, 0xe4, 0x7f, - 0xae, 0x7c, 0x1f, 0xf2, 0x96, 0x58, 0x5f, 0xf0, 0xdf, 0xad, 0x8d, 0x69, 0xb6, 0x42, 0x46, 0x26, - 0xca, 0x24, 0xf9, 0xc9, 0xb0, 0x02, 0x44, 0xb7, 0x60, 0x99, 0x12, 0x4e, 0xcf, 0xb6, 0x0e, 0x39, - 0xa1, 0xf1, 0xfe, 0x3f, 0x17, 0xf5, 0x3d, 0x78, 0x54, 0x00, 0x8f, 0xeb, 0x04, 0xa5, 0x32, 0xff, - 0x12, 0xa5, 0x52, 0x77, 0x60, 0xf6, 0x7f, 0xd8, 0xa3, 0xff, 0x00, 0x8a, 0x51, 0x17, 0xf5, 0x19, - 0x9b, 0xd4, 0x7f, 0x04, 0x05, 0x91, 0x8d, 0x41, 0xf7, 0x7f, 0xc9, 0x4d, 0x94, 0xbc, 0x23, 0x32, - 0x69, 0xee, 0x08, 0x7d, 0x13, 0xfc, 0xff, 0x99, 0x89, 0x6a, 0xea, 0xbf, 0xd8, 0x63, 0xd5, 0x34, - 0xfe, 0xfc, 0x8e, 0x8d, 0xcc, 0x7e, 0xa1, 0x01, 0xc8, 0xe7, 0xe3, 0xce, 0x09, 0x71, 0xb9, 0x70, - 0x4c, 0xec, 0xc0, 0xa8, 0x63, 0xf2, 0x18, 0x49, 0x0e, 0xba, 0x07, 0x79, 0x4f, 0x76, 0x57, 0x6a, - 0x86, 0x35, 0xe5, 0x38, 0x20, 0xcc, 0x3a, 0xbf, 0x45, 0xc3, 0x0a, 0xcc, 0x58, 0x7f, 0xfa, 0xbc, - 0x3a, 0xf3, 0xec, 0x79, 0x75, 0xe6, 0xa3, 0xe7, 0xd5, 0x99, 0x0f, 0x86, 0x55, 0xed, 0xe9, 0xb0, - 0xaa, 0x3d, 0x1b, 0x56, 0xb5, 0x8f, 0x86, 0x55, 0xed, 0xe3, 0x61, 0x55, 0x7b, 0xfc, 0x49, 0x75, - 0xe6, 0x41, 0xe6, 0x64, 0xe3, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6c, 0xc5, 0x28, 0xb2, 0x54, - 0x20, 0x00, 0x00, + 0xf6, 0x3e, 0xb1, 0x3c, 0xb7, 0xcd, 0xe4, 0x11, 0x65, 0x8d, 0xcf, 0x0d, 0x07, 0x35, 0x74, 0x6b, + 0x8c, 0x8b, 0x2f, 0xd0, 0x40, 0x0e, 0x94, 0x7b, 0x54, 0xfe, 0xb6, 0xb9, 0x2a, 0xe0, 0x22, 0x71, + 0xde, 0x4e, 0xb7, 0xf6, 0x56, 0x5c, 0xd5, 0x58, 0x1e, 0x0e, 0x6a, 0xe5, 0x04, 0x09, 0x27, 0xc1, + 0xd1, 0x77, 0x61, 0xc9, 0xa3, 0xbd, 0x23, 0xd3, 0x6d, 0x92, 0x1e, 0x71, 0xdb, 0xc4, 0xe5, 0x4c, + 0x26, 0x73, 0xc1, 0x58, 0x11, 0x65, 0xf7, 0xee, 0x08, 0x0f, 0x8f, 0x49, 0xa3, 0x07, 0xb0, 0xdc, + 0xa3, 0x5e, 0xcf, 0xec, 0x98, 0x02, 0xb1, 0xe5, 0x39, 0xb6, 0x75, 0x26, 0x93, 0xbd, 0x68, 0x5c, + 0x1d, 0x0e, 0x6a, 0xcb, 0xad, 0x51, 0xe6, 0xf9, 0xa0, 0xf6, 0x8a, 0xdc, 0x3a, 0x41, 0x89, 0x98, + 0x78, 0x1c, 0x46, 0xdf, 0x85, 0x42, 0xb3, 0x4f, 0x25, 0x05, 0x7d, 0x1b, 0x0a, 0x6d, 0xf5, 0x5b, + 0xed, 0xea, 0x6b, 0xc1, 0x9d, 0x14, 0xc8, 0x9c, 0x0f, 0x6a, 0x65, 0x71, 0xf5, 0xd6, 0x03, 0x02, + 0x0e, 0x55, 0xf4, 0x87, 0x50, 0xde, 0x39, 0xed, 0x79, 0x94, 0x07, 0xe7, 0xf5, 0x06, 0xe4, 0x89, + 0x24, 0x48, 0xb4, 0x42, 0x54, 0x48, 0x7d, 0x31, 0xac, 0xb8, 0x22, 0xb1, 0xc9, 0xa9, 0x69, 0x71, + 0x55, 0x11, 0xc3, 0xc4, 0xde, 0x11, 0x44, 0xec, 0xf3, 0xf4, 0x27, 0x1a, 0xc0, 0x2d, 0x12, 0x62, + 0x6f, 0xc1, 0x62, 0x90, 0x14, 0xc9, 0x5c, 0xfd, 0xbc, 0xd2, 0x5e, 0xc4, 0x49, 0x36, 0x1e, 0x95, + 0x47, 0x2d, 0x58, 0xb1, 0x5d, 0xcb, 0xe9, 0xb7, 0xc9, 0x3d, 0xd7, 0x76, 0x6d, 0x6e, 0x9b, 0x8e, + 0xfd, 0x93, 0xb0, 0x2e, 0x7f, 0x41, 0xe1, 0xac, 0xec, 0x5e, 0x20, 0x83, 0x2f, 0xd4, 0xd4, 0x1f, + 0x42, 0x51, 0x56, 0x08, 0x51, 0x9c, 0xa3, 0x72, 0xa5, 0xbd, 0xa0, 0x5c, 0x05, 0xd5, 0x3d, 0x33, + 0xa9, 0xba, 0xc7, 0x12, 0xc2, 0x81, 0xb2, 0xaf, 0x1b, 0x5c, 0x38, 0xa9, 0x2c, 0x5c, 0x85, 0x42, + 0xb0, 0x70, 0x65, 0x25, 0x6c, 0x34, 0x02, 0x20, 0x1c, 0x4a, 0xc4, 0xac, 0x1d, 0x41, 0xa2, 0xda, + 0xa5, 0x33, 0x16, 0xab, 0xbe, 0x99, 0x17, 0x57, 0xdf, 0x98, 0xa5, 0x9f, 0x41, 0x65, 0x52, 0x77, + 0xf2, 0x12, 0xf5, 0x38, 0xbd, 0x2b, 0xfa, 0xaf, 0x35, 0x58, 0x8a, 0x23, 0xa5, 0x3f, 0xbe, 0xf4, + 0x46, 0x2e, 0xbf, 0xc7, 0x63, 0x3b, 0xf2, 0x5b, 0x0d, 0x56, 0x12, 0x4b, 0x9b, 0xea, 0xc4, 0xa7, + 0x70, 0x2a, 0x1e, 0x1c, 0xd9, 0x29, 0x82, 0xa3, 0x01, 0xa5, 0xdd, 0x30, 0xee, 0xe9, 0xe5, 0x9d, + 0x8f, 0xfe, 0x17, 0x0d, 0xe6, 0x63, 0x1a, 0x0c, 0x3d, 0x84, 0x39, 0x51, 0xdf, 0x6c, 0xb7, 0xa3, + 0xba, 0xb2, 0x94, 0x97, 0x65, 0x0c, 0x24, 0x5a, 0x57, 0xcb, 0x47, 0xc2, 0x01, 0x24, 0x6a, 0x41, + 0x9e, 0x12, 0xd6, 0x77, 0xb8, 0x2a, 0xed, 0x57, 0x53, 0x5e, 0x6b, 0xdc, 0xe4, 0x7d, 0x66, 0x80, + 0xa8, 0x51, 0x58, 0xea, 0x63, 0x85, 0xa3, 0xff, 0x3d, 0x03, 0xe5, 0xdb, 0xe6, 0x01, 0x71, 0xf6, + 0x89, 0x43, 0x2c, 0xee, 0x51, 0xf4, 0x53, 0x28, 0x75, 0x4d, 0x6e, 0x1d, 0x49, 0x6a, 0xd0, 0x5b, + 0x36, 0xd3, 0x19, 0x4a, 0x20, 0xd5, 0xf7, 0x22, 0x98, 0x1d, 0x97, 0xd3, 0x33, 0xe3, 0x15, 0xb5, + 0xb0, 0x52, 0x8c, 0x83, 0xe3, 0xd6, 0xe4, 0x83, 0x40, 0x7e, 0xef, 0x9c, 0xf6, 0xc4, 0x25, 0x3a, + 0xfd, 0x3b, 0x24, 0xe1, 0x02, 0x26, 0xef, 0xf7, 0x6d, 0x4a, 0xba, 0xc4, 0xe5, 0xd1, 0x83, 0x60, + 0x6f, 0x04, 0x1f, 0x8f, 0x59, 0x5c, 0xbd, 0x01, 0x4b, 0xa3, 0xce, 0xa3, 0x25, 0xc8, 0x1e, 0x93, + 0x33, 0x3f, 0x16, 0xb0, 0xf8, 0x89, 0x56, 0x20, 0x77, 0x62, 0x3a, 0x7d, 0x55, 0x7f, 0xb0, 0xff, + 0x71, 0x3d, 0x73, 0x4d, 0xd3, 0x7f, 0xaf, 0x41, 0x65, 0x92, 0x23, 0xe8, 0x8b, 0x31, 0x20, 0xa3, + 0xa4, 0xbc, 0xca, 0xbe, 0x4b, 0xce, 0x7c, 0xd4, 0x1d, 0x28, 0x78, 0x3d, 0xf1, 0x84, 0xf3, 0xa8, + 0x8a, 0xf3, 0x37, 0x83, 0xd8, 0xbd, 0xab, 0xe8, 0xe7, 0x83, 0xda, 0x95, 0x04, 0x7c, 0xc0, 0xc0, + 0xa1, 0x2a, 0xd2, 0x21, 0x2f, 0xfd, 0x11, 0x97, 0xb2, 0x68, 0x9f, 0xe4, 0xe1, 0xdf, 0x97, 0x14, + 0xac, 0x38, 0xfa, 0x9f, 0x34, 0x98, 0x95, 0xed, 0xe1, 0x43, 0x28, 0x88, 0xfd, 0x6b, 0x9b, 0xdc, + 0x94, 0x7e, 0xa5, 0x7e, 0x4c, 0x08, 0xed, 0x3d, 0xc2, 0xcd, 0x28, 0xbf, 0x02, 0x0a, 0x0e, 0x11, + 0x11, 0x86, 0x9c, 0xcd, 0x49, 0x37, 0x38, 0xc8, 0xb7, 0x26, 0x42, 0xab, 0xf7, 0x6f, 0x1d, 0x9b, + 0x8f, 0x76, 0x4e, 0x39, 0x71, 0xc5, 0x61, 0x44, 0xc5, 0x60, 0x57, 0x60, 0x60, 0x1f, 0x4a, 0xff, + 0x83, 0x06, 0xa1, 0x29, 0x91, 0xee, 0x8c, 0x38, 0x87, 0xb7, 0x6d, 0xf7, 0x58, 0x6d, 0x6b, 0xe8, + 0xce, 0xbe, 0xa2, 0xe3, 0x50, 0xe2, 0xa2, 0x2b, 0x36, 0x33, 0xe5, 0x15, 0x7b, 0x15, 0x0a, 0x96, + 0xe7, 0x72, 0xdb, 0xed, 0x8f, 0xd5, 0x97, 0x6d, 0x45, 0xc7, 0xa1, 0x84, 0xfe, 0x2c, 0x0b, 0x25, + 0xe1, 0x6b, 0x70, 0xc7, 0x7f, 0x13, 0xca, 0x4e, 0xfc, 0xf4, 0x94, 0xcf, 0x57, 0x14, 0x44, 0x32, + 0x1f, 0x71, 0x52, 0x56, 0x28, 0x1f, 0xda, 0xc4, 0x69, 0x87, 0xca, 0x99, 0xa4, 0xf2, 0xcd, 0x38, + 0x13, 0x27, 0x65, 0x45, 0x9d, 0x7d, 0x24, 0xe2, 0x5a, 0x35, 0x6a, 0xe1, 0xd6, 0x7e, 0x4f, 0x10, + 0xb1, 0xcf, 0xbb, 0x68, 0x7f, 0x66, 0xa7, 0xdc, 0x9f, 0xeb, 0xb0, 0x20, 0x0e, 0xd2, 0xeb, 0xf3, + 0xa0, 0x9b, 0xcd, 0xc9, 0xbe, 0x0b, 0x0d, 0x07, 0xb5, 0x85, 0xf7, 0x12, 0x1c, 0x3c, 0x22, 0x39, + 0xb1, 0x7d, 0xc9, 0x7f, 0xda, 0xf6, 0x45, 0xac, 0xda, 0xb1, 0xbb, 0x36, 0xaf, 0xcc, 0x49, 0x27, + 0xc2, 0x55, 0xdf, 0x16, 0x44, 0xec, 0xf3, 0x12, 0x47, 0x5a, 0xb8, 0xf4, 0x48, 0xdf, 0x87, 0xe2, + 0x9e, 0x6d, 0x51, 0x4f, 0xac, 0x45, 0x5c, 0x4c, 0x2c, 0xd1, 0xb4, 0x87, 0x05, 0x3c, 0x58, 0x63, + 0xc0, 0x17, 0xae, 0xb8, 0xa6, 0xeb, 0xf9, 0xad, 0x79, 0x2e, 0x72, 0xe5, 0x8e, 0x20, 0x62, 0x9f, + 0x77, 0x7d, 0x45, 0xdc, 0x47, 0xbf, 0x7c, 0x52, 0x9b, 0x79, 0xfc, 0xa4, 0x36, 0xf3, 0xe1, 0x13, + 0x75, 0x37, 0xfd, 0x0b, 0x00, 0xee, 0x1e, 0xfc, 0x98, 0x58, 0x7e, 0xcc, 0x5f, 0xfe, 0x2a, 0x17, + 0x3d, 0x86, 0x1a, 0x06, 0xc9, 0x17, 0x6c, 0x66, 0xa4, 0xc7, 0x88, 0xf1, 0x70, 0x42, 0x12, 0x35, + 0xa0, 0x18, 0xbe, 0xd4, 0x55, 0x7c, 0x2f, 0x2b, 0xb5, 0x62, 0xf8, 0x9c, 0xc7, 0x91, 0x4c, 0x22, + 0x01, 0x67, 0x2f, 0x4d, 0x40, 0x03, 0xb2, 0x7d, 0xbb, 0x2d, 0x43, 0xa2, 0x68, 0x7c, 0x35, 0x28, + 0x80, 0xf7, 0x76, 0x9b, 0xe7, 0x83, 0xda, 0x6b, 0x93, 0x66, 0x5c, 0xfc, 0xac, 0x47, 0x58, 0xfd, + 0xde, 0x6e, 0x13, 0x0b, 0xe5, 0x8b, 0x82, 0x34, 0x3f, 0x65, 0x90, 0x6e, 0x02, 0xa8, 0x55, 0x0b, + 0x6d, 0x3f, 0x36, 0xc2, 0xa9, 0xc5, 0xad, 0x90, 0x83, 0x63, 0x52, 0x88, 0xc1, 0xb2, 0x45, 0x89, + 0xfc, 0x2d, 0x8e, 0x9e, 0x71, 0xb3, 0xeb, 0xbf, 0xdb, 0x4b, 0x9b, 0x5f, 0x4e, 0x57, 0x31, 0x85, + 0x9a, 0xf1, 0xaa, 0x32, 0xb3, 0xbc, 0x3d, 0x0a, 0x86, 0xc7, 0xf1, 0x91, 0x07, 0xcb, 0x6d, 0xf5, + 0xea, 0x89, 0x8c, 0x16, 0xa7, 0x36, 0x7a, 0x45, 0x18, 0x6c, 0x8e, 0x02, 0xe1, 0x71, 0x6c, 0xf4, + 0x43, 0x58, 0x0d, 0x88, 0xe3, 0x4f, 0xcf, 0x0a, 0xc8, 0x9d, 0xaa, 0x8a, 0xc7, 0x70, 0x73, 0xa2, + 0x14, 0x7e, 0x01, 0x02, 0x6a, 0x43, 0xde, 0xf1, 0xbb, 0x8b, 0x92, 0xbc, 0x11, 0xbe, 0x95, 0x6e, + 0x15, 0x51, 0xf4, 0xd7, 0xe3, 0x5d, 0x45, 0xf8, 0xfc, 0x52, 0x0d, 0x85, 0xc2, 0x46, 0xa7, 0x50, + 0x32, 0x5d, 0xd7, 0xe3, 0xa6, 0xff, 0x18, 0x9e, 0x97, 0xa6, 0xb6, 0xa6, 0x36, 0xb5, 0x15, 0x61, + 0x8c, 0x74, 0x31, 0x31, 0x0e, 0x8e, 0x9b, 0x42, 0x8f, 0x60, 0xd1, 0x7b, 0xe4, 0x12, 0x8a, 0xc9, + 0x21, 0xa1, 0xc4, 0xb5, 0x08, 0xab, 0x94, 0xa5, 0xf5, 0xaf, 0xa5, 0xb4, 0x9e, 0x50, 0x8e, 0x42, + 0x3a, 0x49, 0x67, 0x78, 0xd4, 0x0a, 0xaa, 0x03, 0x1c, 0xda, 0xae, 0xea, 0x45, 0x2b, 0x0b, 0xd1, + 0xe8, 0xe9, 0x66, 0x48, 0xc5, 0x31, 0x09, 0xf4, 0x75, 0x28, 0x59, 0x4e, 0x9f, 0x71, 0xe2, 0xcf, + 0xb8, 0x16, 0x65, 0x06, 0x85, 0xeb, 0xdb, 0x8e, 0x58, 0x38, 0x2e, 0x87, 0x8e, 0x60, 0xde, 0x8e, + 0x35, 0xbd, 0x95, 0x25, 0x19, 0x8b, 0x9b, 0x53, 0x77, 0xba, 0xcc, 0x58, 0x12, 0x95, 0x28, 0x4e, + 0xc1, 0x09, 0xe4, 0xd5, 0x6f, 0x40, 0xe9, 0x53, 0xf6, 0x60, 0xa2, 0x87, 0x1b, 0x3d, 0xba, 0xa9, + 0x7a, 0xb8, 0xbf, 0x66, 0x60, 0x21, 0xb9, 0xe1, 0xe1, 0x5b, 0x47, 0x9b, 0x38, 0xb3, 0x0c, 0xaa, + 0x72, 0x76, 0x62, 0x55, 0x56, 0xc5, 0x6f, 0xf6, 0x65, 0x8a, 0xdf, 0x26, 0x80, 0xd9, 0xb3, 0x83, + 0xba, 0xe7, 0xd7, 0xd1, 0xb0, 0x72, 0x45, 0x53, 0x34, 0x1c, 0x93, 0x92, 0x53, 0x49, 0xcf, 0xe5, + 0xd4, 0x73, 0x1c, 0x42, 0xd5, 0x65, 0xea, 0x4f, 0x25, 0x43, 0x2a, 0x8e, 0x49, 0xa0, 0x9b, 0x80, + 0x0e, 0x1c, 0xcf, 0x3a, 0x96, 0x5b, 0x10, 0xe4, 0xb9, 0xac, 0x92, 0x05, 0x7f, 0x28, 0x65, 0x8c, + 0x71, 0xf1, 0x05, 0x1a, 0xfa, 0x5d, 0x48, 0x8e, 0x91, 0xd0, 0x0d, 0x7f, 0x03, 0xb4, 0x70, 0xce, + 0x33, 0xdd, 0xe2, 0xf5, 0xab, 0x50, 0xc4, 0x9e, 0xc7, 0x5b, 0x26, 0x3f, 0x62, 0xa8, 0x06, 0xb9, + 0x9e, 0xf8, 0xa1, 0x66, 0x84, 0x72, 0xec, 0x2b, 0x39, 0xd8, 0xa7, 0xeb, 0xbf, 0xd2, 0xe0, 0xd5, + 0x89, 0x23, 0x3b, 0xb1, 0x91, 0x56, 0xf8, 0xa5, 0x5c, 0x0a, 0x37, 0x32, 0x92, 0xc3, 0x31, 0x29, + 0xd1, 0x80, 0x25, 0xe6, 0x7c, 0xa3, 0x0d, 0x58, 0xc2, 0x1a, 0x4e, 0xca, 0xea, 0xff, 0xce, 0x40, + 0xde, 0x7f, 0x8d, 0xfd, 0x97, 0x7b, 0xee, 0x37, 0x20, 0xcf, 0xa4, 0x1d, 0xe5, 0x5e, 0x58, 0x24, + 0x7d, 0xeb, 0x58, 0x71, 0x45, 0xef, 0xd2, 0x25, 0x8c, 0x99, 0x9d, 0x20, 0x66, 0xc3, 0xde, 0x65, + 0xcf, 0x27, 0xe3, 0x80, 0x8f, 0xde, 0x11, 0x8f, 0x4f, 0x93, 0x85, 0xed, 0x60, 0x35, 0x80, 0xc4, + 0x92, 0x7a, 0x3e, 0xa8, 0xcd, 0x2b, 0x70, 0xf9, 0x8d, 0x95, 0x34, 0x7a, 0x00, 0x73, 0x6d, 0xc2, + 0x4d, 0xdb, 0xf1, 0xbb, 0xc0, 0xd4, 0x03, 0x49, 0x1f, 0xac, 0xe9, 0xab, 0x1a, 0x25, 0xe1, 0x93, + 0xfa, 0xc0, 0x01, 0xa0, 0xc8, 0x37, 0xcb, 0x6b, 0xfb, 0xd3, 0xf9, 0x5c, 0x94, 0x6f, 0xdb, 0x5e, + 0x9b, 0x60, 0xc9, 0xd1, 0x1f, 0x6b, 0x50, 0xf2, 0x91, 0xb6, 0xcd, 0x3e, 0x23, 0x68, 0x23, 0x5c, + 0x85, 0x7f, 0xdc, 0xc1, 0x55, 0x3c, 0xfb, 0xde, 0x59, 0x8f, 0x9c, 0x0f, 0x6a, 0x45, 0x29, 0x26, + 0x3e, 0xc2, 0x05, 0xc4, 0xf6, 0x28, 0x73, 0xc9, 0x1e, 0xbd, 0x0e, 0x39, 0xd9, 0x71, 0xab, 0xcd, + 0x0c, 0xfb, 0x3b, 0xd9, 0x95, 0x63, 0x9f, 0xa7, 0x7f, 0x9c, 0x81, 0x72, 0x62, 0x71, 0x29, 0x9a, + 0xb9, 0x70, 0x42, 0x92, 0x49, 0x31, 0x75, 0x9b, 0xfc, 0x3f, 0x95, 0xef, 0x43, 0xde, 0x12, 0xeb, + 0x0b, 0xfe, 0xa9, 0xb5, 0x31, 0xcd, 0x51, 0xc8, 0x9d, 0x89, 0x22, 0x49, 0x7e, 0x32, 0xac, 0x00, + 0xd1, 0x2d, 0x58, 0xa6, 0x84, 0xd3, 0xb3, 0xad, 0x43, 0x4e, 0x68, 0xbc, 0xed, 0xcf, 0x45, 0xed, + 0x0e, 0x1e, 0x15, 0xc0, 0xe3, 0x3a, 0x41, 0x85, 0xcc, 0xbf, 0x44, 0x85, 0xd4, 0x1d, 0x98, 0xfd, + 0x1f, 0xb6, 0xe6, 0x3f, 0x80, 0x62, 0xd4, 0x3c, 0x7d, 0xc6, 0x26, 0xf5, 0x1f, 0x41, 0x41, 0x44, + 0x63, 0xd0, 0xf4, 0x5f, 0x72, 0x01, 0x25, 0xaf, 0x86, 0x4c, 0x9a, 0xab, 0x41, 0xdf, 0x04, 0xff, + 0x5f, 0x65, 0xa2, 0x9a, 0xfa, 0x0f, 0xf5, 0x58, 0x35, 0x8d, 0xbf, 0xba, 0x63, 0x93, 0xb2, 0x5f, + 0x68, 0x00, 0xf2, 0xd5, 0xb8, 0x73, 0x42, 0x5c, 0x2e, 0x1c, 0x13, 0x27, 0x30, 0xea, 0x98, 0x4c, + 0x23, 0xc9, 0x41, 0xf7, 0x20, 0xef, 0xc9, 0xa6, 0x4a, 0x8d, 0xae, 0xa6, 0x9c, 0x02, 0x84, 0x51, + 0xe7, 0x77, 0x66, 0x58, 0x81, 0x19, 0xeb, 0x4f, 0x9f, 0x57, 0x67, 0x9e, 0x3d, 0xaf, 0xce, 0x7c, + 0xf4, 0xbc, 0x3a, 0xf3, 0xc1, 0xb0, 0xaa, 0x3d, 0x1d, 0x56, 0xb5, 0x67, 0xc3, 0xaa, 0xf6, 0xd1, + 0xb0, 0xaa, 0x7d, 0x3c, 0xac, 0x6a, 0x8f, 0x3f, 0xa9, 0xce, 0x3c, 0xc8, 0x9c, 0x6c, 0xfc, 0x27, + 0x00, 0x00, 0xff, 0xff, 0x66, 0xe7, 0x2a, 0x84, 0x4b, 0x20, 0x00, 0x00, } diff --git a/k8s.io/apimachinery/pkg/apis/meta/v1/register.go b/k8s.io/apimachinery/pkg/apis/meta/v1/register.go index b300d370..6e449a43 100644 --- a/k8s.io/apimachinery/pkg/apis/meta/v1/register.go +++ b/k8s.io/apimachinery/pkg/apis/meta/v1/register.go @@ -70,6 +70,7 @@ func AddToGroupVersion(scheme *runtime.Scheme, groupVersion schema.GroupVersion) ) // register manually. This usually goes through the SchemeBuilder, which we cannot use here. + scheme.AddGeneratedDeepCopyFuncs(GetGeneratedDeepCopyFuncs()...) AddConversionFuncs(scheme) RegisterDefaults(scheme) } @@ -89,5 +90,6 @@ func init() { ) // register manually. This usually goes through the SchemeBuilder, which we cannot use here. + scheme.AddGeneratedDeepCopyFuncs(GetGeneratedDeepCopyFuncs()...) RegisterDefaults(scheme) } diff --git a/k8s.io/apimachinery/pkg/apis/meta/v1/types.go b/k8s.io/apimachinery/pkg/apis/meta/v1/types.go index c8ee4e5d..13ae66c6 100644 --- a/k8s.io/apimachinery/pkg/apis/meta/v1/types.go +++ b/k8s.io/apimachinery/pkg/apis/meta/v1/types.go @@ -177,16 +177,15 @@ type ObjectMeta struct { // DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This // field is set by the server when a graceful deletion is requested by the user, and is not // directly settable by a client. The resource is expected to be deleted (no longer visible - // from resource lists, and not reachable by name) after the time in this field, once the - // finalizers list is empty. As long as the finalizers list contains items, deletion is blocked. - // Once the deletionTimestamp is set, this value may not be unset or be set further into the - // future, although it may be shortened or the resource may be deleted prior to this time. - // For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react - // by sending a graceful termination signal to the containers in the pod. After that 30 seconds, - // the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, - // remove the pod from the API. In the presence of network partitions, this object may still - // exist after this timestamp, until an administrator or automated process can determine the - // resource is fully terminated. + // from resource lists, and not reachable by name) after the time in this field. Once set, + // this value may not be unset or be set further into the future, although it may be shortened + // or the resource may be deleted prior to this time. For example, a user may request that + // a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination + // signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard + // termination signal (SIGKILL) to the container and after cleanup, remove the pod from the + // API. In the presence of network partitions, this object may still exist after this + // timestamp, until an administrator or automated process can determine the resource is + // fully terminated. // If not set, graceful deletion of the object has not been requested. // // Populated by the system when a graceful deletion is requested. @@ -446,10 +445,6 @@ type DeleteOptions struct { // Either this field or OrphanDependents may be set, but not both. // The default policy is decided by the existing finalizer set in the // metadata.finalizers and the resource-specific default policy. - // Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - - // allow the garbage collector to delete the dependents in the background; - // 'Foreground' - a cascading policy that deletes all dependents in the - // foreground. // +optional PropagationPolicy *DeletionPropagation `json:"propagationPolicy,omitempty" protobuf:"varint,4,opt,name=propagationPolicy"` } diff --git a/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go b/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go index 5dbba4b0..49d2de1e 100644 --- a/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go +++ b/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go @@ -90,7 +90,7 @@ var map_DeleteOptions = map[string]string{ "gracePeriodSeconds": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", "preconditions": "Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be returned.", "orphanDependents": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", - "propagationPolicy": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "propagationPolicy": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy.", } func (DeleteOptions) SwaggerDoc() map[string]string { @@ -214,7 +214,7 @@ var map_ObjectMeta = map[string]string{ "resourceVersion": "An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.\n\nPopulated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency", "generation": "A sequence number representing a specific generation of the desired state. Populated by the system. Read-only.", "creationTimestamp": "CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.\n\nPopulated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", - "deletionTimestamp": "DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field, once the finalizers list is empty. As long as the finalizers list contains items, deletion is blocked. Once the deletionTimestamp is set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.\n\nPopulated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "deletionTimestamp": "DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field. Once set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.\n\nPopulated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", "deletionGracePeriodSeconds": "Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only.", "labels": "Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels", "annotations": "Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations", diff --git a/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go b/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go deleted file mode 100644 index 8d035254..00000000 --- a/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go +++ /dev/null @@ -1,453 +0,0 @@ -/* -Copyright 2015 The Kubernetes 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 unstructured - -import ( - gojson "encoding/json" - "errors" - "fmt" - "io" - "strings" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/json" -) - -// NestedFieldCopy returns a deep copy of the value of a nested field. -// false is returned if the value is missing. -// nil, true is returned for a nil field. -func NestedFieldCopy(obj map[string]interface{}, fields ...string) (interface{}, bool) { - val, ok := nestedFieldNoCopy(obj, fields...) - if !ok { - return nil, false - } - return runtime.DeepCopyJSONValue(val), true -} - -func nestedFieldNoCopy(obj map[string]interface{}, fields ...string) (interface{}, bool) { - var val interface{} = obj - for _, field := range fields { - if m, ok := val.(map[string]interface{}); ok { - val, ok = m[field] - if !ok { - return nil, false - } - } else { - // Expected map[string]interface{}, got something else - return nil, false - } - } - return val, true -} - -// NestedString returns the string value of a nested field. -// Returns false if value is not found or is not a string. -func NestedString(obj map[string]interface{}, fields ...string) (string, bool) { - val, ok := nestedFieldNoCopy(obj, fields...) - if !ok { - return "", false - } - s, ok := val.(string) - return s, ok -} - -// NestedBool returns the bool value of a nested field. -// Returns false if value is not found or is not a bool. -func NestedBool(obj map[string]interface{}, fields ...string) (bool, bool) { - val, ok := nestedFieldNoCopy(obj, fields...) - if !ok { - return false, false - } - b, ok := val.(bool) - return b, ok -} - -// NestedFloat64 returns the bool value of a nested field. -// Returns false if value is not found or is not a float64. -func NestedFloat64(obj map[string]interface{}, fields ...string) (float64, bool) { - val, ok := nestedFieldNoCopy(obj, fields...) - if !ok { - return 0, false - } - f, ok := val.(float64) - return f, ok -} - -// NestedInt64 returns the int64 value of a nested field. -// Returns false if value is not found or is not an int64. -func NestedInt64(obj map[string]interface{}, fields ...string) (int64, bool) { - val, ok := nestedFieldNoCopy(obj, fields...) - if !ok { - return 0, false - } - i, ok := val.(int64) - return i, ok -} - -// NestedStringSlice returns a copy of []string value of a nested field. -// Returns false if value is not found, is not a []interface{} or contains non-string items in the slice. -func NestedStringSlice(obj map[string]interface{}, fields ...string) ([]string, bool) { - val, ok := nestedFieldNoCopy(obj, fields...) - if !ok { - return nil, false - } - if m, ok := val.([]interface{}); ok { - strSlice := make([]string, 0, len(m)) - for _, v := range m { - if str, ok := v.(string); ok { - strSlice = append(strSlice, str) - } else { - return nil, false - } - } - return strSlice, true - } - return nil, false -} - -// NestedSlice returns a deep copy of []interface{} value of a nested field. -// Returns false if value is not found or is not a []interface{}. -func NestedSlice(obj map[string]interface{}, fields ...string) ([]interface{}, bool) { - val, ok := nestedFieldNoCopy(obj, fields...) - if !ok { - return nil, false - } - if _, ok := val.([]interface{}); ok { - return runtime.DeepCopyJSONValue(val).([]interface{}), true - } - return nil, false -} - -// NestedStringMap returns a copy of map[string]string value of a nested field. -// Returns false if value is not found, is not a map[string]interface{} or contains non-string values in the map. -func NestedStringMap(obj map[string]interface{}, fields ...string) (map[string]string, bool) { - m, ok := nestedMapNoCopy(obj, fields...) - if !ok { - return nil, false - } - strMap := make(map[string]string, len(m)) - for k, v := range m { - if str, ok := v.(string); ok { - strMap[k] = str - } else { - return nil, false - } - } - return strMap, true -} - -// NestedMap returns a deep copy of map[string]interface{} value of a nested field. -// Returns false if value is not found or is not a map[string]interface{}. -func NestedMap(obj map[string]interface{}, fields ...string) (map[string]interface{}, bool) { - m, ok := nestedMapNoCopy(obj, fields...) - if !ok { - return nil, false - } - return runtime.DeepCopyJSON(m), true -} - -// nestedMapNoCopy returns a map[string]interface{} value of a nested field. -// Returns false if value is not found or is not a map[string]interface{}. -func nestedMapNoCopy(obj map[string]interface{}, fields ...string) (map[string]interface{}, bool) { - val, ok := nestedFieldNoCopy(obj, fields...) - if !ok { - return nil, false - } - m, ok := val.(map[string]interface{}) - return m, ok -} - -// SetNestedField sets the value of a nested field to a deep copy of the value provided. -// Returns false if value cannot be set because one of the nesting levels is not a map[string]interface{}. -func SetNestedField(obj map[string]interface{}, value interface{}, fields ...string) bool { - return setNestedFieldNoCopy(obj, runtime.DeepCopyJSONValue(value), fields...) -} - -func setNestedFieldNoCopy(obj map[string]interface{}, value interface{}, fields ...string) bool { - m := obj - for _, field := range fields[:len(fields)-1] { - if val, ok := m[field]; ok { - if valMap, ok := val.(map[string]interface{}); ok { - m = valMap - } else { - return false - } - } else { - newVal := make(map[string]interface{}) - m[field] = newVal - m = newVal - } - } - m[fields[len(fields)-1]] = value - return true -} - -// SetNestedStringSlice sets the string slice value of a nested field. -// Returns false if value cannot be set because one of the nesting levels is not a map[string]interface{}. -func SetNestedStringSlice(obj map[string]interface{}, value []string, fields ...string) bool { - m := make([]interface{}, 0, len(value)) // convert []string into []interface{} - for _, v := range value { - m = append(m, v) - } - return setNestedFieldNoCopy(obj, m, fields...) -} - -// SetNestedSlice sets the slice value of a nested field. -// Returns false if value cannot be set because one of the nesting levels is not a map[string]interface{}. -func SetNestedSlice(obj map[string]interface{}, value []interface{}, fields ...string) bool { - return SetNestedField(obj, value, fields...) -} - -// SetNestedStringMap sets the map[string]string value of a nested field. -// Returns false if value cannot be set because one of the nesting levels is not a map[string]interface{}. -func SetNestedStringMap(obj map[string]interface{}, value map[string]string, fields ...string) bool { - m := make(map[string]interface{}, len(value)) // convert map[string]string into map[string]interface{} - for k, v := range value { - m[k] = v - } - return setNestedFieldNoCopy(obj, m, fields...) -} - -// SetNestedMap sets the map[string]interface{} value of a nested field. -// Returns false if value cannot be set because one of the nesting levels is not a map[string]interface{}. -func SetNestedMap(obj map[string]interface{}, value map[string]interface{}, fields ...string) bool { - return SetNestedField(obj, value, fields...) -} - -// RemoveNestedField removes the nested field from the obj. -func RemoveNestedField(obj map[string]interface{}, fields ...string) { - m := obj - for _, field := range fields[:len(fields)-1] { - if x, ok := m[field].(map[string]interface{}); ok { - m = x - } else { - return - } - } - delete(m, fields[len(fields)-1]) -} - -func getNestedString(obj map[string]interface{}, fields ...string) string { - val, ok := NestedString(obj, fields...) - if !ok { - return "" - } - return val -} - -func extractOwnerReference(v map[string]interface{}) metav1.OwnerReference { - // though this field is a *bool, but when decoded from JSON, it's - // unmarshalled as bool. - var controllerPtr *bool - if controller, ok := NestedBool(v, "controller"); ok { - controllerPtr = &controller - } - var blockOwnerDeletionPtr *bool - if blockOwnerDeletion, ok := NestedBool(v, "blockOwnerDeletion"); ok { - blockOwnerDeletionPtr = &blockOwnerDeletion - } - return metav1.OwnerReference{ - Kind: getNestedString(v, "kind"), - Name: getNestedString(v, "name"), - APIVersion: getNestedString(v, "apiVersion"), - UID: types.UID(getNestedString(v, "uid")), - Controller: controllerPtr, - BlockOwnerDeletion: blockOwnerDeletionPtr, - } -} - -// UnstructuredJSONScheme is capable of converting JSON data into the Unstructured -// type, which can be used for generic access to objects without a predefined scheme. -// TODO: move into serializer/json. -var UnstructuredJSONScheme runtime.Codec = unstructuredJSONScheme{} - -type unstructuredJSONScheme struct{} - -func (s unstructuredJSONScheme) Decode(data []byte, _ *schema.GroupVersionKind, obj runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { - var err error - if obj != nil { - err = s.decodeInto(data, obj) - } else { - obj, err = s.decode(data) - } - - if err != nil { - return nil, nil, err - } - - gvk := obj.GetObjectKind().GroupVersionKind() - if len(gvk.Kind) == 0 { - return nil, &gvk, runtime.NewMissingKindErr(string(data)) - } - - return obj, &gvk, nil -} - -func (unstructuredJSONScheme) Encode(obj runtime.Object, w io.Writer) error { - switch t := obj.(type) { - case *Unstructured: - return json.NewEncoder(w).Encode(t.Object) - case *UnstructuredList: - items := make([]interface{}, 0, len(t.Items)) - for _, i := range t.Items { - items = append(items, i.Object) - } - listObj := make(map[string]interface{}, len(t.Object)+1) - for k, v := range t.Object { // Make a shallow copy - listObj[k] = v - } - listObj["items"] = items - return json.NewEncoder(w).Encode(listObj) - case *runtime.Unknown: - // TODO: Unstructured needs to deal with ContentType. - _, err := w.Write(t.Raw) - return err - default: - return json.NewEncoder(w).Encode(t) - } -} - -func (s unstructuredJSONScheme) decode(data []byte) (runtime.Object, error) { - type detector struct { - Items gojson.RawMessage - } - var det detector - if err := json.Unmarshal(data, &det); err != nil { - return nil, err - } - - if det.Items != nil { - list := &UnstructuredList{} - err := s.decodeToList(data, list) - return list, err - } - - // No Items field, so it wasn't a list. - unstruct := &Unstructured{} - err := s.decodeToUnstructured(data, unstruct) - return unstruct, err -} - -func (s unstructuredJSONScheme) decodeInto(data []byte, obj runtime.Object) error { - switch x := obj.(type) { - case *Unstructured: - return s.decodeToUnstructured(data, x) - case *UnstructuredList: - return s.decodeToList(data, x) - case *runtime.VersionedObjects: - o, err := s.decode(data) - if err == nil { - x.Objects = []runtime.Object{o} - } - return err - default: - return json.Unmarshal(data, x) - } -} - -func (unstructuredJSONScheme) decodeToUnstructured(data []byte, unstruct *Unstructured) error { - m := make(map[string]interface{}) - if err := json.Unmarshal(data, &m); err != nil { - return err - } - - unstruct.Object = m - - return nil -} - -func (s unstructuredJSONScheme) decodeToList(data []byte, list *UnstructuredList) error { - type decodeList struct { - Items []gojson.RawMessage - } - - var dList decodeList - if err := json.Unmarshal(data, &dList); err != nil { - return err - } - - if err := json.Unmarshal(data, &list.Object); err != nil { - return err - } - - // For typed lists, e.g., a PodList, API server doesn't set each item's - // APIVersion and Kind. We need to set it. - listAPIVersion := list.GetAPIVersion() - listKind := list.GetKind() - itemKind := strings.TrimSuffix(listKind, "List") - - delete(list.Object, "items") - list.Items = make([]Unstructured, 0, len(dList.Items)) - for _, i := range dList.Items { - unstruct := &Unstructured{} - if err := s.decodeToUnstructured([]byte(i), unstruct); err != nil { - return err - } - // This is hacky. Set the item's Kind and APIVersion to those inferred - // from the List. - if len(unstruct.GetKind()) == 0 && len(unstruct.GetAPIVersion()) == 0 { - unstruct.SetKind(itemKind) - unstruct.SetAPIVersion(listAPIVersion) - } - list.Items = append(list.Items, *unstruct) - } - return nil -} - -// UnstructuredObjectConverter is an ObjectConverter for use with -// Unstructured objects. Since it has no schema or type information, -// it will only succeed for no-op conversions. This is provided as a -// sane implementation for APIs that require an object converter. -type UnstructuredObjectConverter struct{} - -func (UnstructuredObjectConverter) Convert(in, out, context interface{}) error { - unstructIn, ok := in.(*Unstructured) - if !ok { - return fmt.Errorf("input type %T in not valid for unstructured conversion", in) - } - - unstructOut, ok := out.(*Unstructured) - if !ok { - return fmt.Errorf("output type %T in not valid for unstructured conversion", out) - } - - // maybe deep copy the map? It is documented in the - // ObjectConverter interface that this function is not - // guaranteed to not mutate the input. Or maybe set the input - // object to nil. - unstructOut.Object = unstructIn.Object - return nil -} - -func (UnstructuredObjectConverter) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) { - if kind := in.GetObjectKind().GroupVersionKind(); !kind.Empty() { - gvk, ok := target.KindForGroupVersionKinds([]schema.GroupVersionKind{kind}) - if !ok { - // TODO: should this be a typed error? - return nil, fmt.Errorf("%v is unstructured and is not suitable for converting to %q", kind, target) - } - in.GetObjectKind().SetGroupVersionKind(gvk) - } - return in, nil -} - -func (UnstructuredObjectConverter) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { - return "", "", errors.New("unstructured cannot convert field labels") -} diff --git a/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go b/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go index 36e769bd..7213b7a1 100644 --- a/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go +++ b/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go @@ -18,13 +18,20 @@ package unstructured import ( "bytes" + gojson "encoding/json" "errors" "fmt" + "io" + "strings" + + "github.com/golang/glog" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/conversion/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/json" utilruntime "k8s.io/apimachinery/pkg/util/runtime" ) @@ -47,31 +54,39 @@ type Unstructured struct { var _ metav1.Object = &Unstructured{} var _ runtime.Unstructured = &Unstructured{} +var _ runtime.Unstructured = &UnstructuredList{} + +func (obj *Unstructured) GetObjectKind() schema.ObjectKind { return obj } +func (obj *UnstructuredList) GetObjectKind() schema.ObjectKind { return obj } -func (obj *Unstructured) GetObjectKind() schema.ObjectKind { return obj } +func (obj *Unstructured) IsUnstructuredObject() {} +func (obj *UnstructuredList) IsUnstructuredObject() {} func (obj *Unstructured) IsList() bool { - field, ok := obj.Object["items"] - if !ok { - return false + if obj.Object != nil { + _, ok := obj.Object["items"] + return ok } - _, ok = field.([]interface{}) - return ok + return false } +func (obj *UnstructuredList) IsList() bool { return true } func (obj *Unstructured) EachListItem(fn func(runtime.Object) error) error { + if obj.Object == nil { + return fmt.Errorf("content is not a list") + } field, ok := obj.Object["items"] if !ok { - return errors.New("content is not a list") + return fmt.Errorf("content is not a list") } items, ok := field.([]interface{}) if !ok { - return fmt.Errorf("content is not a list: %T", field) + return nil } for _, item := range items { child, ok := item.(map[string]interface{}) if !ok { - return fmt.Errorf("items member is not an object: %T", child) + return fmt.Errorf("items member is not an object") } if err := fn(&Unstructured{Object: child}); err != nil { return err @@ -80,6 +95,15 @@ func (obj *Unstructured) EachListItem(fn func(runtime.Object) error) error { return nil } +func (obj *UnstructuredList) EachListItem(fn func(runtime.Object) error) error { + for i := range obj.Items { + if err := fn(&obj.Items[i]); err != nil { + return err + } + } + return nil +} + func (obj *Unstructured) UnstructuredContent() map[string]interface{} { if obj.Object == nil { obj.Object = make(map[string]interface{}) @@ -87,8 +111,23 @@ func (obj *Unstructured) UnstructuredContent() map[string]interface{} { return obj.Object } -func (obj *Unstructured) SetUnstructuredContent(content map[string]interface{}) { - obj.Object = content +// UnstructuredContent returns a map contain an overlay of the Items field onto +// the Object field. Items always overwrites overlay. Changing "items" in the +// returned object will affect items in the underlying Items field, but changing +// the "items" slice itself will have no effect. +// TODO: expose SetUnstructuredContent on runtime.Unstructured that allows +// items to be changed. +func (obj *UnstructuredList) UnstructuredContent() map[string]interface{} { + out := obj.Object + if out == nil { + out = make(map[string]interface{}) + } + items := make([]interface{}, len(obj.Items)) + for i, item := range obj.Items { + items[i] = item.Object + } + out["items"] = items + return out } // MarshalJSON ensures that the unstructured object produces proper @@ -112,61 +151,227 @@ func (in *Unstructured) DeepCopy() *Unstructured { } out := new(Unstructured) *out = *in - out.Object = runtime.DeepCopyJSON(in.Object) + out.Object = unstructured.DeepCopyJSON(in.Object) + return out +} + +func (in *UnstructuredList) DeepCopy() *UnstructuredList { + if in == nil { + return nil + } + out := new(UnstructuredList) + *out = *in + out.Object = unstructured.DeepCopyJSON(in.Object) + out.Items = make([]Unstructured, len(in.Items)) + for i := range in.Items { + in.Items[i].DeepCopyInto(&out.Items[i]) + } return out } +func getNestedField(obj map[string]interface{}, fields ...string) interface{} { + var val interface{} = obj + for _, field := range fields { + if _, ok := val.(map[string]interface{}); !ok { + return nil + } + val = val.(map[string]interface{})[field] + } + return val +} + +func getNestedString(obj map[string]interface{}, fields ...string) string { + if str, ok := getNestedField(obj, fields...).(string); ok { + return str + } + return "" +} + +func getNestedInt64(obj map[string]interface{}, fields ...string) int64 { + if str, ok := getNestedField(obj, fields...).(int64); ok { + return str + } + return 0 +} + +func getNestedInt64Pointer(obj map[string]interface{}, fields ...string) *int64 { + nested := getNestedField(obj, fields...) + switch n := nested.(type) { + case int64: + return &n + case *int64: + return n + default: + return nil + } +} + +func getNestedSlice(obj map[string]interface{}, fields ...string) []string { + if m, ok := getNestedField(obj, fields...).([]interface{}); ok { + strSlice := make([]string, 0, len(m)) + for _, v := range m { + if str, ok := v.(string); ok { + strSlice = append(strSlice, str) + } + } + return strSlice + } + return nil +} + +func getNestedMap(obj map[string]interface{}, fields ...string) map[string]string { + if m, ok := getNestedField(obj, fields...).(map[string]interface{}); ok { + strMap := make(map[string]string, len(m)) + for k, v := range m { + if str, ok := v.(string); ok { + strMap[k] = str + } + } + return strMap + } + return nil +} + +func setNestedField(obj map[string]interface{}, value interface{}, fields ...string) { + m := obj + if len(fields) > 1 { + for _, field := range fields[0 : len(fields)-1] { + if _, ok := m[field].(map[string]interface{}); !ok { + m[field] = make(map[string]interface{}) + } + m = m[field].(map[string]interface{}) + } + } + m[fields[len(fields)-1]] = value +} + +func setNestedSlice(obj map[string]interface{}, value []string, fields ...string) { + m := make([]interface{}, 0, len(value)) + for _, v := range value { + m = append(m, v) + } + setNestedField(obj, m, fields...) +} + +func setNestedMap(obj map[string]interface{}, value map[string]string, fields ...string) { + m := make(map[string]interface{}, len(value)) + for k, v := range value { + m[k] = v + } + setNestedField(obj, m, fields...) +} + func (u *Unstructured) setNestedField(value interface{}, fields ...string) { if u.Object == nil { u.Object = make(map[string]interface{}) } - SetNestedField(u.Object, value, fields...) + setNestedField(u.Object, value, fields...) } func (u *Unstructured) setNestedSlice(value []string, fields ...string) { if u.Object == nil { u.Object = make(map[string]interface{}) } - SetNestedStringSlice(u.Object, value, fields...) + setNestedSlice(u.Object, value, fields...) } func (u *Unstructured) setNestedMap(value map[string]string, fields ...string) { if u.Object == nil { u.Object = make(map[string]interface{}) } - SetNestedStringMap(u.Object, value, fields...) + setNestedMap(u.Object, value, fields...) } -func (u *Unstructured) GetOwnerReferences() []metav1.OwnerReference { - field, ok := nestedFieldNoCopy(u.Object, "metadata", "ownerReferences") +func extractOwnerReference(src interface{}) metav1.OwnerReference { + v := src.(map[string]interface{}) + // though this field is a *bool, but when decoded from JSON, it's + // unmarshalled as bool. + var controllerPtr *bool + controller, ok := (getNestedField(v, "controller")).(bool) if !ok { - return nil + controllerPtr = nil + } else { + controllerCopy := controller + controllerPtr = &controllerCopy } - original, ok := field.([]interface{}) + var blockOwnerDeletionPtr *bool + blockOwnerDeletion, ok := (getNestedField(v, "blockOwnerDeletion")).(bool) if !ok { - return nil + blockOwnerDeletionPtr = nil + } else { + blockOwnerDeletionCopy := blockOwnerDeletion + blockOwnerDeletionPtr = &blockOwnerDeletionCopy } - ret := make([]metav1.OwnerReference, 0, len(original)) - for _, obj := range original { - o, ok := obj.(map[string]interface{}) + return metav1.OwnerReference{ + Kind: getNestedString(v, "kind"), + Name: getNestedString(v, "name"), + APIVersion: getNestedString(v, "apiVersion"), + UID: (types.UID)(getNestedString(v, "uid")), + Controller: controllerPtr, + BlockOwnerDeletion: blockOwnerDeletionPtr, + } +} + +func setOwnerReference(src metav1.OwnerReference) map[string]interface{} { + ret := make(map[string]interface{}) + setNestedField(ret, src.Kind, "kind") + setNestedField(ret, src.Name, "name") + setNestedField(ret, src.APIVersion, "apiVersion") + setNestedField(ret, string(src.UID), "uid") + // json.Unmarshal() extracts boolean json fields as bool, not as *bool and hence extractOwnerReference() + // expects bool or a missing field, not *bool. So if pointer is nil, fields are omitted from the ret object. + // If pointer is non-nil, they are set to the referenced value. + if src.Controller != nil { + setNestedField(ret, *src.Controller, "controller") + } + if src.BlockOwnerDeletion != nil { + setNestedField(ret, *src.BlockOwnerDeletion, "blockOwnerDeletion") + } + return ret +} + +func getOwnerReferences(object map[string]interface{}) ([]map[string]interface{}, error) { + field := getNestedField(object, "metadata", "ownerReferences") + if field == nil { + return nil, fmt.Errorf("cannot find field metadata.ownerReferences in %v", object) + } + ownerReferences, ok := field.([]map[string]interface{}) + if ok { + return ownerReferences, nil + } + // TODO: This is hacky... + interfaces, ok := field.([]interface{}) + if !ok { + return nil, fmt.Errorf("expect metadata.ownerReferences to be a slice in %#v", object) + } + ownerReferences = make([]map[string]interface{}, 0, len(interfaces)) + for i := 0; i < len(interfaces); i++ { + r, ok := interfaces[i].(map[string]interface{}) if !ok { - // expected map[string]interface{}, got something else - return nil + return nil, fmt.Errorf("expect element metadata.ownerReferences to be a map[string]interface{} in %#v", object) } - ret = append(ret, extractOwnerReference(o)) + ownerReferences = append(ownerReferences, r) + } + return ownerReferences, nil +} + +func (u *Unstructured) GetOwnerReferences() []metav1.OwnerReference { + original, err := getOwnerReferences(u.Object) + if err != nil { + glog.V(6).Info(err) + return nil + } + ret := make([]metav1.OwnerReference, 0, len(original)) + for i := 0; i < len(original); i++ { + ret = append(ret, extractOwnerReference(original[i])) } return ret } func (u *Unstructured) SetOwnerReferences(references []metav1.OwnerReference) { - newReferences := make([]interface{}, 0, len(references)) - for _, reference := range references { - out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&reference) - if err != nil { - utilruntime.HandleError(fmt.Errorf("unable to convert Owner Reference: %v", err)) - continue - } - newReferences = append(newReferences, out) + var newReferences = make([]map[string]interface{}, 0, len(references)) + for i := 0; i < len(references); i++ { + newReferences = append(newReferences, setOwnerReference(references[i])) } u.setNestedField(newReferences, "metadata", "ownerReferences") } @@ -228,11 +433,7 @@ func (u *Unstructured) SetResourceVersion(version string) { } func (u *Unstructured) GetGeneration() int64 { - val, ok := NestedInt64(u.Object, "metadata", "generation") - if !ok { - return 0 - } - return val + return getNestedInt64(u.Object, "metadata", "generation") } func (u *Unstructured) SetGeneration(generation int64) { @@ -263,10 +464,6 @@ func (u *Unstructured) GetCreationTimestamp() metav1.Time { func (u *Unstructured) SetCreationTimestamp(timestamp metav1.Time) { ts, _ := timestamp.MarshalQueryParameter() - if len(ts) == 0 || timestamp.Time.IsZero() { - RemoveNestedField(u.Object, "metadata", "creationTimestamp") - return - } u.setNestedField(ts, "metadata", "creationTimestamp") } @@ -281,7 +478,7 @@ func (u *Unstructured) GetDeletionTimestamp() *metav1.Time { func (u *Unstructured) SetDeletionTimestamp(timestamp *metav1.Time) { if timestamp == nil { - RemoveNestedField(u.Object, "metadata", "deletionTimestamp") + u.setNestedField(nil, "metadata", "deletionTimestamp") return } ts, _ := timestamp.MarshalQueryParameter() @@ -289,24 +486,15 @@ func (u *Unstructured) SetDeletionTimestamp(timestamp *metav1.Time) { } func (u *Unstructured) GetDeletionGracePeriodSeconds() *int64 { - val, ok := NestedInt64(u.Object, "metadata", "deletionGracePeriodSeconds") - if !ok { - return nil - } - return &val + return getNestedInt64Pointer(u.Object, "metadata", "deletionGracePeriodSeconds") } func (u *Unstructured) SetDeletionGracePeriodSeconds(deletionGracePeriodSeconds *int64) { - if deletionGracePeriodSeconds == nil { - RemoveNestedField(u.Object, "metadata", "deletionGracePeriodSeconds") - return - } - u.setNestedField(*deletionGracePeriodSeconds, "metadata", "deletionGracePeriodSeconds") + u.setNestedField(deletionGracePeriodSeconds, "metadata", "deletionGracePeriodSeconds") } func (u *Unstructured) GetLabels() map[string]string { - m, _ := NestedStringMap(u.Object, "metadata", "labels") - return m + return getNestedMap(u.Object, "metadata", "labels") } func (u *Unstructured) SetLabels(labels map[string]string) { @@ -314,8 +502,7 @@ func (u *Unstructured) SetLabels(labels map[string]string) { } func (u *Unstructured) GetAnnotations() map[string]string { - m, _ := NestedStringMap(u.Object, "metadata", "annotations") - return m + return getNestedMap(u.Object, "metadata", "annotations") } func (u *Unstructured) SetAnnotations(annotations map[string]string) { @@ -336,34 +523,41 @@ func (u *Unstructured) GroupVersionKind() schema.GroupVersionKind { return gvk } +var converter = unstructured.NewConverter(false) + func (u *Unstructured) GetInitializers() *metav1.Initializers { - m, ok := nestedMapNoCopy(u.Object, "metadata", "initializers") + field := getNestedField(u.Object, "metadata", "initializers") + if field == nil { + return nil + } + obj, ok := field.(map[string]interface{}) if !ok { return nil } out := &metav1.Initializers{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(m, out); err != nil { + if err := converter.FromUnstructured(obj, out); err != nil { utilruntime.HandleError(fmt.Errorf("unable to retrieve initializers for object: %v", err)) - return nil } return out } func (u *Unstructured) SetInitializers(initializers *metav1.Initializers) { + if u.Object == nil { + u.Object = make(map[string]interface{}) + } if initializers == nil { - RemoveNestedField(u.Object, "metadata", "initializers") + setNestedField(u.Object, nil, "metadata", "initializers") return } - out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(initializers) + out, err := converter.ToUnstructured(initializers) if err != nil { utilruntime.HandleError(fmt.Errorf("unable to retrieve initializers for object: %v", err)) } - u.setNestedField(out, "metadata", "initializers") + setNestedField(u.Object, out, "metadata", "initializers") } func (u *Unstructured) GetFinalizers() []string { - val, _ := NestedStringSlice(u.Object, "metadata", "finalizers") - return val + return getNestedSlice(u.Object, "metadata", "finalizers") } func (u *Unstructured) SetFinalizers(finalizers []string) { @@ -377,3 +571,272 @@ func (u *Unstructured) GetClusterName() string { func (u *Unstructured) SetClusterName(clusterName string) { u.setNestedField(clusterName, "metadata", "clusterName") } + +// UnstructuredList allows lists that do not have Golang structs +// registered to be manipulated generically. This can be used to deal +// with the API lists from a plug-in. +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:deepcopy-gen=true +type UnstructuredList struct { + Object map[string]interface{} + + // Items is a list of unstructured objects. + Items []Unstructured `json:"items"` +} + +var _ metav1.ListInterface = &UnstructuredList{} + +// MarshalJSON ensures that the unstructured list object produces proper +// JSON when passed to Go's standard JSON library. +func (u *UnstructuredList) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + err := UnstructuredJSONScheme.Encode(u, &buf) + return buf.Bytes(), err +} + +// UnmarshalJSON ensures that the unstructured list object properly +// decodes JSON when passed to Go's standard JSON library. +func (u *UnstructuredList) UnmarshalJSON(b []byte) error { + _, _, err := UnstructuredJSONScheme.Decode(b, nil, u) + return err +} + +func (u *UnstructuredList) setNestedField(value interface{}, fields ...string) { + if u.Object == nil { + u.Object = make(map[string]interface{}) + } + setNestedField(u.Object, value, fields...) +} + +func (u *UnstructuredList) GetAPIVersion() string { + return getNestedString(u.Object, "apiVersion") +} + +func (u *UnstructuredList) SetAPIVersion(version string) { + u.setNestedField(version, "apiVersion") +} + +func (u *UnstructuredList) GetKind() string { + return getNestedString(u.Object, "kind") +} + +func (u *UnstructuredList) SetKind(kind string) { + u.setNestedField(kind, "kind") +} + +func (u *UnstructuredList) GetResourceVersion() string { + return getNestedString(u.Object, "metadata", "resourceVersion") +} + +func (u *UnstructuredList) SetResourceVersion(version string) { + u.setNestedField(version, "metadata", "resourceVersion") +} + +func (u *UnstructuredList) GetSelfLink() string { + return getNestedString(u.Object, "metadata", "selfLink") +} + +func (u *UnstructuredList) SetSelfLink(selfLink string) { + u.setNestedField(selfLink, "metadata", "selfLink") +} + +func (u *UnstructuredList) GetContinue() string { + return getNestedString(u.Object, "metadata", "continue") +} + +func (u *UnstructuredList) SetContinue(c string) { + u.setNestedField(c, "metadata", "continue") +} + +func (u *UnstructuredList) SetGroupVersionKind(gvk schema.GroupVersionKind) { + u.SetAPIVersion(gvk.GroupVersion().String()) + u.SetKind(gvk.Kind) +} + +func (u *UnstructuredList) GroupVersionKind() schema.GroupVersionKind { + gv, err := schema.ParseGroupVersion(u.GetAPIVersion()) + if err != nil { + return schema.GroupVersionKind{} + } + gvk := gv.WithKind(u.GetKind()) + return gvk +} + +// UnstructuredJSONScheme is capable of converting JSON data into the Unstructured +// type, which can be used for generic access to objects without a predefined scheme. +// TODO: move into serializer/json. +var UnstructuredJSONScheme runtime.Codec = unstructuredJSONScheme{} + +type unstructuredJSONScheme struct{} + +func (s unstructuredJSONScheme) Decode(data []byte, _ *schema.GroupVersionKind, obj runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { + var err error + if obj != nil { + err = s.decodeInto(data, obj) + } else { + obj, err = s.decode(data) + } + + if err != nil { + return nil, nil, err + } + + gvk := obj.GetObjectKind().GroupVersionKind() + if len(gvk.Kind) == 0 { + return nil, &gvk, runtime.NewMissingKindErr(string(data)) + } + + return obj, &gvk, nil +} + +func (unstructuredJSONScheme) Encode(obj runtime.Object, w io.Writer) error { + switch t := obj.(type) { + case *Unstructured: + return json.NewEncoder(w).Encode(t.Object) + case *UnstructuredList: + items := make([]map[string]interface{}, 0, len(t.Items)) + for _, i := range t.Items { + items = append(items, i.Object) + } + listObj := make(map[string]interface{}, len(t.Object)+1) + for k, v := range t.Object { // Make a shallow copy + listObj[k] = v + } + listObj["items"] = items + return json.NewEncoder(w).Encode(listObj) + case *runtime.Unknown: + // TODO: Unstructured needs to deal with ContentType. + _, err := w.Write(t.Raw) + return err + default: + return json.NewEncoder(w).Encode(t) + } +} + +func (s unstructuredJSONScheme) decode(data []byte) (runtime.Object, error) { + type detector struct { + Items gojson.RawMessage + } + var det detector + if err := json.Unmarshal(data, &det); err != nil { + return nil, err + } + + if det.Items != nil { + list := &UnstructuredList{} + err := s.decodeToList(data, list) + return list, err + } + + // No Items field, so it wasn't a list. + unstruct := &Unstructured{} + err := s.decodeToUnstructured(data, unstruct) + return unstruct, err +} + +func (s unstructuredJSONScheme) decodeInto(data []byte, obj runtime.Object) error { + switch x := obj.(type) { + case *Unstructured: + return s.decodeToUnstructured(data, x) + case *UnstructuredList: + return s.decodeToList(data, x) + case *runtime.VersionedObjects: + o, err := s.decode(data) + if err == nil { + x.Objects = []runtime.Object{o} + } + return err + default: + return json.Unmarshal(data, x) + } +} + +func (unstructuredJSONScheme) decodeToUnstructured(data []byte, unstruct *Unstructured) error { + m := make(map[string]interface{}) + if err := json.Unmarshal(data, &m); err != nil { + return err + } + + unstruct.Object = m + + return nil +} + +func (s unstructuredJSONScheme) decodeToList(data []byte, list *UnstructuredList) error { + type decodeList struct { + Items []gojson.RawMessage + } + + var dList decodeList + if err := json.Unmarshal(data, &dList); err != nil { + return err + } + + if err := json.Unmarshal(data, &list.Object); err != nil { + return err + } + + // For typed lists, e.g., a PodList, API server doesn't set each item's + // APIVersion and Kind. We need to set it. + listAPIVersion := list.GetAPIVersion() + listKind := list.GetKind() + itemKind := strings.TrimSuffix(listKind, "List") + + delete(list.Object, "items") + list.Items = nil + for _, i := range dList.Items { + unstruct := &Unstructured{} + if err := s.decodeToUnstructured([]byte(i), unstruct); err != nil { + return err + } + // This is hacky. Set the item's Kind and APIVersion to those inferred + // from the List. + if len(unstruct.GetKind()) == 0 && len(unstruct.GetAPIVersion()) == 0 { + unstruct.SetKind(itemKind) + unstruct.SetAPIVersion(listAPIVersion) + } + list.Items = append(list.Items, *unstruct) + } + return nil +} + +// UnstructuredObjectConverter is an ObjectConverter for use with +// Unstructured objects. Since it has no schema or type information, +// it will only succeed for no-op conversions. This is provided as a +// sane implementation for APIs that require an object converter. +type UnstructuredObjectConverter struct{} + +func (UnstructuredObjectConverter) Convert(in, out, context interface{}) error { + unstructIn, ok := in.(*Unstructured) + if !ok { + return fmt.Errorf("input type %T in not valid for unstructured conversion", in) + } + + unstructOut, ok := out.(*Unstructured) + if !ok { + return fmt.Errorf("output type %T in not valid for unstructured conversion", out) + } + + // maybe deep copy the map? It is documented in the + // ObjectConverter interface that this function is not + // guaranteeed to not mutate the input. Or maybe set the input + // object to nil. + unstructOut.Object = unstructIn.Object + return nil +} + +func (UnstructuredObjectConverter) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) { + if kind := in.GetObjectKind().GroupVersionKind(); !kind.Empty() { + gvk, ok := target.KindForGroupVersionKinds([]schema.GroupVersionKind{kind}) + if !ok { + // TODO: should this be a typed error? + return nil, fmt.Errorf("%v is unstructured and is not suitable for converting to %q", kind, target) + } + in.GetObjectKind().SetGroupVersionKind(gvk) + } + return in, nil +} + +func (UnstructuredObjectConverter) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { + return "", "", errors.New("unstructured cannot convert field labels") +} diff --git a/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_list.go b/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_list.go deleted file mode 100644 index 57d78a09..00000000 --- a/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured_list.go +++ /dev/null @@ -1,189 +0,0 @@ -/* -Copyright 2015 The Kubernetes 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 unstructured - -import ( - "bytes" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -var _ runtime.Unstructured = &UnstructuredList{} -var _ metav1.ListInterface = &UnstructuredList{} - -// UnstructuredList allows lists that do not have Golang structs -// registered to be manipulated generically. This can be used to deal -// with the API lists from a plug-in. -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// +k8s:deepcopy-gen=true -type UnstructuredList struct { - Object map[string]interface{} - - // Items is a list of unstructured objects. - Items []Unstructured `json:"items"` -} - -func (u *UnstructuredList) GetObjectKind() schema.ObjectKind { return u } - -func (u *UnstructuredList) IsList() bool { return true } - -func (u *UnstructuredList) EachListItem(fn func(runtime.Object) error) error { - for i := range u.Items { - if err := fn(&u.Items[i]); err != nil { - return err - } - } - return nil -} - -// UnstructuredContent returns a map contain an overlay of the Items field onto -// the Object field. Items always overwrites overlay. Changing "items" in the -// returned object will affect items in the underlying Items field, but changing -// the "items" slice itself will have no effect. -// TODO: expose SetUnstructuredContent on runtime.Unstructured that allows -// items to be changed. -func (u *UnstructuredList) UnstructuredContent() map[string]interface{} { - out := u.Object - if out == nil { - out = make(map[string]interface{}) - } - items := make([]interface{}, len(u.Items)) - for i, item := range u.Items { - items[i] = item.Object - } - out["items"] = items - return out -} - -// SetUnstructuredContent obeys the conventions of List and keeps Items and the items -// array in sync. If items is not an array of objects in the incoming map, then any -// mismatched item will be removed. -func (obj *UnstructuredList) SetUnstructuredContent(content map[string]interface{}) { - obj.Object = content - if content == nil { - obj.Items = nil - return - } - items, ok := obj.Object["items"].([]interface{}) - if !ok || items == nil { - items = []interface{}{} - } - unstructuredItems := make([]Unstructured, 0, len(items)) - newItems := make([]interface{}, 0, len(items)) - for _, item := range items { - o, ok := item.(map[string]interface{}) - if !ok { - continue - } - unstructuredItems = append(unstructuredItems, Unstructured{Object: o}) - newItems = append(newItems, o) - } - obj.Items = unstructuredItems - obj.Object["items"] = newItems -} - -func (u *UnstructuredList) DeepCopy() *UnstructuredList { - if u == nil { - return nil - } - out := new(UnstructuredList) - *out = *u - out.Object = runtime.DeepCopyJSON(u.Object) - out.Items = make([]Unstructured, len(u.Items)) - for i := range u.Items { - u.Items[i].DeepCopyInto(&out.Items[i]) - } - return out -} - -// MarshalJSON ensures that the unstructured list object produces proper -// JSON when passed to Go's standard JSON library. -func (u *UnstructuredList) MarshalJSON() ([]byte, error) { - var buf bytes.Buffer - err := UnstructuredJSONScheme.Encode(u, &buf) - return buf.Bytes(), err -} - -// UnmarshalJSON ensures that the unstructured list object properly -// decodes JSON when passed to Go's standard JSON library. -func (u *UnstructuredList) UnmarshalJSON(b []byte) error { - _, _, err := UnstructuredJSONScheme.Decode(b, nil, u) - return err -} - -func (u *UnstructuredList) GetAPIVersion() string { - return getNestedString(u.Object, "apiVersion") -} - -func (u *UnstructuredList) SetAPIVersion(version string) { - u.setNestedField(version, "apiVersion") -} - -func (u *UnstructuredList) GetKind() string { - return getNestedString(u.Object, "kind") -} - -func (u *UnstructuredList) SetKind(kind string) { - u.setNestedField(kind, "kind") -} - -func (u *UnstructuredList) GetResourceVersion() string { - return getNestedString(u.Object, "metadata", "resourceVersion") -} - -func (u *UnstructuredList) SetResourceVersion(version string) { - u.setNestedField(version, "metadata", "resourceVersion") -} - -func (u *UnstructuredList) GetSelfLink() string { - return getNestedString(u.Object, "metadata", "selfLink") -} - -func (u *UnstructuredList) SetSelfLink(selfLink string) { - u.setNestedField(selfLink, "metadata", "selfLink") -} - -func (u *UnstructuredList) GetContinue() string { - return getNestedString(u.Object, "metadata", "continue") -} - -func (u *UnstructuredList) SetContinue(c string) { - u.setNestedField(c, "metadata", "continue") -} - -func (u *UnstructuredList) SetGroupVersionKind(gvk schema.GroupVersionKind) { - u.SetAPIVersion(gvk.GroupVersion().String()) - u.SetKind(gvk.Kind) -} - -func (u *UnstructuredList) GroupVersionKind() schema.GroupVersionKind { - gv, err := schema.ParseGroupVersion(u.GetAPIVersion()) - if err != nil { - return schema.GroupVersionKind{} - } - gvk := gv.WithKind(u.GetKind()) - return gvk -} - -func (u *UnstructuredList) setNestedField(value interface{}, fields ...string) { - if u.Object == nil { - u.Object = make(map[string]interface{}) - } - SetNestedField(u.Object, value, fields...) -} diff --git a/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/zz_generated.deepcopy.go b/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/zz_generated.deepcopy.go index e3bae45e..248acf98 100644 --- a/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/zz_generated.deepcopy.go +++ b/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -21,9 +21,27 @@ limitations under the License. package unstructured import ( + conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" + reflect "reflect" ) +// GetGeneratedDeepCopyFuncs returns the generated funcs, since we aren't registering them. +// +// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented. +func GetGeneratedDeepCopyFuncs() []conversion.GeneratedDeepCopyFunc { + return []conversion.GeneratedDeepCopyFunc{ + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*Unstructured).DeepCopyInto(out.(*Unstructured)) + return nil + }, InType: reflect.TypeOf(&Unstructured{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*UnstructuredList).DeepCopyInto(out.(*UnstructuredList)) + return nil + }, InType: reflect.TypeOf(&UnstructuredList{})}, + } +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Unstructured) DeepCopyInto(out *Unstructured) { clone := in.DeepCopy() diff --git a/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.deepcopy.go b/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.deepcopy.go index 2aa20902..c73e777b 100644 --- a/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.deepcopy.go +++ b/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -21,10 +21,164 @@ limitations under the License. package v1 import ( + conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" types "k8s.io/apimachinery/pkg/types" + reflect "reflect" ) +// GetGeneratedDeepCopyFuncs returns the generated funcs, since we aren't registering them. +// +// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented. +func GetGeneratedDeepCopyFuncs() []conversion.GeneratedDeepCopyFunc { + return []conversion.GeneratedDeepCopyFunc{ + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*APIGroup).DeepCopyInto(out.(*APIGroup)) + return nil + }, InType: reflect.TypeOf(&APIGroup{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*APIGroupList).DeepCopyInto(out.(*APIGroupList)) + return nil + }, InType: reflect.TypeOf(&APIGroupList{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*APIResource).DeepCopyInto(out.(*APIResource)) + return nil + }, InType: reflect.TypeOf(&APIResource{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*APIResourceList).DeepCopyInto(out.(*APIResourceList)) + return nil + }, InType: reflect.TypeOf(&APIResourceList{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*APIVersions).DeepCopyInto(out.(*APIVersions)) + return nil + }, InType: reflect.TypeOf(&APIVersions{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*DeleteOptions).DeepCopyInto(out.(*DeleteOptions)) + return nil + }, InType: reflect.TypeOf(&DeleteOptions{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*Duration).DeepCopyInto(out.(*Duration)) + return nil + }, InType: reflect.TypeOf(&Duration{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*ExportOptions).DeepCopyInto(out.(*ExportOptions)) + return nil + }, InType: reflect.TypeOf(&ExportOptions{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*GetOptions).DeepCopyInto(out.(*GetOptions)) + return nil + }, InType: reflect.TypeOf(&GetOptions{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*GroupKind).DeepCopyInto(out.(*GroupKind)) + return nil + }, InType: reflect.TypeOf(&GroupKind{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*GroupResource).DeepCopyInto(out.(*GroupResource)) + return nil + }, InType: reflect.TypeOf(&GroupResource{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*GroupVersion).DeepCopyInto(out.(*GroupVersion)) + return nil + }, InType: reflect.TypeOf(&GroupVersion{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*GroupVersionForDiscovery).DeepCopyInto(out.(*GroupVersionForDiscovery)) + return nil + }, InType: reflect.TypeOf(&GroupVersionForDiscovery{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*GroupVersionKind).DeepCopyInto(out.(*GroupVersionKind)) + return nil + }, InType: reflect.TypeOf(&GroupVersionKind{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*GroupVersionResource).DeepCopyInto(out.(*GroupVersionResource)) + return nil + }, InType: reflect.TypeOf(&GroupVersionResource{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*Initializer).DeepCopyInto(out.(*Initializer)) + return nil + }, InType: reflect.TypeOf(&Initializer{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*Initializers).DeepCopyInto(out.(*Initializers)) + return nil + }, InType: reflect.TypeOf(&Initializers{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*InternalEvent).DeepCopyInto(out.(*InternalEvent)) + return nil + }, InType: reflect.TypeOf(&InternalEvent{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*LabelSelector).DeepCopyInto(out.(*LabelSelector)) + return nil + }, InType: reflect.TypeOf(&LabelSelector{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*LabelSelectorRequirement).DeepCopyInto(out.(*LabelSelectorRequirement)) + return nil + }, InType: reflect.TypeOf(&LabelSelectorRequirement{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*List).DeepCopyInto(out.(*List)) + return nil + }, InType: reflect.TypeOf(&List{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*ListMeta).DeepCopyInto(out.(*ListMeta)) + return nil + }, InType: reflect.TypeOf(&ListMeta{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*ListOptions).DeepCopyInto(out.(*ListOptions)) + return nil + }, InType: reflect.TypeOf(&ListOptions{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*MicroTime).DeepCopyInto(out.(*MicroTime)) + return nil + }, InType: reflect.TypeOf(&MicroTime{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*ObjectMeta).DeepCopyInto(out.(*ObjectMeta)) + return nil + }, InType: reflect.TypeOf(&ObjectMeta{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*OwnerReference).DeepCopyInto(out.(*OwnerReference)) + return nil + }, InType: reflect.TypeOf(&OwnerReference{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*Patch).DeepCopyInto(out.(*Patch)) + return nil + }, InType: reflect.TypeOf(&Patch{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*Preconditions).DeepCopyInto(out.(*Preconditions)) + return nil + }, InType: reflect.TypeOf(&Preconditions{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*RootPaths).DeepCopyInto(out.(*RootPaths)) + return nil + }, InType: reflect.TypeOf(&RootPaths{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*ServerAddressByClientCIDR).DeepCopyInto(out.(*ServerAddressByClientCIDR)) + return nil + }, InType: reflect.TypeOf(&ServerAddressByClientCIDR{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*Status).DeepCopyInto(out.(*Status)) + return nil + }, InType: reflect.TypeOf(&Status{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*StatusCause).DeepCopyInto(out.(*StatusCause)) + return nil + }, InType: reflect.TypeOf(&StatusCause{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*StatusDetails).DeepCopyInto(out.(*StatusDetails)) + return nil + }, InType: reflect.TypeOf(&StatusDetails{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*Time).DeepCopyInto(out.(*Time)) + return nil + }, InType: reflect.TypeOf(&Time{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*Timestamp).DeepCopyInto(out.(*Timestamp)) + return nil + }, InType: reflect.TypeOf(&Timestamp{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*WatchEvent).DeepCopyInto(out.(*WatchEvent)) + return nil + }, InType: reflect.TypeOf(&WatchEvent{})}, + } +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *APIGroup) DeepCopyInto(out *APIGroup) { *out = *in diff --git a/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.defaults.go b/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.defaults.go index 88d7af08..6df448eb 100644 --- a/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.defaults.go +++ b/k8s.io/apimachinery/pkg/apis/meta/v1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/k8s.io/apimachinery/pkg/apis/meta/v1alpha1/generated.pb.go b/k8s.io/apimachinery/pkg/apis/meta/v1alpha1/generated.pb.go index 4fcddb3a..2d43bf94 100644 --- a/k8s.io/apimachinery/pkg/apis/meta/v1alpha1/generated.pb.go +++ b/k8s.io/apimachinery/pkg/apis/meta/v1alpha1/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/k8s.io/apimachinery/pkg/apis/meta/v1alpha1/zz_generated.deepcopy.go b/k8s.io/apimachinery/pkg/apis/meta/v1alpha1/zz_generated.deepcopy.go index 1b317200..043456cd 100644 --- a/k8s.io/apimachinery/pkg/apis/meta/v1alpha1/zz_generated.deepcopy.go +++ b/k8s.io/apimachinery/pkg/apis/meta/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -21,9 +21,47 @@ limitations under the License. package v1alpha1 import ( + conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" + reflect "reflect" ) +// GetGeneratedDeepCopyFuncs returns the generated funcs, since we aren't registering them. +// +// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented. +func GetGeneratedDeepCopyFuncs() []conversion.GeneratedDeepCopyFunc { + return []conversion.GeneratedDeepCopyFunc{ + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*PartialObjectMetadata).DeepCopyInto(out.(*PartialObjectMetadata)) + return nil + }, InType: reflect.TypeOf(&PartialObjectMetadata{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*PartialObjectMetadataList).DeepCopyInto(out.(*PartialObjectMetadataList)) + return nil + }, InType: reflect.TypeOf(&PartialObjectMetadataList{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*Table).DeepCopyInto(out.(*Table)) + return nil + }, InType: reflect.TypeOf(&Table{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*TableColumnDefinition).DeepCopyInto(out.(*TableColumnDefinition)) + return nil + }, InType: reflect.TypeOf(&TableColumnDefinition{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*TableOptions).DeepCopyInto(out.(*TableOptions)) + return nil + }, InType: reflect.TypeOf(&TableOptions{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*TableRow).DeepCopyInto(out.(*TableRow)) + return nil + }, InType: reflect.TypeOf(&TableRow{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*TableRowCondition).DeepCopyInto(out.(*TableRowCondition)) + return nil + }, InType: reflect.TypeOf(&TableRowCondition{})}, + } +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PartialObjectMetadata) DeepCopyInto(out *PartialObjectMetadata) { *out = *in diff --git a/k8s.io/apimachinery/pkg/apis/meta/v1alpha1/zz_generated.defaults.go b/k8s.io/apimachinery/pkg/apis/meta/v1alpha1/zz_generated.defaults.go index 5e24d22c..7e6df29d 100644 --- a/k8s.io/apimachinery/pkg/apis/meta/v1alpha1/zz_generated.defaults.go +++ b/k8s.io/apimachinery/pkg/apis/meta/v1alpha1/zz_generated.defaults.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/k8s.io/apimachinery/pkg/conversion/cloner.go b/k8s.io/apimachinery/pkg/conversion/cloner.go new file mode 100644 index 00000000..c5dec1f3 --- /dev/null +++ b/k8s.io/apimachinery/pkg/conversion/cloner.go @@ -0,0 +1,249 @@ +/* +Copyright 2014 The Kubernetes 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 conversion + +import ( + "fmt" + "reflect" +) + +// Cloner knows how to copy one type to another. +type Cloner struct { + // Map from the type to a function which can do the deep copy. + deepCopyFuncs map[reflect.Type]reflect.Value + generatedDeepCopyFuncs map[reflect.Type]func(in interface{}, out interface{}, c *Cloner) error +} + +// NewCloner creates a new Cloner object. +func NewCloner() *Cloner { + c := &Cloner{ + deepCopyFuncs: map[reflect.Type]reflect.Value{}, + generatedDeepCopyFuncs: map[reflect.Type]func(in interface{}, out interface{}, c *Cloner) error{}, + } + if err := c.RegisterDeepCopyFunc(byteSliceDeepCopy); err != nil { + // If one of the deep-copy functions is malformed, detect it immediately. + panic(err) + } + return c +} + +// Prevent recursing into every byte... +func byteSliceDeepCopy(in *[]byte, out *[]byte, c *Cloner) error { + if *in != nil { + *out = make([]byte, len(*in)) + copy(*out, *in) + } else { + *out = nil + } + return nil +} + +// Verifies whether a deep-copy function has a correct signature. +func verifyDeepCopyFunctionSignature(ft reflect.Type) error { + if ft.Kind() != reflect.Func { + return fmt.Errorf("expected func, got: %v", ft) + } + if ft.NumIn() != 3 { + return fmt.Errorf("expected three 'in' params, got %v", ft) + } + if ft.NumOut() != 1 { + return fmt.Errorf("expected one 'out' param, got %v", ft) + } + if ft.In(0).Kind() != reflect.Ptr { + return fmt.Errorf("expected pointer arg for 'in' param 0, got: %v", ft) + } + if ft.In(1) != ft.In(0) { + return fmt.Errorf("expected 'in' param 0 the same as param 1, got: %v", ft) + } + var forClonerType Cloner + if expected := reflect.TypeOf(&forClonerType); ft.In(2) != expected { + return fmt.Errorf("expected '%v' arg for 'in' param 2, got: '%v'", expected, ft.In(2)) + } + var forErrorType error + // This convolution is necessary, otherwise TypeOf picks up on the fact + // that forErrorType is nil + errorType := reflect.TypeOf(&forErrorType).Elem() + if ft.Out(0) != errorType { + return fmt.Errorf("expected error return, got: %v", ft) + } + return nil +} + +// RegisterGeneratedDeepCopyFunc registers a copying func with the Cloner. +// deepCopyFunc must take three parameters: a type input, a pointer to a +// type output, and a pointer to Cloner. It should return an error. +// +// Example: +// c.RegisterGeneratedDeepCopyFunc( +// func(in Pod, out *Pod, c *Cloner) error { +// // deep copy logic... +// return nil +// }) +func (c *Cloner) RegisterDeepCopyFunc(deepCopyFunc interface{}) error { + fv := reflect.ValueOf(deepCopyFunc) + ft := fv.Type() + if err := verifyDeepCopyFunctionSignature(ft); err != nil { + return err + } + c.deepCopyFuncs[ft.In(0)] = fv + return nil +} + +// GeneratedDeepCopyFunc bundles an untyped generated deep-copy function of a type +// with a reflection type object used as a key to lookup the deep-copy function. +type GeneratedDeepCopyFunc struct { + Fn func(in interface{}, out interface{}, c *Cloner) error + InType reflect.Type +} + +// Similar to RegisterDeepCopyFunc, but registers deep copy function that were +// automatically generated. +func (c *Cloner) RegisterGeneratedDeepCopyFunc(fn GeneratedDeepCopyFunc) error { + c.generatedDeepCopyFuncs[fn.InType] = fn.Fn + return nil +} + +// DeepCopy will perform a deep copy of a given object. +func (c *Cloner) DeepCopy(in interface{}) (interface{}, error) { + // Can be invalid if we run DeepCopy(X) where X is a nil interface type. + // For example, we get an invalid value when someone tries to deep-copy + // a nil labels.Selector. + // This does not occur if X is nil and is a pointer to a concrete type. + if in == nil { + return nil, nil + } + inValue := reflect.ValueOf(in) + outValue, err := c.deepCopy(inValue) + if err != nil { + return nil, err + } + return outValue.Interface(), nil +} + +func (c *Cloner) deepCopy(src reflect.Value) (reflect.Value, error) { + inType := src.Type() + + switch src.Kind() { + case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: + if src.IsNil() { + return src, nil + } + } + + if fv, ok := c.deepCopyFuncs[inType]; ok { + return c.customDeepCopy(src, fv) + } + if fv, ok := c.generatedDeepCopyFuncs[inType]; ok { + var outValue reflect.Value + outValue = reflect.New(inType.Elem()) + err := fv(src.Interface(), outValue.Interface(), c) + return outValue, err + } + return c.defaultDeepCopy(src) +} + +func (c *Cloner) customDeepCopy(src, fv reflect.Value) (reflect.Value, error) { + outValue := reflect.New(src.Type().Elem()) + args := []reflect.Value{src, outValue, reflect.ValueOf(c)} + result := fv.Call(args)[0].Interface() + // This convolution is necessary because nil interfaces won't convert + // to error. + if result == nil { + return outValue, nil + } + return outValue, result.(error) +} + +func (c *Cloner) defaultDeepCopy(src reflect.Value) (reflect.Value, error) { + switch src.Kind() { + case reflect.Chan, reflect.Func, reflect.UnsafePointer, reflect.Uintptr: + return src, fmt.Errorf("cannot deep copy kind: %s", src.Kind()) + case reflect.Array: + dst := reflect.New(src.Type()) + for i := 0; i < src.Len(); i++ { + copyVal, err := c.deepCopy(src.Index(i)) + if err != nil { + return src, err + } + dst.Elem().Index(i).Set(copyVal) + } + return dst.Elem(), nil + case reflect.Interface: + if src.IsNil() { + return src, nil + } + return c.deepCopy(src.Elem()) + case reflect.Map: + if src.IsNil() { + return src, nil + } + dst := reflect.MakeMap(src.Type()) + for _, k := range src.MapKeys() { + copyVal, err := c.deepCopy(src.MapIndex(k)) + if err != nil { + return src, err + } + dst.SetMapIndex(k, copyVal) + } + return dst, nil + case reflect.Ptr: + if src.IsNil() { + return src, nil + } + dst := reflect.New(src.Type().Elem()) + copyVal, err := c.deepCopy(src.Elem()) + if err != nil { + return src, err + } + dst.Elem().Set(copyVal) + return dst, nil + case reflect.Slice: + if src.IsNil() { + return src, nil + } + dst := reflect.MakeSlice(src.Type(), 0, src.Len()) + for i := 0; i < src.Len(); i++ { + copyVal, err := c.deepCopy(src.Index(i)) + if err != nil { + return src, err + } + dst = reflect.Append(dst, copyVal) + } + return dst, nil + case reflect.Struct: + dst := reflect.New(src.Type()) + for i := 0; i < src.NumField(); i++ { + if !dst.Elem().Field(i).CanSet() { + // Can't set private fields. At this point, the + // best we can do is a shallow copy. For + // example, time.Time is a value type with + // private members that can be shallow copied. + return src, nil + } + copyVal, err := c.deepCopy(src.Field(i)) + if err != nil { + return src, err + } + dst.Elem().Field(i).Set(copyVal) + } + return dst.Elem(), nil + + default: + // Value types like numbers, booleans, and strings. + return src, nil + } +} diff --git a/k8s.io/apimachinery/pkg/runtime/converter.go b/k8s.io/apimachinery/pkg/conversion/unstructured/converter.go similarity index 90% rename from k8s.io/apimachinery/pkg/runtime/converter.go rename to k8s.io/apimachinery/pkg/conversion/unstructured/converter.go index f6f7c10d..d0e625d2 100644 --- a/k8s.io/apimachinery/pkg/runtime/converter.go +++ b/k8s.io/apimachinery/pkg/conversion/unstructured/converter.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package runtime +package unstructured import ( "bytes" @@ -27,18 +27,19 @@ import ( "strings" "sync" "sync/atomic" - "time" - "k8s.io/apimachinery/pkg/conversion" + apiequality "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/json" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "github.com/golang/glog" ) -// UnstructuredConverter is an interface for converting between interface{} +// Converter is an interface for converting between interface{} // and map[string]interface representation. -type UnstructuredConverter interface { +type Converter interface { ToUnstructured(obj interface{}) (map[string]interface{}, error) FromUnstructured(u map[string]interface{}, obj interface{}) error } @@ -77,16 +78,7 @@ var ( float64Type = reflect.TypeOf(float64(0)) boolType = reflect.TypeOf(bool(false)) fieldCache = newFieldsCache() - - // DefaultUnstructuredConverter performs unstructured to Go typed object conversions. - DefaultUnstructuredConverter = &unstructuredConverter{ - mismatchDetection: parseBool(os.Getenv("KUBE_PATCH_CONVERSION_DETECTOR")), - comparison: conversion.EqualitiesOrDie( - func(a, b time.Time) bool { - return a.UTC() == b.UTC() - }, - ), - } + DefaultConverter = NewConverter(parseBool(os.Getenv("KUBE_PATCH_CONVERSION_DETECTOR"))) ) func parseBool(key string) bool { @@ -100,30 +92,24 @@ func parseBool(key string) bool { return value } -// unstructuredConverter knows how to convert between interface{} and +// ConverterImpl knows how to convert between interface{} and // Unstructured in both ways. -type unstructuredConverter struct { +type converterImpl struct { // If true, we will be additionally running conversion via json // to ensure that the result is true. // This is supposed to be set only in tests. mismatchDetection bool - // comparison is the default test logic used to compare - comparison conversion.Equalities } -// NewTestUnstructuredConverter creates an UnstructuredConverter that accepts JSON typed maps and translates them -// to Go types via reflection. It performs mismatch detection automatically and is intended for use by external -// test tools. Use DefaultUnstructuredConverter if you do not explicitly need mismatch detection. -func NewTestUnstructuredConverter(comparison conversion.Equalities) UnstructuredConverter { - return &unstructuredConverter{ - mismatchDetection: true, - comparison: comparison, +func NewConverter(mismatchDetection bool) Converter { + return &converterImpl{ + mismatchDetection: mismatchDetection, } } // FromUnstructured converts an object from map[string]interface{} representation into a concrete type. // It uses encoding/json/Unmarshaler if object implements it or reflection if not. -func (c *unstructuredConverter) FromUnstructured(u map[string]interface{}, obj interface{}) error { +func (c *converterImpl) FromUnstructured(u map[string]interface{}, obj interface{}) error { t := reflect.TypeOf(obj) value := reflect.ValueOf(obj) if t.Kind() != reflect.Ptr || value.IsNil() { @@ -136,8 +122,8 @@ func (c *unstructuredConverter) FromUnstructured(u map[string]interface{}, obj i if (err != nil) != (newErr != nil) { glog.Fatalf("FromUnstructured unexpected error for %v: error: %v", u, err) } - if err == nil && !c.comparison.DeepEqual(obj, newObj) { - glog.Fatalf("FromUnstructured mismatch\nobj1: %#v\nobj2: %#v", obj, newObj) + if err == nil && !apiequality.Semantic.DeepEqual(obj, newObj) { + glog.Fatalf("FromUnstructured mismatch for %#v, diff: %v", obj, diff.ObjectReflectDiff(obj, newObj)) } } return err @@ -407,12 +393,11 @@ func interfaceFromUnstructured(sv, dv reflect.Value) error { // ToUnstructured converts an object into map[string]interface{} representation. // It uses encoding/json/Marshaler if object implements it or reflection if not. -func (c *unstructuredConverter) ToUnstructured(obj interface{}) (map[string]interface{}, error) { +func (c *converterImpl) ToUnstructured(obj interface{}) (map[string]interface{}, error) { var u map[string]interface{} var err error - if unstr, ok := obj.(Unstructured); ok { - // UnstructuredContent() mutates the object so we need to make a copy first - u = unstr.DeepCopyObject().(Unstructured).UnstructuredContent() + if unstr, ok := obj.(runtime.Unstructured); ok { + u = DeepCopyJSON(unstr.UnstructuredContent()) } else { t := reflect.TypeOf(obj) value := reflect.ValueOf(obj) @@ -428,8 +413,8 @@ func (c *unstructuredConverter) ToUnstructured(obj interface{}) (map[string]inte if (err != nil) != (newErr != nil) { glog.Fatalf("ToUnstructured unexpected error for %v: error: %v; newErr: %v", obj, err, newErr) } - if err == nil && !c.comparison.DeepEqual(u, newUnstr) { - glog.Fatalf("ToUnstructured mismatch\nobj1: %#v\nobj2: %#v", u, newUnstr) + if err == nil && !apiequality.Semantic.DeepEqual(u, newUnstr) { + glog.Fatalf("ToUnstructured mismatch for %#v, diff: %v", u, diff.ObjectReflectDiff(u, newUnstr)) } } if err != nil { @@ -441,23 +426,21 @@ func (c *unstructuredConverter) ToUnstructured(obj interface{}) (map[string]inte // DeepCopyJSON deep copies the passed value, assuming it is a valid JSON representation i.e. only contains // types produced by json.Unmarshal(). func DeepCopyJSON(x map[string]interface{}) map[string]interface{} { - return DeepCopyJSONValue(x).(map[string]interface{}) + return deepCopyJSON(x).(map[string]interface{}) } -// DeepCopyJSONValue deep copies the passed value, assuming it is a valid JSON representation i.e. only contains -// types produced by json.Unmarshal(). -func DeepCopyJSONValue(x interface{}) interface{} { +func deepCopyJSON(x interface{}) interface{} { switch x := x.(type) { case map[string]interface{}: clone := make(map[string]interface{}, len(x)) for k, v := range x { - clone[k] = DeepCopyJSONValue(v) + clone[k] = deepCopyJSON(v) } return clone case []interface{}: clone := make([]interface{}, len(x)) for i, v := range x { - clone[i] = DeepCopyJSONValue(v) + clone[i] = deepCopyJSON(v) } return clone case string, int64, bool, float64, nil, encodingjson.Number: diff --git a/k8s.io/kube-openapi/pkg/util/proto/doc.go b/k8s.io/apimachinery/pkg/conversion/unstructured/doc.go similarity index 74% rename from k8s.io/kube-openapi/pkg/util/proto/doc.go rename to k8s.io/apimachinery/pkg/conversion/unstructured/doc.go index 11ed8a6b..cd40e74b 100644 --- a/k8s.io/kube-openapi/pkg/util/proto/doc.go +++ b/k8s.io/apimachinery/pkg/conversion/unstructured/doc.go @@ -14,6 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Package proto is a collection of libraries for parsing and indexing the type definitions. -// The openapi spec contains the object model definitions and extensions metadata. -package proto +// Package unstructured provides conversion from runtime objects +// to map[string]interface{} representation. +package unstructured // import "k8s.io/apimachinery/pkg/conversion/unstructured" diff --git a/k8s.io/apimachinery/pkg/labels/zz_generated.deepcopy.go b/k8s.io/apimachinery/pkg/labels/zz_generated.deepcopy.go index d22cddbf..80ba3fb7 100644 --- a/k8s.io/apimachinery/pkg/labels/zz_generated.deepcopy.go +++ b/k8s.io/apimachinery/pkg/labels/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -20,6 +20,23 @@ limitations under the License. package labels +import ( + conversion "k8s.io/apimachinery/pkg/conversion" + reflect "reflect" +) + +// GetGeneratedDeepCopyFuncs returns the generated funcs, since we aren't registering them. +// +// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented. +func GetGeneratedDeepCopyFuncs() []conversion.GeneratedDeepCopyFunc { + return []conversion.GeneratedDeepCopyFunc{ + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*Requirement).DeepCopyInto(out.(*Requirement)) + return nil + }, InType: reflect.TypeOf(&Requirement{})}, + } +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Requirement) DeepCopyInto(out *Requirement) { *out = *in diff --git a/k8s.io/apimachinery/pkg/runtime/codec.go b/k8s.io/apimachinery/pkg/runtime/codec.go index 5b3080aa..d9748f06 100644 --- a/k8s.io/apimachinery/pkg/runtime/codec.go +++ b/k8s.io/apimachinery/pkg/runtime/codec.go @@ -139,7 +139,6 @@ func NewParameterCodec(scheme *Scheme) ParameterCodec { typer: scheme, convertor: scheme, creator: scheme, - defaulter: scheme, } } @@ -148,7 +147,6 @@ type parameterCodec struct { typer ObjectTyper convertor ObjectConvertor creator ObjectCreater - defaulter ObjectDefaulter } var _ ParameterCodec = ¶meterCodec{} @@ -165,17 +163,9 @@ func (c *parameterCodec) DecodeParameters(parameters url.Values, from schema.Gro } for i := range targetGVKs { if targetGVKs[i].GroupVersion() == from { - if err := c.convertor.Convert(¶meters, into, nil); err != nil { - return err - } - // in the case where we going into the same object we're receiving, default on the outbound object - if c.defaulter != nil { - c.defaulter.Default(into) - } - return nil + return c.convertor.Convert(¶meters, into, nil) } } - input, err := c.creator.New(from.WithKind(targetGVKs[0].Kind)) if err != nil { return err @@ -183,10 +173,6 @@ func (c *parameterCodec) DecodeParameters(parameters url.Values, from schema.Gro if err := c.convertor.Convert(¶meters, input, nil); err != nil { return err } - // if we have defaulter, default the input before converting to output - if c.defaulter != nil { - c.defaulter.Default(input) - } return c.convertor.Convert(input, into, nil) } diff --git a/k8s.io/apimachinery/pkg/runtime/error.go b/k8s.io/apimachinery/pkg/runtime/error.go index 86b24840..21a35570 100644 --- a/k8s.io/apimachinery/pkg/runtime/error.go +++ b/k8s.io/apimachinery/pkg/runtime/error.go @@ -94,6 +94,8 @@ type missingVersionErr struct { data string } +// IsMissingVersion returns true if the error indicates that the provided object +// is missing a 'Version' field. func NewMissingVersionErr(data string) error { return &missingVersionErr{data} } @@ -102,8 +104,6 @@ func (k *missingVersionErr) Error() string { return fmt.Sprintf("Object 'apiVersion' is missing in '%s'", k.data) } -// IsMissingVersion returns true if the error indicates that the provided object -// is missing a 'Version' field. func IsMissingVersion(err error) bool { if err == nil { return false diff --git a/k8s.io/apimachinery/pkg/runtime/generated.pb.go b/k8s.io/apimachinery/pkg/runtime/generated.pb.go index f561fd47..bce8336a 100644 --- a/k8s.io/apimachinery/pkg/runtime/generated.pb.go +++ b/k8s.io/apimachinery/pkg/runtime/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/k8s.io/apimachinery/pkg/runtime/interfaces.go b/k8s.io/apimachinery/pkg/runtime/interfaces.go index 9d00f165..c90eef5a 100644 --- a/k8s.io/apimachinery/pkg/runtime/interfaces.go +++ b/k8s.io/apimachinery/pkg/runtime/interfaces.go @@ -233,13 +233,13 @@ type Object interface { // Unstructured objects store values as map[string]interface{}, with only values that can be serialized // to JSON allowed. type Unstructured interface { - Object + // IsUnstructuredObject is a marker interface to allow objects that can be serialized but not introspected + // to bypass conversion. + IsUnstructuredObject() // UnstructuredContent returns a non-nil, mutable map of the contents of this object. Values may be // []interface{}, map[string]interface{}, or any primitive type. Contents are typically serialized to // and from JSON. UnstructuredContent() map[string]interface{} - // SetUnstructuredContent updates the object content to match the provided map. - SetUnstructuredContent(map[string]interface{}) // IsList returns true if this type is a list or matches the list convention - has an array called "items". IsList() bool // EachListItem should pass a single item out of the list as an Object to the provided function. Any diff --git a/k8s.io/apimachinery/pkg/runtime/schema/generated.pb.go b/k8s.io/apimachinery/pkg/runtime/schema/generated.pb.go index 5357628a..e2cc1216 100644 --- a/k8s.io/apimachinery/pkg/runtime/schema/generated.pb.go +++ b/k8s.io/apimachinery/pkg/runtime/schema/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/k8s.io/apimachinery/pkg/runtime/scheme.go b/k8s.io/apimachinery/pkg/runtime/scheme.go index 08b75538..c597fcf9 100644 --- a/k8s.io/apimachinery/pkg/runtime/scheme.go +++ b/k8s.io/apimachinery/pkg/runtime/scheme.go @@ -68,6 +68,10 @@ type Scheme struct { // converter stores all registered conversion functions. It also has // default coverting behavior. converter *conversion.Converter + + // cloner stores all registered copy functions. It also has default + // deep copy behavior. + cloner *conversion.Cloner } // Function to convert a field selector to internal representation. @@ -76,10 +80,11 @@ type FieldLabelConversionFunc func(label, value string) (internalLabel, internal // NewScheme creates a new Scheme. This scheme is pluggable by default. func NewScheme() *Scheme { s := &Scheme{ - gvkToType: map[schema.GroupVersionKind]reflect.Type{}, - typeToGVK: map[reflect.Type][]schema.GroupVersionKind{}, - unversionedTypes: map[reflect.Type]schema.GroupVersionKind{}, - unversionedKinds: map[string]reflect.Type{}, + gvkToType: map[schema.GroupVersionKind]reflect.Type{}, + typeToGVK: map[reflect.Type][]schema.GroupVersionKind{}, + unversionedTypes: map[reflect.Type]schema.GroupVersionKind{}, + unversionedKinds: map[string]reflect.Type{}, + cloner: conversion.NewCloner(), fieldLabelConversionFuncs: map[string]map[string]FieldLabelConversionFunc{}, defaulterFuncs: map[reflect.Type]func(interface{}){}, } @@ -217,22 +222,19 @@ func (s *Scheme) AllKnownTypes() map[schema.GroupVersionKind]reflect.Type { return s.gvkToType } +// ObjectKind returns the group,version,kind of the go object and true if this object +// is considered unversioned, or an error if it's not a pointer or is unregistered. +func (s *Scheme) ObjectKind(obj Object) (schema.GroupVersionKind, bool, error) { + gvks, unversionedType, err := s.ObjectKinds(obj) + if err != nil { + return schema.GroupVersionKind{}, false, err + } + return gvks[0], unversionedType, nil +} + // ObjectKinds returns all possible group,version,kind of the go object, true if the // object is considered unversioned, or an error if it's not a pointer or is unregistered. func (s *Scheme) ObjectKinds(obj Object) ([]schema.GroupVersionKind, bool, error) { - // Unstructured objects are always considered to have their declared GVK - if _, ok := obj.(Unstructured); ok { - // we require that the GVK be populated in order to recognize the object - gvk := obj.GetObjectKind().GroupVersionKind() - if len(gvk.Kind) == 0 { - return nil, false, NewMissingKindErr("unstructured object has no kind") - } - if len(gvk.Version) == 0 { - return nil, false, NewMissingVersionErr("unstructured object has no version") - } - return []schema.GroupVersionKind{gvk}, false, nil - } - v, err := conversion.EnforcePtr(obj) if err != nil { return nil, false, err @@ -341,7 +343,7 @@ func (s *Scheme) AddConversionFuncs(conversionFuncs ...interface{}) error { return nil } -// AddGeneratedConversionFuncs registers conversion functions that were +// Similar to AddConversionFuncs, but registers conversion functions that were // automatically generated. func (s *Scheme) AddGeneratedConversionFuncs(conversionFuncs ...interface{}) error { for _, f := range conversionFuncs { @@ -352,6 +354,29 @@ func (s *Scheme) AddGeneratedConversionFuncs(conversionFuncs ...interface{}) err return nil } +// AddDeepCopyFuncs adds a function to the list of deep-copy functions. +// For the expected format of deep-copy function, see the comment for +// Copier.RegisterDeepCopyFunction. +func (s *Scheme) AddDeepCopyFuncs(deepCopyFuncs ...interface{}) error { + for _, f := range deepCopyFuncs { + if err := s.cloner.RegisterDeepCopyFunc(f); err != nil { + return err + } + } + return nil +} + +// Similar to AddDeepCopyFuncs, but registers deep-copy functions that were +// automatically generated. +func (s *Scheme) AddGeneratedDeepCopyFuncs(deepCopyFuncs ...conversion.GeneratedDeepCopyFunc) error { + for _, fn := range deepCopyFuncs { + if err := s.cloner.RegisterGeneratedDeepCopyFunc(fn); err != nil { + return err + } + } + return nil +} + // AddFieldLabelConversionFunc adds a conversion function to convert field selectors // of the given kind from the given version to internal version representation. func (s *Scheme) AddFieldLabelConversionFunc(version, kind string, conversionFunc FieldLabelConversionFunc) error { @@ -399,68 +424,10 @@ func (s *Scheme) Default(src Object) { // testing of conversion functions. Returns an error if the conversion isn't // possible. You can call this with types that haven't been registered (for example, // a to test conversion of types that are nested within registered types). The -// context interface is passed to the convertor. Convert also supports Unstructured -// types and will convert them intelligently. +// context interface is passed to the convertor. +// TODO: identify whether context should be hidden, or behind a formal context/scope +// interface func (s *Scheme) Convert(in, out interface{}, context interface{}) error { - unstructuredIn, okIn := in.(Unstructured) - unstructuredOut, okOut := out.(Unstructured) - switch { - case okIn && okOut: - // converting unstructured input to an unstructured output is a straight copy - unstructured - // is a "smart holder" and the contents are passed by reference between the two objects - unstructuredOut.SetUnstructuredContent(unstructuredIn.UnstructuredContent()) - return nil - - case okOut: - // if the output is an unstructured object, use the standard Go type to unstructured - // conversion. The object must not be internal. - obj, ok := in.(Object) - if !ok { - return fmt.Errorf("unable to convert object type %T to Unstructured, must be a runtime.Object", in) - } - gvks, unversioned, err := s.ObjectKinds(obj) - if err != nil { - return err - } - gvk := gvks[0] - - // if no conversion is necessary, convert immediately - if unversioned || gvk.Version != APIVersionInternal { - content, err := DefaultUnstructuredConverter.ToUnstructured(in) - if err != nil { - return err - } - unstructuredOut.SetUnstructuredContent(content) - return nil - } - - // attempt to convert the object to an external version first. - target, ok := context.(GroupVersioner) - if !ok { - return fmt.Errorf("unable to convert the internal object type %T to Unstructured without providing a preferred version to convert to", in) - } - // Convert is implicitly unsafe, so we don't need to perform a safe conversion - versioned, err := s.UnsafeConvertToVersion(obj, target) - if err != nil { - return err - } - content, err := DefaultUnstructuredConverter.ToUnstructured(versioned) - if err != nil { - return err - } - unstructuredOut.SetUnstructuredContent(content) - return nil - - case okIn: - // converting an unstructured object to any type is modeled by first converting - // the input to a versioned type, then running standard conversions - typed, err := s.unstructuredToTyped(unstructuredIn) - if err != nil { - return err - } - in = typed - } - flags, meta := s.generateConvertMeta(in) meta.Context = context if flags == 0 { @@ -469,8 +436,8 @@ func (s *Scheme) Convert(in, out interface{}, context interface{}) error { return s.converter.Convert(in, out, flags, meta) } -// ConvertFieldLabel alters the given field label and value for an kind field selector from -// versioned representation to an unversioned one or returns an error. +// Converts the given field label and value for an kind field selector from +// versioned representation to an unversioned one. func (s *Scheme) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { if s.fieldLabelConversionFuncs[version] == nil { return DefaultMetaV1FieldSelectorConversion(label, value) @@ -500,30 +467,15 @@ func (s *Scheme) UnsafeConvertToVersion(in Object, target GroupVersioner) (Objec // convertToVersion handles conversion with an optional copy. func (s *Scheme) convertToVersion(copy bool, in Object, target GroupVersioner) (Object, error) { - var t reflect.Type - - if u, ok := in.(Unstructured); ok { - typed, err := s.unstructuredToTyped(u) - if err != nil { - return nil, err - } - - in = typed - // unstructuredToTyped returns an Object, which must be a pointer to a struct. - t = reflect.TypeOf(in).Elem() - - } else { - // determine the incoming kinds with as few allocations as possible. - t = reflect.TypeOf(in) - if t.Kind() != reflect.Ptr { - return nil, fmt.Errorf("only pointer types may be converted: %v", t) - } - t = t.Elem() - if t.Kind() != reflect.Struct { - return nil, fmt.Errorf("only pointers to struct types may be converted: %v", t) - } + // determine the incoming kinds with as few allocations as possible. + t := reflect.TypeOf(in) + if t.Kind() != reflect.Ptr { + return nil, fmt.Errorf("only pointer types may be converted: %v", t) + } + t = t.Elem() + if t.Kind() != reflect.Struct { + return nil, fmt.Errorf("only pointers to struct types may be converted: %v", t) } - kinds, ok := s.typeToGVK[t] if !ok || len(kinds) == 0 { return nil, NewNotRegisteredErrForType(t) @@ -539,6 +491,7 @@ func (s *Scheme) convertToVersion(copy bool, in Object, target GroupVersioner) ( } return copyAndSetTargetKind(copy, in, unversionedKind) } + return nil, NewNotRegisteredErrForTarget(t, target) } @@ -576,25 +529,6 @@ func (s *Scheme) convertToVersion(copy bool, in Object, target GroupVersioner) ( return out, nil } -// unstructuredToTyped attempts to transform an unstructured object to a typed -// object if possible. It will return an error if conversion is not possible, or the versioned -// Go form of the object. Note that this conversion will lose fields. -func (s *Scheme) unstructuredToTyped(in Unstructured) (Object, error) { - // the type must be something we recognize - gvks, _, err := s.ObjectKinds(in) - if err != nil { - return nil, err - } - typed, err := s.New(gvks[0]) - if err != nil { - return nil, err - } - if err := DefaultUnstructuredConverter.FromUnstructured(in.UnstructuredContent(), typed); err != nil { - return nil, fmt.Errorf("unable to convert unstructured object to %v: %v", gvks[0], err) - } - return typed, nil -} - // generateConvertMeta constructs the meta value we pass to Convert. func (s *Scheme) generateConvertMeta(in interface{}) (conversion.FieldMatchingFlags, *conversion.Meta) { return s.converter.DefaultMeta(reflect.TypeOf(in)) diff --git a/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go b/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go index 8a217f32..ce3d77c2 100644 --- a/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go +++ b/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go @@ -150,10 +150,9 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i } if into != nil { - _, isUnstructured := into.(runtime.Unstructured) types, _, err := s.typer.ObjectKinds(into) switch { - case runtime.IsNotRegisteredError(err), isUnstructured: + case runtime.IsNotRegisteredError(err): if err := jsoniter.ConfigFastest.Unmarshal(data, into); err != nil { return nil, actual, err } diff --git a/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go b/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go index 82cf19ce..d347461a 100644 --- a/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go +++ b/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -20,6 +20,31 @@ limitations under the License. package runtime +import ( + conversion "k8s.io/apimachinery/pkg/conversion" + reflect "reflect" +) + +// GetGeneratedDeepCopyFuncs returns the generated funcs, since we aren't registering them. +// +// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented. +func GetGeneratedDeepCopyFuncs() []conversion.GeneratedDeepCopyFunc { + return []conversion.GeneratedDeepCopyFunc{ + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*RawExtension).DeepCopyInto(out.(*RawExtension)) + return nil + }, InType: reflect.TypeOf(&RawExtension{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*Unknown).DeepCopyInto(out.(*Unknown)) + return nil + }, InType: reflect.TypeOf(&Unknown{})}, + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*VersionedObjects).DeepCopyInto(out.(*VersionedObjects)) + return nil + }, InType: reflect.TypeOf(&VersionedObjects{})}, + } +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RawExtension) DeepCopyInto(out *RawExtension) { *out = *in diff --git a/k8s.io/apimachinery/pkg/util/intstr/generated.pb.go b/k8s.io/apimachinery/pkg/util/intstr/generated.pb.go index 161e9a6f..433dfa5c 100644 --- a/k8s.io/apimachinery/pkg/util/intstr/generated.pb.go +++ b/k8s.io/apimachinery/pkg/util/intstr/generated.pb.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/k8s.io/apimachinery/pkg/util/mergepatch/errors.go b/k8s.io/apimachinery/pkg/util/mergepatch/errors.go index 16501d5a..ac3c1e8c 100644 --- a/k8s.io/apimachinery/pkg/util/mergepatch/errors.go +++ b/k8s.io/apimachinery/pkg/util/mergepatch/errors.go @@ -29,7 +29,6 @@ var ( ErrBadPatchFormatForRetainKeys = errors.New("invalid patch format of retainKeys") ErrBadPatchFormatForSetElementOrderList = errors.New("invalid patch format of setElementOrder list") ErrPatchContentNotMatchRetainKeys = errors.New("patch content doesn't match retainKeys list") - ErrUnsupportedStrategicMergePatchFormat = errors.New("strategic merge patch format is not supported") ) func ErrNoMergeKey(m map[string]interface{}, k string) error { diff --git a/k8s.io/apimachinery/pkg/util/net/http.go b/k8s.io/apimachinery/pkg/util/net/http.go index bc2a531b..b544a60a 100644 --- a/k8s.io/apimachinery/pkg/util/net/http.go +++ b/k8s.io/apimachinery/pkg/util/net/http.go @@ -276,7 +276,17 @@ func NewProxierWithNoProxyCIDR(delegate func(req *http.Request) (*url.URL, error } return func(req *http.Request) (*url.URL, error) { - ip := net.ParseIP(req.URL.Hostname()) + host := req.URL.Host + // for some urls, the Host is already the host, not the host:port + if net.ParseIP(host) == nil { + var err error + host, _, err = net.SplitHostPort(req.URL.Host) + if err != nil { + return delegate(req) + } + } + + ip := net.ParseIP(host) if ip == nil { return delegate(req) } diff --git a/k8s.io/apimachinery/pkg/util/net/util.go b/k8s.io/apimachinery/pkg/util/net/util.go index 8344d10c..461144f0 100644 --- a/k8s.io/apimachinery/pkg/util/net/util.go +++ b/k8s.io/apimachinery/pkg/util/net/util.go @@ -18,8 +18,6 @@ package net import ( "net" - "net/url" - "os" "reflect" "syscall" ) @@ -40,16 +38,8 @@ func IPNetEqual(ipnet1, ipnet2 *net.IPNet) bool { // Returns if the given err is "connection reset by peer" error. func IsConnectionReset(err error) bool { - if urlErr, ok := err.(*url.Error); ok { - err = urlErr.Err - } - if opErr, ok := err.(*net.OpError); ok { - err = opErr.Err - } - if osErr, ok := err.(*os.SyscallError); ok { - err = osErr.Err - } - if errno, ok := err.(syscall.Errno); ok && errno == syscall.ECONNRESET { + opErr, ok := err.(*net.OpError) + if ok && opErr.Err.Error() == syscall.ECONNRESET.Error() { return true } return false diff --git a/k8s.io/apimachinery/pkg/util/strategicpatch/errors.go b/k8s.io/apimachinery/pkg/util/strategicpatch/errors.go deleted file mode 100644 index ab66d045..00000000 --- a/k8s.io/apimachinery/pkg/util/strategicpatch/errors.go +++ /dev/null @@ -1,49 +0,0 @@ -/* -Copyright 2017 The Kubernetes 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 strategicpatch - -import ( - "fmt" -) - -type LookupPatchMetaError struct { - Path string - Err error -} - -func (e LookupPatchMetaError) Error() string { - return fmt.Sprintf("LookupPatchMetaError(%s): %v", e.Path, e.Err) -} - -type FieldNotFoundError struct { - Path string - Field string -} - -func (e FieldNotFoundError) Error() string { - return fmt.Sprintf("unable to find api field %q in %s", e.Field, e.Path) -} - -type InvalidTypeError struct { - Path string - Expected string - Actual string -} - -func (e InvalidTypeError) Error() string { - return fmt.Sprintf("invalid type for %s: got %q, expected %q", e.Path, e.Actual, e.Expected) -} diff --git a/k8s.io/apimachinery/pkg/util/strategicpatch/meta.go b/k8s.io/apimachinery/pkg/util/strategicpatch/meta.go deleted file mode 100644 index c31de15e..00000000 --- a/k8s.io/apimachinery/pkg/util/strategicpatch/meta.go +++ /dev/null @@ -1,194 +0,0 @@ -/* -Copyright 2017 The Kubernetes 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 strategicpatch - -import ( - "errors" - "fmt" - "reflect" - - "k8s.io/apimachinery/pkg/util/mergepatch" - forkedjson "k8s.io/apimachinery/third_party/forked/golang/json" - openapi "k8s.io/kube-openapi/pkg/util/proto" -) - -type PatchMeta struct { - patchStrategies []string - patchMergeKey string -} - -func (pm PatchMeta) GetPatchStrategies() []string { - if pm.patchStrategies == nil { - return []string{} - } - return pm.patchStrategies -} - -func (pm PatchMeta) SetPatchStrategies(ps []string) { - pm.patchStrategies = ps -} - -func (pm PatchMeta) GetPatchMergeKey() string { - return pm.patchMergeKey -} - -func (pm PatchMeta) SetPatchMergeKey(pmk string) { - pm.patchMergeKey = pmk -} - -type LookupPatchMeta interface { - // LookupPatchMetadataForStruct gets subschema and the patch metadata (e.g. patch strategy and merge key) for map. - LookupPatchMetadataForStruct(key string) (LookupPatchMeta, PatchMeta, error) - // LookupPatchMetadataForSlice get subschema and the patch metadata for slice. - LookupPatchMetadataForSlice(key string) (LookupPatchMeta, PatchMeta, error) - // Get the type name of the field - Name() string -} - -type PatchMetaFromStruct struct { - T reflect.Type -} - -func NewPatchMetaFromStruct(dataStruct interface{}) (PatchMetaFromStruct, error) { - t, err := getTagStructType(dataStruct) - return PatchMetaFromStruct{T: t}, err -} - -var _ LookupPatchMeta = PatchMetaFromStruct{} - -func (s PatchMetaFromStruct) LookupPatchMetadataForStruct(key string) (LookupPatchMeta, PatchMeta, error) { - fieldType, fieldPatchStrategies, fieldPatchMergeKey, err := forkedjson.LookupPatchMetadataForStruct(s.T, key) - if err != nil { - return nil, PatchMeta{}, err - } - - return PatchMetaFromStruct{T: fieldType}, - PatchMeta{ - patchStrategies: fieldPatchStrategies, - patchMergeKey: fieldPatchMergeKey, - }, nil -} - -func (s PatchMetaFromStruct) LookupPatchMetadataForSlice(key string) (LookupPatchMeta, PatchMeta, error) { - subschema, patchMeta, err := s.LookupPatchMetadataForStruct(key) - if err != nil { - return nil, PatchMeta{}, err - } - elemPatchMetaFromStruct := subschema.(PatchMetaFromStruct) - t := elemPatchMetaFromStruct.T - - var elemType reflect.Type - switch t.Kind() { - // If t is an array or a slice, get the element type. - // If element is still an array or a slice, return an error. - // Otherwise, return element type. - case reflect.Array, reflect.Slice: - elemType = t.Elem() - if elemType.Kind() == reflect.Array || elemType.Kind() == reflect.Slice { - return nil, PatchMeta{}, errors.New("unexpected slice of slice") - } - // If t is an pointer, get the underlying element. - // If the underlying element is neither an array nor a slice, the pointer is pointing to a slice, - // e.g. https://github.com/kubernetes/kubernetes/blob/bc22e206c79282487ea0bf5696d5ccec7e839a76/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/patch_test.go#L2782-L2822 - // If the underlying element is either an array or a slice, return its element type. - case reflect.Ptr: - t = t.Elem() - if t.Kind() == reflect.Array || t.Kind() == reflect.Slice { - t = t.Elem() - } - elemType = t - default: - return nil, PatchMeta{}, fmt.Errorf("expected slice or array type, but got: %s", s.T.Kind().String()) - } - - return PatchMetaFromStruct{T: elemType}, patchMeta, nil -} - -func (s PatchMetaFromStruct) Name() string { - return s.T.Kind().String() -} - -func getTagStructType(dataStruct interface{}) (reflect.Type, error) { - if dataStruct == nil { - return nil, mergepatch.ErrBadArgKind(struct{}{}, nil) - } - - t := reflect.TypeOf(dataStruct) - // Get the underlying type for pointers - if t.Kind() == reflect.Ptr { - t = t.Elem() - } - - if t.Kind() != reflect.Struct { - return nil, mergepatch.ErrBadArgKind(struct{}{}, dataStruct) - } - - return t, nil -} - -func GetTagStructTypeOrDie(dataStruct interface{}) reflect.Type { - t, err := getTagStructType(dataStruct) - if err != nil { - panic(err) - } - return t -} - -type PatchMetaFromOpenAPI struct { - Schema openapi.Schema -} - -func NewPatchMetaFromOpenAPI(s openapi.Schema) PatchMetaFromOpenAPI { - return PatchMetaFromOpenAPI{Schema: s} -} - -var _ LookupPatchMeta = PatchMetaFromOpenAPI{} - -func (s PatchMetaFromOpenAPI) LookupPatchMetadataForStruct(key string) (LookupPatchMeta, PatchMeta, error) { - if s.Schema == nil { - return nil, PatchMeta{}, nil - } - kindItem := NewKindItem(key, s.Schema.GetPath()) - s.Schema.Accept(kindItem) - - err := kindItem.Error() - if err != nil { - return nil, PatchMeta{}, err - } - return PatchMetaFromOpenAPI{Schema: kindItem.subschema}, - kindItem.patchmeta, nil -} - -func (s PatchMetaFromOpenAPI) LookupPatchMetadataForSlice(key string) (LookupPatchMeta, PatchMeta, error) { - if s.Schema == nil { - return nil, PatchMeta{}, nil - } - sliceItem := NewSliceItem(key, s.Schema.GetPath()) - s.Schema.Accept(sliceItem) - - err := sliceItem.Error() - if err != nil { - return nil, PatchMeta{}, err - } - return PatchMetaFromOpenAPI{Schema: sliceItem.subschema}, - sliceItem.patchmeta, nil -} - -func (s PatchMetaFromOpenAPI) Name() string { - schema := s.Schema - return schema.GetName() -} diff --git a/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go b/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go index fd08759f..01014f9d 100644 --- a/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go +++ b/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go @@ -22,9 +22,9 @@ import ( "sort" "strings" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/json" "k8s.io/apimachinery/pkg/util/mergepatch" + forkedjson "k8s.io/apimachinery/third_party/forked/golang/json" ) // An alternate implementation of JSON Merge Patch @@ -92,16 +92,6 @@ type MergeOptions struct { // return a patch that yields the modified document when applied to the original document, or an error // if either of the two documents is invalid. func CreateTwoWayMergePatch(original, modified []byte, dataStruct interface{}, fns ...mergepatch.PreconditionFunc) ([]byte, error) { - schema, err := NewPatchMetaFromStruct(dataStruct) - if err != nil { - return nil, err - } - - return CreateTwoWayMergePatchUsingLookupPatchMeta(original, modified, schema, fns...) -} - -func CreateTwoWayMergePatchUsingLookupPatchMeta( - original, modified []byte, schema LookupPatchMeta, fns ...mergepatch.PreconditionFunc) ([]byte, error) { originalMap := map[string]interface{}{} if len(original) > 0 { if err := json.Unmarshal(original, &originalMap); err != nil { @@ -116,7 +106,7 @@ func CreateTwoWayMergePatchUsingLookupPatchMeta( } } - patchMap, err := CreateTwoWayMergeMapPatchUsingLookupPatchMeta(originalMap, modifiedMap, schema, fns...) + patchMap, err := CreateTwoWayMergeMapPatch(originalMap, modifiedMap, dataStruct, fns...) if err != nil { return nil, err } @@ -128,19 +118,15 @@ func CreateTwoWayMergePatchUsingLookupPatchMeta( // encoded JSONMap. // The serialized version of the map can then be passed to StrategicMergeMapPatch. func CreateTwoWayMergeMapPatch(original, modified JSONMap, dataStruct interface{}, fns ...mergepatch.PreconditionFunc) (JSONMap, error) { - schema, err := NewPatchMetaFromStruct(dataStruct) + t, err := getTagStructType(dataStruct) if err != nil { return nil, err } - return CreateTwoWayMergeMapPatchUsingLookupPatchMeta(original, modified, schema, fns...) -} - -func CreateTwoWayMergeMapPatchUsingLookupPatchMeta(original, modified JSONMap, schema LookupPatchMeta, fns ...mergepatch.PreconditionFunc) (JSONMap, error) { diffOptions := DiffOptions{ SetElementOrder: true, } - patchMap, err := diffMaps(original, modified, schema, diffOptions) + patchMap, err := diffMaps(original, modified, t, diffOptions) if err != nil { return nil, err } @@ -165,9 +151,12 @@ func CreateTwoWayMergeMapPatchUsingLookupPatchMeta(original, modified JSONMap, s // - IFF list of primitives && merge strategy - use parallel deletion list // - IFF list of maps or primitives with replace strategy (default) - set patch value to the value in modified // - Build $retainKeys directive for fields with retainKeys patch strategy -func diffMaps(original, modified map[string]interface{}, schema LookupPatchMeta, diffOptions DiffOptions) (map[string]interface{}, error) { +func diffMaps(original, modified map[string]interface{}, t reflect.Type, diffOptions DiffOptions) (map[string]interface{}, error) { patch := map[string]interface{}{} - + // Get the underlying type for pointers + if t.Kind() == reflect.Ptr { + t = t.Elem() + } // This will be used to build the $retainKeys directive sent in the patch retainKeysList := make([]interface{}, 0, len(modified)) @@ -209,10 +198,10 @@ func diffMaps(original, modified map[string]interface{}, schema LookupPatchMeta, switch originalValueTyped := originalValue.(type) { case map[string]interface{}: modifiedValueTyped := modifiedValue.(map[string]interface{}) - err = handleMapDiff(key, originalValueTyped, modifiedValueTyped, patch, schema, diffOptions) + err = handleMapDiff(key, originalValueTyped, modifiedValueTyped, patch, t, diffOptions) case []interface{}: modifiedValueTyped := modifiedValue.([]interface{}) - err = handleSliceDiff(key, originalValueTyped, modifiedValueTyped, patch, schema, diffOptions) + err = handleSliceDiff(key, originalValueTyped, modifiedValueTyped, patch, t, diffOptions) default: replacePatchFieldIfNotEqual(key, originalValue, modifiedValue, patch, diffOptions) } @@ -259,9 +248,8 @@ func handleDirectiveMarker(key string, originalValue, modifiedValue interface{}, // patch is the patch map that contains key and the updated value, and it is the parent of originalValue, modifiedValue // diffOptions contains multiple options to control how we do the diff. func handleMapDiff(key string, originalValue, modifiedValue, patch map[string]interface{}, - schema LookupPatchMeta, diffOptions DiffOptions) error { - subschema, patchMeta, err := schema.LookupPatchMetadataForStruct(key) - + t reflect.Type, diffOptions DiffOptions) error { + fieldType, fieldPatchStrategies, _, err := forkedjson.LookupPatchMetadata(t, key) if err != nil { // We couldn't look up metadata for the field // If the values are identical, this doesn't matter, no patch is needed @@ -271,7 +259,7 @@ func handleMapDiff(key string, originalValue, modifiedValue, patch map[string]in // Otherwise, return the error return err } - retainKeys, patchStrategy, err := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies()) + retainKeys, patchStrategy, err := extractRetainKeysPatchStrategy(fieldPatchStrategies) if err != nil { return err } @@ -283,7 +271,7 @@ func handleMapDiff(key string, originalValue, modifiedValue, patch map[string]in patch[key] = modifiedValue } default: - patchValue, err := diffMaps(originalValue, modifiedValue, subschema, diffOptions) + patchValue, err := diffMaps(originalValue, modifiedValue, fieldType, diffOptions) if err != nil { return err } @@ -302,8 +290,8 @@ func handleMapDiff(key string, originalValue, modifiedValue, patch map[string]in // patch is the patch map that contains key and the updated value, and it is the parent of originalValue, modifiedValue // diffOptions contains multiple options to control how we do the diff. func handleSliceDiff(key string, originalValue, modifiedValue []interface{}, patch map[string]interface{}, - schema LookupPatchMeta, diffOptions DiffOptions) error { - subschema, patchMeta, err := schema.LookupPatchMetadataForSlice(key) + t reflect.Type, diffOptions DiffOptions) error { + fieldType, fieldPatchStrategies, fieldPatchMergeKey, err := forkedjson.LookupPatchMetadata(t, key) if err != nil { // We couldn't look up metadata for the field // If the values are identical, this doesn't matter, no patch is needed @@ -313,7 +301,7 @@ func handleSliceDiff(key string, originalValue, modifiedValue []interface{}, pat // Otherwise, return the error return err } - retainKeys, patchStrategy, err := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies()) + retainKeys, patchStrategy, err := extractRetainKeysPatchStrategy(fieldPatchStrategies) if err != nil { return err } @@ -321,7 +309,7 @@ func handleSliceDiff(key string, originalValue, modifiedValue []interface{}, pat // Merge the 2 slices using mergePatchKey case mergeDirective: diffOptions.BuildRetainKeysDirective = retainKeys - addList, deletionList, setOrderList, err := diffLists(originalValue, modifiedValue, subschema, patchMeta.GetPatchMergeKey(), diffOptions) + addList, deletionList, setOrderList, err := diffLists(originalValue, modifiedValue, fieldType.Elem(), fieldPatchMergeKey, diffOptions) if err != nil { return err } @@ -548,7 +536,7 @@ func normalizeSliceOrder(toSort, order []interface{}, mergeKey string, kind refl // another list to set the order of the list // Only list of primitives with merge strategy will generate a parallel deletion list. // These two lists should yield modified when applied to original, for lists with merge semantics. -func diffLists(original, modified []interface{}, schema LookupPatchMeta, mergeKey string, diffOptions DiffOptions) ([]interface{}, []interface{}, []interface{}, error) { +func diffLists(original, modified []interface{}, t reflect.Type, mergeKey string, diffOptions DiffOptions) ([]interface{}, []interface{}, []interface{}, error) { if len(original) == 0 { // Both slices are empty - do nothing if len(modified) == 0 || diffOptions.IgnoreChangesAndAdditions { @@ -568,7 +556,7 @@ func diffLists(original, modified []interface{}, schema LookupPatchMeta, mergeKe kind := elementType.Kind() switch kind { case reflect.Map: - patchList, deleteList, err = diffListsOfMaps(original, modified, schema, mergeKey, diffOptions) + patchList, deleteList, err = diffListsOfMaps(original, modified, t, mergeKey, diffOptions) if err != nil { return nil, nil, nil, err } @@ -714,15 +702,15 @@ func compareListValuesAtIndex(list1Inbounds, list2Inbounds bool, list1Value, lis // diffListsOfMaps takes a pair of lists and // returns a (recursive) strategic merge patch list contains additions and changes and // a deletion list contains deletions -func diffListsOfMaps(original, modified []interface{}, schema LookupPatchMeta, mergeKey string, diffOptions DiffOptions) ([]interface{}, []interface{}, error) { +func diffListsOfMaps(original, modified []interface{}, t reflect.Type, mergeKey string, diffOptions DiffOptions) ([]interface{}, []interface{}, error) { patch := make([]interface{}, 0, len(modified)) deletionList := make([]interface{}, 0, len(original)) - originalSorted, err := sortMergeListsByNameArray(original, schema, mergeKey, false) + originalSorted, err := sortMergeListsByNameArray(original, t, mergeKey, false) if err != nil { return nil, nil, err } - modifiedSorted, err := sortMergeListsByNameArray(modified, schema, mergeKey, false) + modifiedSorted, err := sortMergeListsByNameArray(modified, t, mergeKey, false) if err != nil { return nil, nil, err } @@ -757,7 +745,7 @@ func diffListsOfMaps(original, modified []interface{}, schema LookupPatchMeta, m switch { case bothInBounds && ItemMatchesOriginalAndModifiedSlice(originalElementMergeKeyValueString, modifiedElementMergeKeyValueString): // Merge key values are equal, so recurse - patchValue, err := diffMaps(originalElement, modifiedElement, schema, diffOptions) + patchValue, err := diffMaps(originalElement, modifiedElement, t, diffOptions) if err != nil { return nil, nil, err } @@ -810,15 +798,6 @@ func getMapAndMergeKeyValueByIndex(index int, mergeKey string, listOfMaps []inte // must be json encoded content. A patch can be created from an original and a modified document // by calling CreateStrategicMergePatch. func StrategicMergePatch(original, patch []byte, dataStruct interface{}) ([]byte, error) { - schema, err := NewPatchMetaFromStruct(dataStruct) - if err != nil { - return nil, err - } - - return StrategicMergePatchUsingLookupPatchMeta(original, patch, schema) -} - -func StrategicMergePatchUsingLookupPatchMeta(original, patch []byte, schema LookupPatchMeta) ([]byte, error) { originalMap, err := handleUnmarshal(original) if err != nil { return nil, err @@ -828,7 +807,7 @@ func StrategicMergePatchUsingLookupPatchMeta(original, patch []byte, schema Look return nil, err } - result, err := StrategicMergeMapPatchUsingLookupPatchMeta(originalMap, patchMap, schema) + result, err := StrategicMergeMapPatch(originalMap, patchMap, dataStruct) if err != nil { return nil, err } @@ -849,35 +828,38 @@ func handleUnmarshal(j []byte) (map[string]interface{}, error) { return m, nil } -// StrategicMergeMapPatch applies a strategic merge patch. The original and patch documents +// StrategicMergePatch applies a strategic merge patch. The original and patch documents // must be JSONMap. A patch can be created from an original and modified document by // calling CreateTwoWayMergeMapPatch. // Warning: the original and patch JSONMap objects are mutated by this function and should not be reused. func StrategicMergeMapPatch(original, patch JSONMap, dataStruct interface{}) (JSONMap, error) { - schema, err := NewPatchMetaFromStruct(dataStruct) + t, err := getTagStructType(dataStruct) if err != nil { return nil, err } + mergeOptions := MergeOptions{ + MergeParallelList: true, + IgnoreUnmatchedNulls: true, + } + return mergeMap(original, patch, t, mergeOptions) +} - // We need the go struct tags `patchMergeKey` and `patchStrategy` for fields that support a strategic merge patch. - // For native resources, we can easily figure out these tags since we know the fields. - - // Because custom resources are decoded as Unstructured and because we're missing the metadata about how to handle - // each field in a strategic merge patch, we can't find the go struct tags. Hence, we can't easily do a strategic merge - // for custom resources. So we should fail fast and return an error. - if _, ok := dataStruct.(*unstructured.Unstructured); ok { - return nil, mergepatch.ErrUnsupportedStrategicMergePatchFormat +func getTagStructType(dataStruct interface{}) (reflect.Type, error) { + if dataStruct == nil { + return nil, mergepatch.ErrBadArgKind(struct{}{}, nil) } - return StrategicMergeMapPatchUsingLookupPatchMeta(original, patch, schema) -} + t := reflect.TypeOf(dataStruct) + // Get the underlying type for pointers + if t.Kind() == reflect.Ptr { + t = t.Elem() + } -func StrategicMergeMapPatchUsingLookupPatchMeta(original, patch JSONMap, schema LookupPatchMeta) (JSONMap, error) { - mergeOptions := MergeOptions{ - MergeParallelList: true, - IgnoreUnmatchedNulls: true, + if t.Kind() != reflect.Struct { + return nil, mergepatch.ErrBadArgKind(struct{}{}, dataStruct) } - return mergeMap(original, patch, schema, mergeOptions) + + return t, nil } // handleDirectiveInMergeMap handles the patch directive when merging 2 maps. @@ -1085,7 +1067,7 @@ func applyRetainKeysDirective(original, patch map[string]interface{}, options Me // The precedence is $setElementOrder > order in patch list > order in live list. // This function will delete the item after merging it to prevent process it again in the future. // Ref: https://git.k8s.io/community/contributors/design-proposals/cli/preserve-order-in-strategic-merge-patch.md -func mergePatchIntoOriginal(original, patch map[string]interface{}, schema LookupPatchMeta, mergeOptions MergeOptions) error { +func mergePatchIntoOriginal(original, patch map[string]interface{}, t reflect.Type, mergeOptions MergeOptions) error { for key, patchV := range patch { // Do nothing if there is no ordering directive if !strings.HasPrefix(key, setElementOrderDirectivePrefix) { @@ -1112,9 +1094,9 @@ func mergePatchIntoOriginal(original, patch map[string]interface{}, schema Looku var ( ok bool originalFieldValue, patchFieldValue, merged []interface{} - patchStrategy string - patchMeta PatchMeta - subschema LookupPatchMeta + patchStrategy, mergeKey string + patchStrategies []string + fieldType reflect.Type ) typedSetElementOrderList, ok := setElementOrderInPatch.([]interface{}) if !ok { @@ -1140,16 +1122,16 @@ func mergePatchIntoOriginal(original, patch map[string]interface{}, schema Looku return mergepatch.ErrBadArgType(patchFieldValue, patchList) } } - subschema, patchMeta, err = schema.LookupPatchMetadataForSlice(originalKey) + fieldType, patchStrategies, mergeKey, err = forkedjson.LookupPatchMetadata(t, originalKey) if err != nil { return err } - _, patchStrategy, err = extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies()) + _, patchStrategy, err = extractRetainKeysPatchStrategy(patchStrategies) if err != nil { return err } // Check for consistency between the element order list and the field it applies to - err = validatePatchWithSetOrderList(patchFieldValue, typedSetElementOrderList, patchMeta.GetPatchMergeKey()) + err = validatePatchWithSetOrderList(patchFieldValue, typedSetElementOrderList, mergeKey) if err != nil { return err } @@ -1162,8 +1144,8 @@ func mergePatchIntoOriginal(original, patch map[string]interface{}, schema Looku // list was added merged = patchFieldValue case foundOriginal && foundPatch: - merged, err = mergeSliceHandler(originalList, patchList, subschema, - patchStrategy, patchMeta.GetPatchMergeKey(), false, mergeOptions) + merged, err = mergeSliceHandler(originalList, patchList, fieldType, + patchStrategy, mergeKey, false, mergeOptions) if err != nil { return err } @@ -1173,13 +1155,13 @@ func mergePatchIntoOriginal(original, patch map[string]interface{}, schema Looku // Split all items into patch items and server-only items and then enforce the order. var patchItems, serverOnlyItems []interface{} - if len(patchMeta.GetPatchMergeKey()) == 0 { + if len(mergeKey) == 0 { // Primitives doesn't need merge key to do partitioning. patchItems, serverOnlyItems = partitionPrimitivesByPresentInList(merged, typedSetElementOrderList) } else { // Maps need merge key to do partitioning. - patchItems, serverOnlyItems, err = partitionMapsByPresentInList(merged, typedSetElementOrderList, patchMeta.GetPatchMergeKey()) + patchItems, serverOnlyItems, err = partitionMapsByPresentInList(merged, typedSetElementOrderList, mergeKey) if err != nil { return err } @@ -1193,7 +1175,7 @@ func mergePatchIntoOriginal(original, patch map[string]interface{}, schema Looku // normalize merged list // typedSetElementOrderList contains all the relative order in typedPatchList, // so don't need to use typedPatchList - both, err := normalizeElementOrder(patchItems, serverOnlyItems, typedSetElementOrderList, originalFieldValue, patchMeta.GetPatchMergeKey(), kind) + both, err := normalizeElementOrder(patchItems, serverOnlyItems, typedSetElementOrderList, originalFieldValue, mergeKey, kind) if err != nil { return err } @@ -1255,7 +1237,7 @@ func partitionMapsByPresentInList(original, partitionBy []interface{}, mergeKey // If patch contains any null field (e.g. field_1: null) that is not // present in original, then to propagate it to the end result use // mergeOptions.IgnoreUnmatchedNulls == false. -func mergeMap(original, patch map[string]interface{}, schema LookupPatchMeta, mergeOptions MergeOptions) (map[string]interface{}, error) { +func mergeMap(original, patch map[string]interface{}, t reflect.Type, mergeOptions MergeOptions) (map[string]interface{}, error) { if v, ok := patch[directiveMarker]; ok { return handleDirectiveInMergeMap(v, patch) } @@ -1275,7 +1257,7 @@ func mergeMap(original, patch map[string]interface{}, schema LookupPatchMeta, me // When not merging the directive, it will make sure $setElementOrder list exist only in original. // When merging the directive, it will process $setElementOrder and its patch list together. // This function will delete the merged elements from patch so they will not be reprocessed - err = mergePatchIntoOriginal(original, patch, schema, mergeOptions) + err = mergePatchIntoOriginal(original, patch, t, mergeOptions) if err != nil { return nil, err } @@ -1313,6 +1295,11 @@ func mergeMap(original, patch map[string]interface{}, schema LookupPatchMeta, me continue } + // If the data type is a pointer, resolve the element. + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + originalType := reflect.TypeOf(original[k]) patchType := reflect.TypeOf(patchV) if originalType != patchType { @@ -1320,27 +1307,22 @@ func mergeMap(original, patch map[string]interface{}, schema LookupPatchMeta, me continue } // If they're both maps or lists, recurse into the value. + // First find the fieldPatchStrategy and fieldPatchMergeKey. + fieldType, fieldPatchStrategies, fieldPatchMergeKey, err := forkedjson.LookupPatchMetadata(t, k) + if err != nil { + return nil, err + } + _, patchStrategy, err := extractRetainKeysPatchStrategy(fieldPatchStrategies) + if err != nil { + return nil, err + } + switch originalType.Kind() { case reflect.Map: - subschema, patchMeta, err := schema.LookupPatchMetadataForStruct(k) - if err != nil { - return nil, err - } - _, patchStrategy, err := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies()) - if err != nil { - return nil, err - } - original[k], err = mergeMapHandler(original[k], patchV, subschema, patchStrategy, mergeOptions) + + original[k], err = mergeMapHandler(original[k], patchV, fieldType, patchStrategy, mergeOptions) case reflect.Slice: - subschema, patchMeta, err := schema.LookupPatchMetadataForSlice(k) - if err != nil { - return nil, err - } - _, patchStrategy, err := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies()) - if err != nil { - return nil, err - } - original[k], err = mergeSliceHandler(original[k], patchV, subschema, patchStrategy, patchMeta.GetPatchMergeKey(), isDeleteList, mergeOptions) + original[k], err = mergeSliceHandler(original[k], patchV, fieldType, patchStrategy, fieldPatchMergeKey, isDeleteList, mergeOptions) default: original[k] = patchV } @@ -1353,7 +1335,7 @@ func mergeMap(original, patch map[string]interface{}, schema LookupPatchMeta, me // mergeMapHandler handles how to merge `patchV` whose key is `key` with `original` respecting // fieldPatchStrategy and mergeOptions. -func mergeMapHandler(original, patch interface{}, schema LookupPatchMeta, +func mergeMapHandler(original, patch interface{}, fieldType reflect.Type, fieldPatchStrategy string, mergeOptions MergeOptions) (map[string]interface{}, error) { typedOriginal, typedPatch, err := mapTypeAssertion(original, patch) if err != nil { @@ -1361,7 +1343,7 @@ func mergeMapHandler(original, patch interface{}, schema LookupPatchMeta, } if fieldPatchStrategy != replaceDirective { - return mergeMap(typedOriginal, typedPatch, schema, mergeOptions) + return mergeMap(typedOriginal, typedPatch, fieldType, mergeOptions) } else { return typedPatch, nil } @@ -1369,7 +1351,7 @@ func mergeMapHandler(original, patch interface{}, schema LookupPatchMeta, // mergeSliceHandler handles how to merge `patchV` whose key is `key` with `original` respecting // fieldPatchStrategy, fieldPatchMergeKey, isDeleteList and mergeOptions. -func mergeSliceHandler(original, patch interface{}, schema LookupPatchMeta, +func mergeSliceHandler(original, patch interface{}, fieldType reflect.Type, fieldPatchStrategy, fieldPatchMergeKey string, isDeleteList bool, mergeOptions MergeOptions) ([]interface{}, error) { typedOriginal, typedPatch, err := sliceTypeAssertion(original, patch) if err != nil { @@ -1377,7 +1359,8 @@ func mergeSliceHandler(original, patch interface{}, schema LookupPatchMeta, } if fieldPatchStrategy == mergeDirective { - return mergeSlice(typedOriginal, typedPatch, schema, fieldPatchMergeKey, mergeOptions, isDeleteList) + elemType := fieldType.Elem() + return mergeSlice(typedOriginal, typedPatch, elemType, fieldPatchMergeKey, mergeOptions, isDeleteList) } else { return typedPatch, nil } @@ -1386,7 +1369,7 @@ func mergeSliceHandler(original, patch interface{}, schema LookupPatchMeta, // Merge two slices together. Note: This may modify both the original slice and // the patch because getting a deep copy of a slice in golang is highly // non-trivial. -func mergeSlice(original, patch []interface{}, schema LookupPatchMeta, mergeKey string, mergeOptions MergeOptions, isDeleteList bool) ([]interface{}, error) { +func mergeSlice(original, patch []interface{}, elemType reflect.Type, mergeKey string, mergeOptions MergeOptions, isDeleteList bool) ([]interface{}, error) { if len(original) == 0 && len(patch) == 0 { return original, nil } @@ -1411,7 +1394,7 @@ func mergeSlice(original, patch []interface{}, schema LookupPatchMeta, mergeKey } else { if mergeKey == "" { - return nil, fmt.Errorf("cannot merge lists without merge key for %s", schema.Name()) + return nil, fmt.Errorf("cannot merge lists without merge key for type %s", elemType.Kind().String()) } original, patch, err = mergeSliceWithSpecialElements(original, patch, mergeKey) @@ -1419,7 +1402,7 @@ func mergeSlice(original, patch []interface{}, schema LookupPatchMeta, mergeKey return nil, err } - merged, err = mergeSliceWithoutSpecialElements(original, patch, mergeKey, schema, mergeOptions) + merged, err = mergeSliceWithoutSpecialElements(original, patch, mergeKey, elemType, mergeOptions) if err != nil { return nil, err } @@ -1497,7 +1480,7 @@ func deleteMatchingEntries(original []interface{}, mergeKey string, mergeValue i // mergeSliceWithoutSpecialElements merges slices with non-special elements. // original and patch must be slices of maps, they should be checked before calling this function. -func mergeSliceWithoutSpecialElements(original, patch []interface{}, mergeKey string, schema LookupPatchMeta, mergeOptions MergeOptions) ([]interface{}, error) { +func mergeSliceWithoutSpecialElements(original, patch []interface{}, mergeKey string, elemType reflect.Type, mergeOptions MergeOptions) ([]interface{}, error) { for _, v := range patch { typedV := v.(map[string]interface{}) mergeValue, ok := typedV[mergeKey] @@ -1516,7 +1499,7 @@ func mergeSliceWithoutSpecialElements(original, patch []interface{}, mergeKey st var mergedMaps interface{} var err error // Merge into original. - mergedMaps, err = mergeMap(originalMap, typedV, schema, mergeOptions) + mergedMaps, err = mergeMap(originalMap, typedV, elemType, mergeOptions) if err != nil { return nil, err } @@ -1549,7 +1532,7 @@ func findMapInSliceBasedOnKeyValue(m []interface{}, key string, value interface{ for k, v := range m { typedV, ok := v.(map[string]interface{}) if !ok { - return nil, 0, false, fmt.Errorf("value for key %v is not a map", k) + return nil, 0, false, fmt.Errorf("value for key %v is not a map.", k) } valueToMatch, ok := typedV[key] @@ -1565,14 +1548,14 @@ func findMapInSliceBasedOnKeyValue(m []interface{}, key string, value interface{ // by key. This is needed by tests because in JSON, list order is significant, // but in Strategic Merge Patch, merge lists do not have significant order. // Sorting the lists allows for order-insensitive comparison of patched maps. -func sortMergeListsByName(mapJSON []byte, schema LookupPatchMeta) ([]byte, error) { +func sortMergeListsByName(mapJSON []byte, dataStruct interface{}) ([]byte, error) { var m map[string]interface{} err := json.Unmarshal(mapJSON, &m) if err != nil { - return nil, mergepatch.ErrBadJSONDoc + return nil, err } - newM, err := sortMergeListsByNameMap(m, schema) + newM, err := sortMergeListsByNameMap(m, reflect.TypeOf(dataStruct)) if err != nil { return nil, err } @@ -1581,7 +1564,7 @@ func sortMergeListsByName(mapJSON []byte, schema LookupPatchMeta) ([]byte, error } // Function sortMergeListsByNameMap recursively sorts the merge lists by its mergeKey in a map. -func sortMergeListsByNameMap(s map[string]interface{}, schema LookupPatchMeta) (map[string]interface{}, error) { +func sortMergeListsByNameMap(s map[string]interface{}, t reflect.Type) (map[string]interface{}, error) { newS := map[string]interface{}{} for k, v := range s { if k == retainKeysDirective { @@ -1602,29 +1585,26 @@ func sortMergeListsByNameMap(s map[string]interface{}, schema LookupPatchMeta) ( return nil, mergepatch.ErrBadPatchFormatForSetElementOrderList } } else if k != directiveMarker { - // recurse for map and slice. - switch typedV := v.(type) { - case map[string]interface{}: - subschema, _, err := schema.LookupPatchMetadataForStruct(k) - if err != nil { - return nil, err - } - v, err = sortMergeListsByNameMap(typedV, subschema) - if err != nil { - return nil, err - } - case []interface{}: - subschema, patchMeta, err := schema.LookupPatchMetadataForSlice(k) - if err != nil { - return nil, err - } - _, patchStrategy, err := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies()) + fieldType, fieldPatchStrategies, fieldPatchMergeKey, err := forkedjson.LookupPatchMetadata(t, k) + if err != nil { + return nil, err + } + _, patchStrategy, err := extractRetainKeysPatchStrategy(fieldPatchStrategies) + if err != nil { + return nil, err + } + + // If v is a map or a merge slice, recurse. + if typedV, ok := v.(map[string]interface{}); ok { + var err error + v, err = sortMergeListsByNameMap(typedV, fieldType) if err != nil { return nil, err } + } else if typedV, ok := v.([]interface{}); ok { if patchStrategy == mergeDirective { var err error - v, err = sortMergeListsByNameArray(typedV, subschema, patchMeta.GetPatchMergeKey(), true) + v, err = sortMergeListsByNameArray(typedV, fieldType.Elem(), fieldPatchMergeKey, true) if err != nil { return nil, err } @@ -1639,7 +1619,7 @@ func sortMergeListsByNameMap(s map[string]interface{}, schema LookupPatchMeta) ( } // Function sortMergeListsByNameMap recursively sorts the merge lists by its mergeKey in an array. -func sortMergeListsByNameArray(s []interface{}, schema LookupPatchMeta, mergeKey string, recurse bool) ([]interface{}, error) { +func sortMergeListsByNameArray(s []interface{}, elemType reflect.Type, mergeKey string, recurse bool) ([]interface{}, error) { if len(s) == 0 { return s, nil } @@ -1662,7 +1642,7 @@ func sortMergeListsByNameArray(s []interface{}, schema LookupPatchMeta, mergeKey for _, elem := range s { if recurse { typedElem := elem.(map[string]interface{}) - newElem, err := sortMergeListsByNameMap(typedElem, schema) + newElem, err := sortMergeListsByNameMap(typedElem, elemType) if err != nil { return nil, err } @@ -1808,13 +1788,18 @@ func sliceElementType(slices ...[]interface{}) (reflect.Type, error) { // objects overlap with different values in any key. All keys are required to be // strings. Since patches of the same Type have congruent keys, this is valid // for multiple patch types. This method supports strategic merge patch semantics. -func MergingMapsHaveConflicts(left, right map[string]interface{}, schema LookupPatchMeta) (bool, error) { - return mergingMapFieldsHaveConflicts(left, right, schema, "", "") +func MergingMapsHaveConflicts(left, right map[string]interface{}, dataStruct interface{}) (bool, error) { + t, err := getTagStructType(dataStruct) + if err != nil { + return true, err + } + + return mergingMapFieldsHaveConflicts(left, right, t, "", "") } func mergingMapFieldsHaveConflicts( left, right interface{}, - schema LookupPatchMeta, + fieldType reflect.Type, fieldPatchStrategy, fieldPatchMergeKey string, ) (bool, error) { switch leftType := left.(type) { @@ -1845,14 +1830,15 @@ func mergingMapFieldsHaveConflicts( return false, nil } // Check the individual keys. - return mapsHaveConflicts(leftType, rightType, schema) + return mapsHaveConflicts(leftType, rightType, fieldType) case []interface{}: rightType, ok := right.([]interface{}) if !ok { return true, nil } - return slicesHaveConflicts(leftType, rightType, schema, fieldPatchStrategy, fieldPatchMergeKey) + return slicesHaveConflicts(leftType, rightType, fieldType, fieldPatchStrategy, fieldPatchMergeKey) + case string, float64, bool, int, int64, nil: return !reflect.DeepEqual(left, right), nil default: @@ -1860,37 +1846,21 @@ func mergingMapFieldsHaveConflicts( } } -func mapsHaveConflicts(typedLeft, typedRight map[string]interface{}, schema LookupPatchMeta) (bool, error) { +func mapsHaveConflicts(typedLeft, typedRight map[string]interface{}, structType reflect.Type) (bool, error) { for key, leftValue := range typedLeft { if key != directiveMarker && key != retainKeysDirective { if rightValue, ok := typedRight[key]; ok { - var subschema LookupPatchMeta - var patchMeta PatchMeta - var patchStrategy string - var err error - switch leftValue.(type) { - case []interface{}: - subschema, patchMeta, err = schema.LookupPatchMetadataForSlice(key) - if err != nil { - return true, err - } - _, patchStrategy, err = extractRetainKeysPatchStrategy(patchMeta.patchStrategies) - if err != nil { - return true, err - } - case map[string]interface{}: - subschema, patchMeta, err = schema.LookupPatchMetadataForStruct(key) - if err != nil { - return true, err - } - _, patchStrategy, err = extractRetainKeysPatchStrategy(patchMeta.patchStrategies) - if err != nil { - return true, err - } + fieldType, fieldPatchStrategies, fieldPatchMergeKey, err := forkedjson.LookupPatchMetadata(structType, key) + if err != nil { + return true, err + } + _, patchStrategy, err := extractRetainKeysPatchStrategy(fieldPatchStrategies) + if err != nil { + return true, err } if hasConflicts, err := mergingMapFieldsHaveConflicts(leftValue, rightValue, - subschema, patchStrategy, patchMeta.GetPatchMergeKey()); hasConflicts { + fieldType, patchStrategy, fieldPatchMergeKey); hasConflicts { return true, err } } @@ -1902,7 +1872,7 @@ func mapsHaveConflicts(typedLeft, typedRight map[string]interface{}, schema Look func slicesHaveConflicts( typedLeft, typedRight []interface{}, - schema LookupPatchMeta, + fieldType reflect.Type, fieldPatchStrategy, fieldPatchMergeKey string, ) (bool, error) { elementType, err := sliceElementType(typedLeft, typedRight) @@ -1910,6 +1880,7 @@ func slicesHaveConflicts( return true, err } + valueType := fieldType.Elem() if fieldPatchStrategy == mergeDirective { // Merging lists of scalars have no conflicts by definition // So we only need to check further if the elements are maps @@ -1928,7 +1899,7 @@ func slicesHaveConflicts( return true, err } - return mapsOfMapsHaveConflicts(leftMap, rightMap, schema) + return mapsOfMapsHaveConflicts(leftMap, rightMap, valueType) } // Either we don't have type information, or these are non-merging lists @@ -1946,7 +1917,7 @@ func slicesHaveConflicts( // Compare the slices element by element in order // This test will fail if the slices are not sorted for i := range typedLeft { - if hasConflicts, err := mergingMapFieldsHaveConflicts(typedLeft[i], typedRight[i], schema, "", ""); hasConflicts { + if hasConflicts, err := mergingMapFieldsHaveConflicts(typedLeft[i], typedRight[i], valueType, "", ""); hasConflicts { return true, err } } @@ -1973,10 +1944,10 @@ func sliceOfMapsToMapOfMaps(slice []interface{}, mergeKey string) (map[string]in return result, nil } -func mapsOfMapsHaveConflicts(typedLeft, typedRight map[string]interface{}, schema LookupPatchMeta) (bool, error) { +func mapsOfMapsHaveConflicts(typedLeft, typedRight map[string]interface{}, structType reflect.Type) (bool, error) { for key, leftValue := range typedLeft { if rightValue, ok := typedRight[key]; ok { - if hasConflicts, err := mergingMapFieldsHaveConflicts(leftValue, rightValue, schema, "", ""); hasConflicts { + if hasConflicts, err := mergingMapFieldsHaveConflicts(leftValue, rightValue, structType, "", ""); hasConflicts { return true, err } } @@ -1996,7 +1967,7 @@ func mapsOfMapsHaveConflicts(typedLeft, typedRight map[string]interface{}, schem // in a way that is different from how it is changed in current (e.g., deleting it, changing its // value). We also propagate values fields that do not exist in original but are explicitly // defined in modified. -func CreateThreeWayMergePatch(original, modified, current []byte, schema LookupPatchMeta, overwrite bool, fns ...mergepatch.PreconditionFunc) ([]byte, error) { +func CreateThreeWayMergePatch(original, modified, current []byte, dataStruct interface{}, overwrite bool, fns ...mergepatch.PreconditionFunc) ([]byte, error) { originalMap := map[string]interface{}{} if len(original) > 0 { if err := json.Unmarshal(original, &originalMap); err != nil { @@ -2018,6 +1989,11 @@ func CreateThreeWayMergePatch(original, modified, current []byte, schema LookupP } } + t, err := getTagStructType(dataStruct) + if err != nil { + return nil, err + } + // The patch is the difference from current to modified without deletions, plus deletions // from original to modified. To find it, we compute deletions, which are the deletions from // original to modified, and delta, which is the difference from current to modified without @@ -2026,7 +2002,7 @@ func CreateThreeWayMergePatch(original, modified, current []byte, schema LookupP IgnoreDeletions: true, SetElementOrder: true, } - deltaMap, err := diffMaps(currentMap, modifiedMap, schema, deltaMapDiffOptions) + deltaMap, err := diffMaps(currentMap, modifiedMap, t, deltaMapDiffOptions) if err != nil { return nil, err } @@ -2034,13 +2010,13 @@ func CreateThreeWayMergePatch(original, modified, current []byte, schema LookupP SetElementOrder: true, IgnoreChangesAndAdditions: true, } - deletionsMap, err := diffMaps(originalMap, modifiedMap, schema, deletionsMapDiffOptions) + deletionsMap, err := diffMaps(originalMap, modifiedMap, t, deletionsMapDiffOptions) if err != nil { return nil, err } mergeOptions := MergeOptions{} - patchMap, err := mergeMap(deletionsMap, deltaMap, schema, mergeOptions) + patchMap, err := mergeMap(deletionsMap, deltaMap, t, mergeOptions) if err != nil { return nil, err } @@ -2056,12 +2032,12 @@ func CreateThreeWayMergePatch(original, modified, current []byte, schema LookupP // then return a conflict error. if !overwrite { changeMapDiffOptions := DiffOptions{} - changedMap, err := diffMaps(originalMap, currentMap, schema, changeMapDiffOptions) + changedMap, err := diffMaps(originalMap, currentMap, t, changeMapDiffOptions) if err != nil { return nil, err } - hasConflicts, err := MergingMapsHaveConflicts(patchMap, changedMap, schema) + hasConflicts, err := MergingMapsHaveConflicts(patchMap, changedMap, dataStruct) if err != nil { return nil, err } diff --git a/k8s.io/apimachinery/pkg/util/strategicpatch/types.go b/k8s.io/apimachinery/pkg/util/strategicpatch/types.go deleted file mode 100644 index f84d65aa..00000000 --- a/k8s.io/apimachinery/pkg/util/strategicpatch/types.go +++ /dev/null @@ -1,193 +0,0 @@ -/* -Copyright 2017 The Kubernetes 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 strategicpatch - -import ( - "errors" - "strings" - - "k8s.io/apimachinery/pkg/util/mergepatch" - openapi "k8s.io/kube-openapi/pkg/util/proto" -) - -const ( - patchStrategyOpenapiextensionKey = "x-kubernetes-patch-strategy" - patchMergeKeyOpenapiextensionKey = "x-kubernetes-patch-merge-key" -) - -type LookupPatchItem interface { - openapi.SchemaVisitor - - Error() error - Path() *openapi.Path -} - -type kindItem struct { - key string - path *openapi.Path - err error - patchmeta PatchMeta - subschema openapi.Schema - hasVisitKind bool -} - -func NewKindItem(key string, path *openapi.Path) *kindItem { - return &kindItem{ - key: key, - path: path, - } -} - -var _ LookupPatchItem = &kindItem{} - -func (item *kindItem) Error() error { - return item.err -} - -func (item *kindItem) Path() *openapi.Path { - return item.path -} - -func (item *kindItem) VisitPrimitive(schema *openapi.Primitive) { - item.err = errors.New("expected kind, but got primitive") -} - -func (item *kindItem) VisitArray(schema *openapi.Array) { - item.err = errors.New("expected kind, but got slice") -} - -func (item *kindItem) VisitMap(schema *openapi.Map) { - item.err = errors.New("expected kind, but got map") -} - -func (item *kindItem) VisitReference(schema openapi.Reference) { - if !item.hasVisitKind { - schema.SubSchema().Accept(item) - } -} - -func (item *kindItem) VisitKind(schema *openapi.Kind) { - subschema, ok := schema.Fields[item.key] - if !ok { - item.err = FieldNotFoundError{Path: schema.GetPath().String(), Field: item.key} - return - } - - mergeKey, patchStrategies, err := parsePatchMetadata(subschema.GetExtensions()) - if err != nil { - item.err = err - return - } - item.patchmeta = PatchMeta{ - patchStrategies: patchStrategies, - patchMergeKey: mergeKey, - } - item.subschema = subschema -} - -type sliceItem struct { - key string - path *openapi.Path - err error - patchmeta PatchMeta - subschema openapi.Schema - hasVisitKind bool -} - -func NewSliceItem(key string, path *openapi.Path) *sliceItem { - return &sliceItem{ - key: key, - path: path, - } -} - -var _ LookupPatchItem = &sliceItem{} - -func (item *sliceItem) Error() error { - return item.err -} - -func (item *sliceItem) Path() *openapi.Path { - return item.path -} - -func (item *sliceItem) VisitPrimitive(schema *openapi.Primitive) { - item.err = errors.New("expected slice, but got primitive") -} - -func (item *sliceItem) VisitArray(schema *openapi.Array) { - if !item.hasVisitKind { - item.err = errors.New("expected visit kind first, then visit array") - } - subschema := schema.SubType - item.subschema = subschema -} - -func (item *sliceItem) VisitMap(schema *openapi.Map) { - item.err = errors.New("expected slice, but got map") -} - -func (item *sliceItem) VisitReference(schema openapi.Reference) { - if !item.hasVisitKind { - schema.SubSchema().Accept(item) - } else { - item.subschema = schema.SubSchema() - } -} - -func (item *sliceItem) VisitKind(schema *openapi.Kind) { - subschema, ok := schema.Fields[item.key] - if !ok { - item.err = FieldNotFoundError{Path: schema.GetPath().String(), Field: item.key} - return - } - - mergeKey, patchStrategies, err := parsePatchMetadata(subschema.GetExtensions()) - if err != nil { - item.err = err - return - } - item.patchmeta = PatchMeta{ - patchStrategies: patchStrategies, - patchMergeKey: mergeKey, - } - item.hasVisitKind = true - subschema.Accept(item) -} - -func parsePatchMetadata(extensions map[string]interface{}) (string, []string, error) { - ps, foundPS := extensions[patchStrategyOpenapiextensionKey] - var patchStrategies []string - var mergeKey, patchStrategy string - var ok bool - if foundPS { - patchStrategy, ok = ps.(string) - if ok { - patchStrategies = strings.Split(patchStrategy, ",") - } else { - return "", nil, mergepatch.ErrBadArgType(patchStrategy, ps) - } - } - mk, foundMK := extensions[patchMergeKeyOpenapiextensionKey] - if foundMK { - mergeKey, ok = mk.(string) - if !ok { - return "", nil, mergepatch.ErrBadArgType(mergeKey, mk) - } - } - return mergeKey, patchStrategies, nil -} diff --git a/k8s.io/apimachinery/pkg/watch/zz_generated.deepcopy.go b/k8s.io/apimachinery/pkg/watch/zz_generated.deepcopy.go index 738d0a29..322923d4 100644 --- a/k8s.io/apimachinery/pkg/watch/zz_generated.deepcopy.go +++ b/k8s.io/apimachinery/pkg/watch/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2018 The Kubernetes Authors. +Copyright 2017 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -20,6 +20,23 @@ limitations under the License. package watch +import ( + conversion "k8s.io/apimachinery/pkg/conversion" + reflect "reflect" +) + +// GetGeneratedDeepCopyFuncs returns the generated funcs, since we aren't registering them. +// +// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented. +func GetGeneratedDeepCopyFuncs() []conversion.GeneratedDeepCopyFunc { + return []conversion.GeneratedDeepCopyFunc{ + {Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { + in.(*Event).DeepCopyInto(out.(*Event)) + return nil + }, InType: reflect.TypeOf(&Event{})}, + } +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Event) DeepCopyInto(out *Event) { *out = *in diff --git a/k8s.io/apimachinery/third_party/forked/golang/json/fields.go b/k8s.io/apimachinery/third_party/forked/golang/json/fields.go index 8205a4dd..006972ec 100644 --- a/k8s.io/apimachinery/third_party/forked/golang/json/fields.go +++ b/k8s.io/apimachinery/third_party/forked/golang/json/fields.go @@ -26,14 +26,17 @@ const ( // struct field given the struct type and the JSON name of the field. // It returns field type, a slice of patch strategies, merge key and error. // TODO: fix the returned errors to be introspectable. -func LookupPatchMetadataForStruct(t reflect.Type, jsonField string) ( +func LookupPatchMetadata(t reflect.Type, jsonField string) ( elemType reflect.Type, patchStrategies []string, patchMergeKey string, e error) { if t.Kind() == reflect.Ptr { t = t.Elem() } - + if t.Kind() == reflect.Map { + elemType = t.Elem() + return + } if t.Kind() != reflect.Struct { - e = fmt.Errorf("merging an object in json but data type is not struct, instead is: %s", + e = fmt.Errorf("merging an object in json but data type is not map or struct, instead is: %s", t.Kind().String()) return } diff --git a/k8s.io/client-go/tools/cache/shared_informer.go b/k8s.io/client-go/tools/cache/shared_informer.go index b11f0ebd..9bc52a54 100644 --- a/k8s.io/client-go/tools/cache/shared_informer.go +++ b/k8s.io/client-go/tools/cache/shared_informer.go @@ -334,7 +334,7 @@ func (s *sharedIndexInformer) AddEventHandlerWithResyncPeriod(handler ResourceEv s.blockDeltas.Lock() defer s.blockDeltas.Unlock() - s.processor.addAndStartListener(listener) + s.processor.addListener(listener) for _, item := range s.indexer.List() { listener.add(addNotification{newObj: item}) } @@ -372,6 +372,7 @@ func (s *sharedIndexInformer) HandleDeltas(obj interface{}) error { } type sharedProcessor struct { + listenersStarted bool listenersLock sync.RWMutex listeners []*processorListener syncingListeners []*processorListener @@ -379,20 +380,15 @@ type sharedProcessor struct { wg wait.Group } -func (p *sharedProcessor) addAndStartListener(listener *processorListener) { - p.listenersLock.Lock() - defer p.listenersLock.Unlock() - - p.addListenerLocked(listener) - p.wg.Start(listener.run) - p.wg.Start(listener.pop) -} - func (p *sharedProcessor) addListener(listener *processorListener) { p.listenersLock.Lock() defer p.listenersLock.Unlock() p.addListenerLocked(listener) + if p.listenersStarted { + p.wg.Start(listener.run) + p.wg.Start(listener.pop) + } } func (p *sharedProcessor) addListenerLocked(listener *processorListener) { @@ -423,6 +419,7 @@ func (p *sharedProcessor) run(stopCh <-chan struct{}) { p.wg.Start(listener.run) p.wg.Start(listener.pop) } + p.listenersStarted = true }() <-stopCh p.listenersLock.RLock() diff --git a/k8s.io/helm/pkg/proto/hapi/chart/metadata.pb.go b/k8s.io/helm/pkg/proto/hapi/chart/metadata.pb.go index 49a4aa0a..9daeaa9e 100644 --- a/k8s.io/helm/pkg/proto/hapi/chart/metadata.pb.go +++ b/k8s.io/helm/pkg/proto/hapi/chart/metadata.pb.go @@ -107,7 +107,7 @@ type Metadata struct { // Annotations are additional mappings uninterpreted by Tiller, // made available for inspection by other applications. Annotations map[string]string `protobuf:"bytes,16,rep,name=annotations" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - // KubeVersion is a SemVer constraints on what version of Kubernetes is required. + // KubeVersion is a SemVer constraint specifying the version of Kubernetes required. KubeVersion string `protobuf:"bytes,17,opt,name=kubeVersion" json:"kubeVersion,omitempty"` } @@ -244,32 +244,33 @@ func init() { func init() { proto.RegisterFile("hapi/chart/metadata.proto", fileDescriptor2) } var fileDescriptor2 = []byte{ - // 427 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x52, 0x5d, 0x6b, 0xdb, 0x30, - 0x14, 0x9d, 0x9b, 0x38, 0x89, 0xaf, 0xd7, 0xcd, 0xbb, 0x8c, 0xa2, 0x95, 0x31, 0x4c, 0xd8, 0x20, - 0x4f, 0x29, 0x6c, 0x30, 0xca, 0x1e, 0x06, 0x1b, 0x94, 0x3e, 0x6c, 0x4d, 0x87, 0xd9, 0x07, 0xec, - 0x4d, 0xb5, 0x2f, 0x8d, 0x48, 0x2c, 0x19, 0x49, 0xe9, 0xc8, 0xaf, 0xd8, 0x5f, 0x1e, 0x92, 0xad, - 0xda, 0x19, 0x7d, 0xbb, 0xe7, 0x1c, 0xdd, 0x23, 0x1d, 0xdd, 0x0b, 0x2f, 0xd6, 0xbc, 0x11, 0x67, - 0xe5, 0x9a, 0x6b, 0x7b, 0x56, 0x93, 0xe5, 0x15, 0xb7, 0x7c, 0xd9, 0x68, 0x65, 0x15, 0x82, 0x93, - 0x96, 0x5e, 0x9a, 0xbf, 0x07, 0xb8, 0xe2, 0x42, 0x5a, 0x2e, 0x24, 0x69, 0x44, 0x18, 0x4b, 0x5e, - 0x13, 0x8b, 0xf2, 0x68, 0x91, 0x14, 0xbe, 0xc6, 0xe7, 0x10, 0x53, 0xcd, 0xc5, 0x96, 0x1d, 0x79, - 0xb2, 0x05, 0xf3, 0xbf, 0x31, 0xcc, 0xae, 0x3a, 0xdb, 0x07, 0xdb, 0x10, 0xc6, 0x6b, 0x55, 0x53, - 0xd7, 0xe5, 0x6b, 0x64, 0x30, 0x35, 0x6a, 0xa7, 0x4b, 0x32, 0x6c, 0x94, 0x8f, 0x16, 0x49, 0x11, - 0xa0, 0x53, 0xee, 0x48, 0x1b, 0xa1, 0x24, 0x1b, 0xfb, 0x86, 0x00, 0x31, 0x87, 0xb4, 0x22, 0x53, - 0x6a, 0xd1, 0x58, 0xa7, 0xc6, 0x5e, 0x1d, 0x52, 0x78, 0x0a, 0xb3, 0x0d, 0xed, 0xff, 0x28, 0x5d, - 0x19, 0x36, 0xf1, 0xb6, 0xf7, 0x18, 0xcf, 0x21, 0xad, 0xef, 0xe3, 0x19, 0x36, 0xcd, 0x47, 0x8b, - 0xf4, 0xed, 0xc9, 0xb2, 0xff, 0x80, 0x65, 0x9f, 0xbe, 0x18, 0x1e, 0xc5, 0x13, 0x98, 0x90, 0xbc, - 0x15, 0x92, 0xd8, 0xcc, 0x5f, 0xd9, 0x21, 0x97, 0x4b, 0x94, 0x4a, 0xb2, 0xa4, 0xcd, 0xe5, 0x6a, - 0x7c, 0x05, 0xc0, 0x1b, 0xf1, 0xb3, 0x0b, 0x00, 0x5e, 0x19, 0x30, 0xf8, 0x12, 0x92, 0x52, 0xc9, - 0x4a, 0xf8, 0x04, 0xa9, 0x97, 0x7b, 0xc2, 0x39, 0x5a, 0x7e, 0x6b, 0xd8, 0xe3, 0xd6, 0xd1, 0xd5, - 0xad, 0x63, 0x13, 0x1c, 0x8f, 0x83, 0x63, 0x60, 0x9c, 0x5e, 0x51, 0xa3, 0xa9, 0xe4, 0x96, 0x2a, - 0xf6, 0x24, 0x8f, 0x16, 0xb3, 0x62, 0xc0, 0xe0, 0x6b, 0x38, 0xb6, 0x62, 0xbb, 0x25, 0x1d, 0x2c, - 0x9e, 0x7a, 0x8b, 0x43, 0x12, 0x2f, 0x21, 0xe5, 0x52, 0x2a, 0xcb, 0xdd, 0x3b, 0x0c, 0xcb, 0xfc, - 0xef, 0xbc, 0x39, 0xf8, 0x9d, 0xb0, 0x39, 0x9f, 0xfa, 0x73, 0x17, 0xd2, 0xea, 0x7d, 0x31, 0xec, - 0x74, 0x43, 0xda, 0xec, 0x6e, 0x28, 0x5c, 0xf6, 0xac, 0x1d, 0xd2, 0x80, 0x3a, 0xfd, 0x08, 0xd9, - 0xff, 0x16, 0x98, 0xc1, 0x68, 0x43, 0xfb, 0x6e, 0x6b, 0x5c, 0xe9, 0x76, 0xed, 0x8e, 0x6f, 0x77, - 0x61, 0x6b, 0x5a, 0xf0, 0xe1, 0xe8, 0x3c, 0x9a, 0xe7, 0x30, 0xb9, 0x68, 0x07, 0x90, 0xc2, 0xf4, - 0xc7, 0xea, 0xcb, 0xea, 0xfa, 0xd7, 0x2a, 0x7b, 0x84, 0x09, 0xc4, 0x97, 0xd7, 0xdf, 0xbf, 0x7d, - 0xcd, 0xa2, 0xcf, 0xd3, 0xdf, 0xb1, 0x7f, 0xf3, 0xcd, 0xc4, 0x6f, 0xf9, 0xbb, 0x7f, 0x01, 0x00, - 0x00, 0xff, 0xff, 0x7f, 0xc1, 0xec, 0x3d, 0x02, 0x03, 0x00, 0x00, + // 435 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x52, 0x5d, 0x6b, 0xd4, 0x40, + 0x14, 0x35, 0xcd, 0x66, 0x77, 0x73, 0x63, 0x35, 0x0e, 0x52, 0xc6, 0x22, 0x12, 0x16, 0x85, 0x7d, + 0xda, 0x82, 0xbe, 0x14, 0x1f, 0x04, 0x85, 0x52, 0x41, 0xbb, 0x95, 0xe0, 0x07, 0xf8, 0x36, 0x4d, + 0x2e, 0xdd, 0x61, 0x93, 0x99, 0x30, 0x99, 0xad, 0xec, 0xaf, 0xf0, 0x2f, 0xcb, 0xdc, 0x64, 0x9a, + 0xac, 0xf4, 0xed, 0x9e, 0x73, 0x66, 0xce, 0xcc, 0xbd, 0xf7, 0xc0, 0x8b, 0x8d, 0x68, 0xe4, 0x59, + 0xb1, 0x11, 0xc6, 0x9e, 0xd5, 0x68, 0x45, 0x29, 0xac, 0x58, 0x35, 0x46, 0x5b, 0xcd, 0xc0, 0x49, + 0x2b, 0x92, 0x16, 0x9f, 0x01, 0xae, 0x84, 0x54, 0x56, 0x48, 0x85, 0x86, 0x31, 0x98, 0x28, 0x51, + 0x23, 0x0f, 0xb2, 0x60, 0x19, 0xe7, 0x54, 0xb3, 0xe7, 0x10, 0x61, 0x2d, 0x64, 0xc5, 0x8f, 0x88, + 0xec, 0x00, 0x4b, 0x21, 0xdc, 0x99, 0x8a, 0x87, 0xc4, 0xb9, 0x72, 0xf1, 0x37, 0x82, 0xf9, 0x55, + 0xff, 0xd0, 0x83, 0x46, 0x0c, 0x26, 0x1b, 0x5d, 0x63, 0xef, 0x43, 0x35, 0xe3, 0x30, 0x6b, 0xf5, + 0xce, 0x14, 0xd8, 0xf2, 0x30, 0x0b, 0x97, 0x71, 0xee, 0xa1, 0x53, 0xee, 0xd0, 0xb4, 0x52, 0x2b, + 0x3e, 0xa1, 0x0b, 0x1e, 0xb2, 0x0c, 0x92, 0x12, 0xdb, 0xc2, 0xc8, 0xc6, 0x3a, 0x35, 0x22, 0x75, + 0x4c, 0xb1, 0x53, 0x98, 0x6f, 0x71, 0xff, 0x47, 0x9b, 0xb2, 0xe5, 0x53, 0xb2, 0xbd, 0xc7, 0xec, + 0x1c, 0x92, 0xfa, 0xbe, 0xe1, 0x96, 0xcf, 0xb2, 0x70, 0x99, 0xbc, 0x3d, 0x59, 0x0d, 0x23, 0x59, + 0x0d, 0xf3, 0xc8, 0xc7, 0x47, 0xd9, 0x09, 0x4c, 0x51, 0xdd, 0x4a, 0x85, 0x7c, 0x4e, 0x4f, 0xf6, + 0xc8, 0xf5, 0x25, 0x0b, 0xad, 0x78, 0xdc, 0xf5, 0xe5, 0x6a, 0xf6, 0x0a, 0x40, 0x34, 0xf2, 0x67, + 0xdf, 0x00, 0x90, 0x32, 0x62, 0xd8, 0x4b, 0x88, 0x0b, 0xad, 0x4a, 0x49, 0x1d, 0x24, 0x24, 0x0f, + 0x84, 0x73, 0xb4, 0xe2, 0xb6, 0xe5, 0x8f, 0x3b, 0x47, 0x57, 0x77, 0x8e, 0x8d, 0x77, 0x3c, 0xf6, + 0x8e, 0x9e, 0x71, 0x7a, 0x89, 0x8d, 0xc1, 0x42, 0x58, 0x2c, 0xf9, 0x93, 0x2c, 0x58, 0xce, 0xf3, + 0x11, 0xc3, 0x5e, 0xc3, 0xb1, 0x95, 0x55, 0x85, 0xc6, 0x5b, 0x3c, 0x25, 0x8b, 0x43, 0x92, 0x5d, + 0x42, 0x22, 0x94, 0xd2, 0x56, 0xb8, 0x7f, 0xb4, 0x3c, 0xa5, 0xe9, 0xbc, 0x39, 0x98, 0x8e, 0xcf, + 0xd2, 0xc7, 0xe1, 0xdc, 0x85, 0xb2, 0x66, 0x9f, 0x8f, 0x6f, 0xba, 0x25, 0x6d, 0x77, 0x37, 0xe8, + 0x1f, 0x7b, 0xd6, 0x2d, 0x69, 0x44, 0x9d, 0x7e, 0x80, 0xf4, 0x7f, 0x0b, 0x97, 0xaa, 0x2d, 0xee, + 0xfb, 0xd4, 0xb8, 0xd2, 0xa5, 0xef, 0x4e, 0x54, 0x3b, 0x9f, 0x9a, 0x0e, 0xbc, 0x3f, 0x3a, 0x0f, + 0x16, 0x19, 0x4c, 0x2f, 0xba, 0x05, 0x24, 0x30, 0xfb, 0xb1, 0xfe, 0xb2, 0xbe, 0xfe, 0xb5, 0x4e, + 0x1f, 0xb1, 0x18, 0xa2, 0xcb, 0xeb, 0xef, 0xdf, 0xbe, 0xa6, 0xc1, 0xa7, 0xd9, 0xef, 0x88, 0xfe, + 0x7c, 0x33, 0xa5, 0xdc, 0xbf, 0xfb, 0x17, 0x00, 0x00, 0xff, 0xff, 0x36, 0xf9, 0x0d, 0xa6, 0x14, + 0x03, 0x00, 0x00, } diff --git a/k8s.io/kube-openapi/pkg/util/proto/document.go b/k8s.io/kube-openapi/pkg/util/proto/document.go deleted file mode 100644 index 61dbf4fc..00000000 --- a/k8s.io/kube-openapi/pkg/util/proto/document.go +++ /dev/null @@ -1,285 +0,0 @@ -/* -Copyright 2017 The Kubernetes 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 proto - -import ( - "fmt" - "sort" - "strings" - - openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2" - yaml "gopkg.in/yaml.v2" -) - -func newSchemaError(path *Path, format string, a ...interface{}) error { - err := fmt.Sprintf(format, a...) - if path.Len() == 0 { - return fmt.Errorf("SchemaError: %v", err) - } - return fmt.Errorf("SchemaError(%v): %v", path, err) -} - -// VendorExtensionToMap converts openapi VendorExtension to a map. -func VendorExtensionToMap(e []*openapi_v2.NamedAny) map[string]interface{} { - values := map[string]interface{}{} - - for _, na := range e { - if na.GetName() == "" || na.GetValue() == nil { - continue - } - if na.GetValue().GetYaml() == "" { - continue - } - var value interface{} - err := yaml.Unmarshal([]byte(na.GetValue().GetYaml()), &value) - if err != nil { - continue - } - - values[na.GetName()] = value - } - - return values -} - -// Definitions is an implementation of `Models`. It looks for -// models in an openapi Schema. -type Definitions struct { - models map[string]Schema -} - -var _ Models = &Definitions{} - -// NewOpenAPIData creates a new `Models` out of the openapi document. -func NewOpenAPIData(doc *openapi_v2.Document) (Models, error) { - definitions := Definitions{ - models: map[string]Schema{}, - } - - // Save the list of all models first. This will allow us to - // validate that we don't have any dangling reference. - for _, namedSchema := range doc.GetDefinitions().GetAdditionalProperties() { - definitions.models[namedSchema.GetName()] = nil - } - - // Now, parse each model. We can validate that references exists. - for _, namedSchema := range doc.GetDefinitions().GetAdditionalProperties() { - path := NewPath(namedSchema.GetName()) - schema, err := definitions.ParseSchema(namedSchema.GetValue(), &path) - if err != nil { - return nil, err - } - definitions.models[namedSchema.GetName()] = schema - } - - return &definitions, nil -} - -// We believe the schema is a reference, verify that and returns a new -// Schema -func (d *Definitions) parseReference(s *openapi_v2.Schema, path *Path) (Schema, error) { - if len(s.GetProperties().GetAdditionalProperties()) > 0 { - return nil, newSchemaError(path, "unallowed embedded type definition") - } - if len(s.GetType().GetValue()) > 0 { - return nil, newSchemaError(path, "definition reference can't have a type") - } - - if !strings.HasPrefix(s.GetXRef(), "#/definitions/") { - return nil, newSchemaError(path, "unallowed reference to non-definition %q", s.GetXRef()) - } - reference := strings.TrimPrefix(s.GetXRef(), "#/definitions/") - if _, ok := d.models[reference]; !ok { - return nil, newSchemaError(path, "unknown model in reference: %q", reference) - } - return &Ref{ - BaseSchema: d.parseBaseSchema(s, path), - reference: reference, - definitions: d, - }, nil -} - -func (d *Definitions) parseBaseSchema(s *openapi_v2.Schema, path *Path) BaseSchema { - return BaseSchema{ - Description: s.GetDescription(), - Extensions: VendorExtensionToMap(s.GetVendorExtension()), - Path: *path, - } -} - -// We believe the schema is a map, verify and return a new schema -func (d *Definitions) parseMap(s *openapi_v2.Schema, path *Path) (Schema, error) { - if len(s.GetType().GetValue()) != 0 && s.GetType().GetValue()[0] != object { - return nil, newSchemaError(path, "invalid object type") - } - if s.GetAdditionalProperties().GetSchema() == nil { - return nil, newSchemaError(path, "invalid object doesn't have additional properties") - } - sub, err := d.ParseSchema(s.GetAdditionalProperties().GetSchema(), path) - if err != nil { - return nil, err - } - return &Map{ - BaseSchema: d.parseBaseSchema(s, path), - SubType: sub, - }, nil -} - -func (d *Definitions) parsePrimitive(s *openapi_v2.Schema, path *Path) (Schema, error) { - var t string - if len(s.GetType().GetValue()) > 1 { - return nil, newSchemaError(path, "primitive can't have more than 1 type") - } - if len(s.GetType().GetValue()) == 1 { - t = s.GetType().GetValue()[0] - } - switch t { - case String: - case Number: - case Integer: - case Boolean: - case "": // Some models are completely empty, and can be safely ignored. - // Do nothing - default: - return nil, newSchemaError(path, "Unknown primitive type: %q", t) - } - return &Primitive{ - BaseSchema: d.parseBaseSchema(s, path), - Type: t, - Format: s.GetFormat(), - }, nil -} - -func (d *Definitions) parseArray(s *openapi_v2.Schema, path *Path) (Schema, error) { - if len(s.GetType().GetValue()) != 1 { - return nil, newSchemaError(path, "array should have exactly one type") - } - if s.GetType().GetValue()[0] != array { - return nil, newSchemaError(path, `array should have type "array"`) - } - if len(s.GetItems().GetSchema()) != 1 { - return nil, newSchemaError(path, "array should have exactly one sub-item") - } - sub, err := d.ParseSchema(s.GetItems().GetSchema()[0], path) - if err != nil { - return nil, err - } - return &Array{ - BaseSchema: d.parseBaseSchema(s, path), - SubType: sub, - }, nil -} - -func (d *Definitions) parseKind(s *openapi_v2.Schema, path *Path) (Schema, error) { - if len(s.GetType().GetValue()) != 0 && s.GetType().GetValue()[0] != object { - return nil, newSchemaError(path, "invalid object type") - } - if s.GetProperties() == nil { - return nil, newSchemaError(path, "object doesn't have properties") - } - - fields := map[string]Schema{} - - for _, namedSchema := range s.GetProperties().GetAdditionalProperties() { - var err error - path := path.FieldPath(namedSchema.GetName()) - fields[namedSchema.GetName()], err = d.ParseSchema(namedSchema.GetValue(), &path) - if err != nil { - return nil, err - } - } - - return &Kind{ - BaseSchema: d.parseBaseSchema(s, path), - RequiredFields: s.GetRequired(), - Fields: fields, - }, nil -} - -func (d *Definitions) parseArbitrary(s *openapi_v2.Schema, path *Path) (Schema, error) { - return &Arbitrary{ - BaseSchema: d.parseBaseSchema(s, path), - }, nil -} - -// ParseSchema creates a walkable Schema from an openapi schema. While -// this function is public, it doesn't leak through the interface. -func (d *Definitions) ParseSchema(s *openapi_v2.Schema, path *Path) (Schema, error) { - objectTypes := s.GetType().GetValue() - if len(objectTypes) == 1 { - t := objectTypes[0] - switch t { - case object: - return d.parseMap(s, path) - case array: - return d.parseArray(s, path) - } - - } - if s.GetXRef() != "" { - return d.parseReference(s, path) - } - if s.GetProperties() != nil { - return d.parseKind(s, path) - } - if len(objectTypes) == 0 || (len(objectTypes) == 1 && objectTypes[0] == "") { - return d.parseArbitrary(s, path) - } - return d.parsePrimitive(s, path) -} - -// LookupModel is public through the interface of Models. It -// returns a visitable schema from the given model name. -func (d *Definitions) LookupModel(model string) Schema { - return d.models[model] -} - -func (d *Definitions) ListModels() []string { - models := []string{} - - for model := range d.models { - models = append(models, model) - } - - sort.Strings(models) - return models -} - -type Ref struct { - BaseSchema - - reference string - definitions *Definitions -} - -var _ Reference = &Ref{} - -func (r *Ref) Reference() string { - return r.reference -} - -func (r *Ref) SubSchema() Schema { - return r.definitions.models[r.reference] -} - -func (r *Ref) Accept(v SchemaVisitor) { - v.VisitReference(r) -} - -func (r *Ref) GetName() string { - return fmt.Sprintf("Reference to %q", r.reference) -} diff --git a/k8s.io/kube-openapi/pkg/util/proto/openapi.go b/k8s.io/kube-openapi/pkg/util/proto/openapi.go deleted file mode 100644 index b48e62c3..00000000 --- a/k8s.io/kube-openapi/pkg/util/proto/openapi.go +++ /dev/null @@ -1,276 +0,0 @@ -/* -Copyright 2017 The Kubernetes 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 proto - -import ( - "fmt" - "sort" - "strings" -) - -// Defines openapi types. -const ( - Integer = "integer" - Number = "number" - String = "string" - Boolean = "boolean" - - // These types are private as they should never leak, and are - // represented by actual structs. - array = "array" - object = "object" -) - -// Models interface describe a model provider. They can give you the -// schema for a specific model. -type Models interface { - LookupModel(string) Schema - ListModels() []string -} - -// SchemaVisitor is an interface that you need to implement if you want -// to "visit" an openapi schema. A dispatch on the Schema type will call -// the appropriate function based on its actual type: -// - Array is a list of one and only one given subtype -// - Map is a map of string to one and only one given subtype -// - Primitive can be string, integer, number and boolean. -// - Kind is an object with specific fields mapping to specific types. -// - Reference is a link to another definition. -type SchemaVisitor interface { - VisitArray(*Array) - VisitMap(*Map) - VisitPrimitive(*Primitive) - VisitKind(*Kind) - VisitReference(Reference) -} - -// SchemaVisitorArbitrary is an additional visitor interface which handles -// arbitrary types. For backwards compatability, it's a separate interface -// which is checked for at runtime. -type SchemaVisitorArbitrary interface { - SchemaVisitor - VisitArbitrary(*Arbitrary) -} - -// Schema is the base definition of an openapi type. -type Schema interface { - // Giving a visitor here will let you visit the actual type. - Accept(SchemaVisitor) - - // Pretty print the name of the type. - GetName() string - // Describes how to access this field. - GetPath() *Path - // Describes the field. - GetDescription() string - // Returns type extensions. - GetExtensions() map[string]interface{} -} - -// Path helps us keep track of type paths -type Path struct { - parent *Path - key string -} - -func NewPath(key string) Path { - return Path{key: key} -} - -func (p *Path) Get() []string { - if p == nil { - return []string{} - } - if p.key == "" { - return p.parent.Get() - } - return append(p.parent.Get(), p.key) -} - -func (p *Path) Len() int { - return len(p.Get()) -} - -func (p *Path) String() string { - return strings.Join(p.Get(), "") -} - -// ArrayPath appends an array index and creates a new path -func (p *Path) ArrayPath(i int) Path { - return Path{ - parent: p, - key: fmt.Sprintf("[%d]", i), - } -} - -// FieldPath appends a field name and creates a new path -func (p *Path) FieldPath(field string) Path { - return Path{ - parent: p, - key: fmt.Sprintf(".%s", field), - } -} - -// BaseSchema holds data used by each types of schema. -type BaseSchema struct { - Description string - Extensions map[string]interface{} - - Path Path -} - -func (b *BaseSchema) GetDescription() string { - return b.Description -} - -func (b *BaseSchema) GetExtensions() map[string]interface{} { - return b.Extensions -} - -func (b *BaseSchema) GetPath() *Path { - return &b.Path -} - -// Array must have all its element of the same `SubType`. -type Array struct { - BaseSchema - - SubType Schema -} - -var _ Schema = &Array{} - -func (a *Array) Accept(v SchemaVisitor) { - v.VisitArray(a) -} - -func (a *Array) GetName() string { - return fmt.Sprintf("Array of %s", a.SubType.GetName()) -} - -// Kind is a complex object. It can have multiple different -// subtypes for each field, as defined in the `Fields` field. Mandatory -// fields are listed in `RequiredFields`. The key of the object is -// always of type `string`. -type Kind struct { - BaseSchema - - // Lists names of required fields. - RequiredFields []string - // Maps field names to types. - Fields map[string]Schema -} - -var _ Schema = &Kind{} - -func (k *Kind) Accept(v SchemaVisitor) { - v.VisitKind(k) -} - -func (k *Kind) GetName() string { - properties := []string{} - for key := range k.Fields { - properties = append(properties, key) - } - return fmt.Sprintf("Kind(%v)", properties) -} - -// IsRequired returns true if `field` is a required field for this type. -func (k *Kind) IsRequired(field string) bool { - for _, f := range k.RequiredFields { - if f == field { - return true - } - } - return false -} - -// Keys returns a alphabetically sorted list of keys. -func (k *Kind) Keys() []string { - keys := make([]string, 0) - for key := range k.Fields { - keys = append(keys, key) - } - sort.Strings(keys) - return keys -} - -// Map is an object who values must all be of the same `SubType`. -// The key of the object is always of type `string`. -type Map struct { - BaseSchema - - SubType Schema -} - -var _ Schema = &Map{} - -func (m *Map) Accept(v SchemaVisitor) { - v.VisitMap(m) -} - -func (m *Map) GetName() string { - return fmt.Sprintf("Map of %s", m.SubType.GetName()) -} - -// Primitive is a literal. There can be multiple types of primitives, -// and this subtype can be visited through the `subType` field. -type Primitive struct { - BaseSchema - - // Type of a primitive must be one of: integer, number, string, boolean. - Type string - Format string -} - -var _ Schema = &Primitive{} - -func (p *Primitive) Accept(v SchemaVisitor) { - v.VisitPrimitive(p) -} - -func (p *Primitive) GetName() string { - if p.Format == "" { - return p.Type - } - return fmt.Sprintf("%s (%s)", p.Type, p.Format) -} - -// Arbitrary is a value of any type (primitive, object or array) -type Arbitrary struct { - BaseSchema -} - -var _ Schema = &Arbitrary{} - -func (a *Arbitrary) Accept(v SchemaVisitor) { - if visitor, ok := v.(SchemaVisitorArbitrary); ok { - visitor.VisitArbitrary(a) - } -} - -func (a *Arbitrary) GetName() string { - return "Arbitrary value (primitive, object or array)" -} - -// Reference implementation depends on the type of document. -type Reference interface { - Schema - - Reference() string - SubSchema() Schema -} diff --git a/k8s.io/kubernetes/pkg/apis/core/v1/conversion.go b/k8s.io/kubernetes/pkg/apis/core/v1/conversion.go index 8f6e09b6..4ecab6b6 100644 --- a/k8s.io/kubernetes/pkg/apis/core/v1/conversion.go +++ b/k8s.io/kubernetes/pkg/apis/core/v1/conversion.go @@ -349,6 +349,10 @@ func Convert_core_PodTemplateSpec_To_v1_PodTemplateSpec(in *core.PodTemplateSpec return err } + // drop init container annotations so they don't take effect on legacy kubelets. + // remove this once the oldest supported kubelet no longer honors the annotations over the field. + out.Annotations = dropInitContainerAnnotations(out.Annotations) + return nil } @@ -357,6 +361,9 @@ func Convert_v1_PodTemplateSpec_To_core_PodTemplateSpec(in *v1.PodTemplateSpec, return err } + // drop init container annotations so they don't show up as differences when receiving requests from old clients + out.Annotations = dropInitContainerAnnotations(out.Annotations) + return nil } @@ -404,6 +411,17 @@ func Convert_v1_PodSpec_To_core_PodSpec(in *v1.PodSpec, out *core.PodSpec, s con return nil } +func Convert_v1_Pod_To_core_Pod(in *v1.Pod, out *core.Pod, s conversion.Scope) error { + if err := autoConvert_v1_Pod_To_core_Pod(in, out, s); err != nil { + return err + } + + // drop init container annotations so they don't show up as differences when receiving requests from old clients + out.Annotations = dropInitContainerAnnotations(out.Annotations) + + return nil +} + func Convert_core_Pod_To_v1_Pod(in *core.Pod, out *v1.Pod, s conversion.Scope) error { if err := autoConvert_core_Pod_To_v1_Pod(in, out, s); err != nil { return err @@ -411,17 +429,7 @@ func Convert_core_Pod_To_v1_Pod(in *core.Pod, out *v1.Pod, s conversion.Scope) e // drop init container annotations so they don't take effect on legacy kubelets. // remove this once the oldest supported kubelet no longer honors the annotations over the field. - if len(out.Annotations) > 0 { - old := out.Annotations - out.Annotations = make(map[string]string, len(old)) - for k, v := range old { - out.Annotations[k] = v - } - delete(out.Annotations, "pod.beta.kubernetes.io/init-containers") - delete(out.Annotations, "pod.alpha.kubernetes.io/init-containers") - delete(out.Annotations, "pod.beta.kubernetes.io/init-container-statuses") - delete(out.Annotations, "pod.alpha.kubernetes.io/init-container-statuses") - } + out.Annotations = dropInitContainerAnnotations(out.Annotations) return nil } @@ -569,3 +577,40 @@ func AddFieldLabelConversionsForSecret(scheme *runtime.Scheme) error { } }) } + +var initContainerAnnotations = map[string]bool{ + "pod.beta.kubernetes.io/init-containers": true, + "pod.alpha.kubernetes.io/init-containers": true, + "pod.beta.kubernetes.io/init-container-statuses": true, + "pod.alpha.kubernetes.io/init-container-statuses": true, +} + +// dropInitContainerAnnotations returns a copy of the annotations with init container annotations removed, +// or the original annotations if no init container annotations were present. +// +// this can be removed once no clients prior to 1.8 are supported, and no kubelets prior to 1.8 can be run +// (we don't support kubelets older than 2 versions skewed from the apiserver, but we don't prevent them, either) +func dropInitContainerAnnotations(oldAnnotations map[string]string) map[string]string { + if len(oldAnnotations) == 0 { + return oldAnnotations + } + + found := false + for k := range initContainerAnnotations { + if _, ok := oldAnnotations[k]; ok { + found = true + break + } + } + if !found { + return oldAnnotations + } + + newAnnotations := make(map[string]string, len(oldAnnotations)) + for k, v := range oldAnnotations { + if !initContainerAnnotations[k] { + newAnnotations[k] = v + } + } + return newAnnotations +} diff --git a/k8s.io/kubernetes/pkg/apis/core/v1/zz_generated.conversion.go b/k8s.io/kubernetes/pkg/apis/core/v1/zz_generated.conversion.go index cb878bf4..a71f0d56 100644 --- a/k8s.io/kubernetes/pkg/apis/core/v1/zz_generated.conversion.go +++ b/k8s.io/kubernetes/pkg/apis/core/v1/zz_generated.conversion.go @@ -3395,11 +3395,6 @@ func autoConvert_v1_Pod_To_core_Pod(in *v1.Pod, out *core.Pod, s conversion.Scop return nil } -// Convert_v1_Pod_To_core_Pod is an autogenerated conversion function. -func Convert_v1_Pod_To_core_Pod(in *v1.Pod, out *core.Pod, s conversion.Scope) error { - return autoConvert_v1_Pod_To_core_Pod(in, out, s) -} - func autoConvert_core_Pod_To_v1_Pod(in *core.Pod, out *v1.Pod, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta if err := Convert_core_PodSpec_To_v1_PodSpec(&in.Spec, &out.Spec, s); err != nil { diff --git a/k8s.io/kubernetes/pkg/features/kube_features.go b/k8s.io/kubernetes/pkg/features/kube_features.go index a4f66b84..fbe2a010 100644 --- a/k8s.io/kubernetes/pkg/features/kube_features.go +++ b/k8s.io/kubernetes/pkg/features/kube_features.go @@ -226,6 +226,13 @@ const ( // Mount secret, configMap, downwardAPI and projected volumes ReadOnly. Note: this feature // gate is present only for backward compatability, it will be removed in the 1.11 release. ReadOnlyAPIDataVolumes utilfeature.Feature = "ReadOnlyAPIDataVolumes" + + // owner: @saad-ali + // ga + // + // Allow mounting a subpath of a volume in a container + // Do not remove this feature gate even though it's GA + VolumeSubpath utilfeature.Feature = "VolumeSubpath" ) func init() { @@ -266,6 +273,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS PVCProtection: {Default: false, PreRelease: utilfeature.Alpha}, ResourceLimitsPriorityFunction: {Default: false, PreRelease: utilfeature.Alpha}, SupportIPVSProxyMode: {Default: false, PreRelease: utilfeature.Beta}, + VolumeSubpath: {Default: true, PreRelease: utilfeature.GA}, // inherited features from generic apiserver, relisted here to get a conflict if it is changed // unintentionally on either side: