diff --git a/go.mod b/go.mod index 99d19b06c83..9b899fc23ae 100644 --- a/go.mod +++ b/go.mod @@ -6,20 +6,20 @@ replace cloud.google.com/go/meshtelemetry/v1alpha1 v0.0.0 => ./test/envoye2e/sta require ( cloud.google.com/go/meshtelemetry/v1alpha1 v0.0.0 - github.com/cncf/udpa/go v0.0.0-20200327203949-e8cd3a4bb307 + github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354 github.com/d4l3k/messagediff v1.2.2-0.20180726183240-b9e99b2f9263 - github.com/envoyproxy/go-control-plane v0.9.5 + github.com/envoyproxy/go-control-plane v0.9.7-0.20200813173324-b603f568eca7 + github.com/fsnotify/fsnotify v1.4.9 github.com/ghodss/yaml v1.0.0 - github.com/golang/protobuf v1.4.1 + github.com/golang/protobuf v1.4.2 github.com/kr/pretty v0.1.0 // indirect github.com/prometheus/client_model v0.2.0 github.com/prometheus/common v0.9.1 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect golang.org/x/sys v0.0.0-20200331124033-c3d80250170d // indirect - golang.org/x/text v0.3.2 // indirect google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 google.golang.org/grpc v1.28.0 google.golang.org/protobuf v1.25.0 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect - gopkg.in/yaml.v2 v2.2.8 // indirect + gopkg.in/yaml.v2 v2.2.8 ) diff --git a/go.sum b/go.sum index 9c58540a3b8..ba489904016 100644 --- a/go.sum +++ b/go.sum @@ -12,23 +12,22 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200313221541-5f7e5dd04533 h1:8wZizuKuZVu5COB7EsBYxBQz8nRcXXn5d4Gt91eJLvU= -github.com/cncf/udpa/go v0.0.0-20200313221541-5f7e5dd04533/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20200327203949-e8cd3a4bb307 h1:wP75JfNoHgEnmT+77wAUNQ2shW0sK83RPDQIvYIz47E= -github.com/cncf/udpa/go v0.0.0-20200327203949-e8cd3a4bb307/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354 h1:9kRtNpqLHbZVO/NNxhHp2ymxFxsHOe3x2efJGn//Tas= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/d4l3k/messagediff v1.2.2-0.20180726183240-b9e99b2f9263 h1:Ot817IZ8L+/ZlkfVJ0ZnngYA6GnmcvcxR7lrIz/iZDc= github.com/d4l3k/messagediff v1.2.2-0.20180726183240-b9e99b2f9263/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0 h1:67WMNTvGrl7V1dWdKCeTwxDr7nio9clKoTlLhwIPnT4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.5 h1:lRJIqDD8yjV1YyPRqecMdytjDLs2fTXq363aCib5xPU= -github.com/envoyproxy/go-control-plane v0.9.5/go.mod h1:OXl5to++W0ctG+EHWTFUjiypVxC/Y4VLc/KFU+al13s= +github.com/envoyproxy/go-control-plane v0.9.7-0.20200813173324-b603f568eca7 h1:o1sRFwWsIgDAy8NnjYMyskkiFSJnt/S3ex7zkOunHao= +github.com/envoyproxy/go-control-plane v0.9.7-0.20200813173324-b603f568eca7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -54,6 +53,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -105,6 +106,8 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -136,14 +139,12 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -159,7 +160,6 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -172,6 +172,7 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= @@ -181,6 +182,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= diff --git a/test/envoye2e/driver/scenario.go b/test/envoye2e/driver/scenario.go index df87d68b400..bceab40f188 100644 --- a/test/envoye2e/driver/scenario.go +++ b/test/envoye2e/driver/scenario.go @@ -18,15 +18,16 @@ import ( "bytes" "fmt" "log" + "reflect" "strings" "testing" "text/template" "time" - "github.com/envoyproxy/go-control-plane/pkg/cache/v3" "github.com/ghodss/yaml" "github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/proto" + yamlv2 "gopkg.in/yaml.v2" "istio.io/proxy/test/envoye2e/env" ) @@ -34,7 +35,7 @@ import ( type ( Params struct { XDS int - Config cache.SnapshotCache + Config XDSServer Ports *env.Ports Vars map[string]string N int @@ -165,7 +166,25 @@ func (s *Scenario) Run(p *Params) error { func (s *Scenario) Cleanup() {} func ReadYAML(input string, pb proto.Message) error { - js, err := yaml.YAMLToJSON([]byte(input)) + var jsonObj interface{} + err := yamlv2.Unmarshal([]byte(input), &jsonObj) + if err != nil { + return err + } + // As a special case, convert [x] to x. + // This is needed because jsonpb is unable to parse arrays. + in := reflect.ValueOf(jsonObj) + switch in.Kind() { + case reflect.Slice, reflect.Array: + if in.Len() == 1 { + jsonObj = in.Index(0).Interface() + } + } + yml, err := yamlv2.Marshal(jsonObj) + if err != nil { + return err + } + js, err := yaml.YAMLToJSON(yml) if err != nil { return err } diff --git a/test/envoye2e/driver/xds.go b/test/envoye2e/driver/xds.go index dc3b1e4c2bc..8b26a63e11a 100644 --- a/test/envoye2e/driver/xds.go +++ b/test/envoye2e/driver/xds.go @@ -20,9 +20,13 @@ import ( "log" "net" + "istio.io/proxy/tools/extensionserver" + cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" + core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" discovery "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" + extensionservice "github.com/envoyproxy/go-control-plane/envoy/service/extension/v3" "github.com/envoyproxy/go-control-plane/pkg/cache/types" "github.com/envoyproxy/go-control-plane/pkg/cache/v3" "github.com/envoyproxy/go-control-plane/pkg/server/v3" @@ -34,20 +38,27 @@ type XDS struct { grpc *grpc.Server } +// XDSServer is a struct holding xDS state. +type XDSServer struct { + Extensions *extensionserver.ExtensionServer + Cache cache.SnapshotCache +} + var _ Step = &XDS{} func (x *XDS) Run(p *Params) error { log.Printf("XDS server starting on %d\n", p.XDS) x.grpc = grpc.NewServer() + p.Config.Extensions = extensionserver.New(context.Background()) + extensionservice.RegisterExtensionConfigDiscoveryServiceServer(x.grpc, p.Config.Extensions) + p.Config.Cache = cache.NewSnapshotCache(false, cache.IDHash{}, x) + xdsServer := server.NewServer(context.Background(), p.Config.Cache, nil) + discovery.RegisterAggregatedDiscoveryServiceServer(x.grpc, xdsServer) lis, err := net.Listen("tcp", fmt.Sprintf(":%d", p.XDS)) if err != nil { return err } - p.Config = cache.NewSnapshotCache(false, cache.IDHash{}, x) - xdsServer := server.NewServer(context.Background(), p.Config, nil) - discovery.RegisterAggregatedDiscoveryServiceServer(x.grpc, xdsServer) - go func() { _ = x.grpc.Serve(lis) }() @@ -109,7 +120,29 @@ func (u *Update) Run(p *Params) error { snap := cache.Snapshot{} snap.Resources[types.Cluster] = cache.NewResources(version, clusters) snap.Resources[types.Listener] = cache.NewResources(version, listeners) - return p.Config.SetSnapshot(u.Node, snap) + return p.Config.Cache.SetSnapshot(u.Node, snap) } func (u *Update) Cleanup() {} + +type UpdateExtensions struct { + Extensions []string +} + +var _ Step = &UpdateExtensions{} + +func (u *UpdateExtensions) Run(p *Params) error { + for _, extension := range u.Extensions { + out := &core.TypedExtensionConfig{} + if err := p.FillYAML(extension, out); err != nil { + return err + } + log.Printf("updating extension config %q", out.Name) + if err := p.Config.Extensions.Update(out); err != nil { + return err + } + } + return nil +} + +func (u *UpdateExtensions) Cleanup() {} diff --git a/test/envoye2e/env/utils.go b/test/envoye2e/env/utils.go index d75e32cc41e..421a64fb7ba 100644 --- a/test/envoye2e/env/utils.go +++ b/test/envoye2e/env/utils.go @@ -22,17 +22,15 @@ import ( "testing" ) -func GetDefaultEnvoyBin() string { +func GetBazelBin() string { // Note: `bazel info bazel-bin` returns incorrect path to a binary (always fastbuild, not opt or dbg) // Instead we rely on symbolic link src/envoy/envoy in the workspace workspace, _ := exec.Command("bazel", "info", "workspace").Output() - return filepath.Join(strings.TrimSuffix(string(workspace), "\n"), "bazel-bin/src/envoy/") + return filepath.Join(strings.TrimSuffix(string(workspace), "\n"), "bazel-bin/") } -func GetBazelOptOut() string { - // `make build_wasm` puts generated wasm modules into k8-opt. - bazelOutput, _ := exec.Command("bazel", "info", "output_path").Output() - return filepath.Join(strings.TrimSuffix(string(bazelOutput), "\n"), "k8-opt/bin/") +func GetDefaultEnvoyBin() string { + return filepath.Join(GetBazelBin(), "src/envoy/") } func SkipTSanASan(t *testing.T) { diff --git a/test/envoye2e/http_metadata_exchange/exchange_test.go b/test/envoye2e/http_metadata_exchange/exchange_test.go index 4ed67e3b1ad..0d1b4cedf68 100644 --- a/test/envoye2e/http_metadata_exchange/exchange_test.go +++ b/test/envoye2e/http_metadata_exchange/exchange_test.go @@ -40,11 +40,11 @@ func EncodeMetadata(t *testing.T, p *driver.Params) string { } func TestHTTPExchange(t *testing.T) { - params := driver.NewTestParams(t, map[string]string{ - "EnableMetadataExchange": "true", - }, envoye2e.ProxyE2ETests) + params := driver.NewTestParams(t, map[string]string{}, envoye2e.ProxyE2ETests) params.Vars["ClientMetadata"] = params.LoadTestData("testdata/client_node_metadata.json.tmpl") params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl") + params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl") + params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl") if err := (&driver.Scenario{ []driver.Step{ &driver.XDS{}, diff --git a/test/envoye2e/inventory.go b/test/envoye2e/inventory.go index d819c5c29b8..ea760a4b590 100644 --- a/test/envoye2e/inventory.go +++ b/test/envoye2e/inventory.go @@ -54,6 +54,9 @@ func init() { "TestTCPMetadataExchange", "TestTCPMetadataExchangeNoAlpn", "TestAttributeGen", + "TestStatsECDS/envoy.wasm.runtime.null", + "TestStatsECDS/envoy.wasm.runtime.v8", + "TestStatsECDS/envoy.wasm.runtime.v8#01", }, } } diff --git a/test/envoye2e/stackdriver_plugin/stackdriver_test.go b/test/envoye2e/stackdriver_plugin/stackdriver_test.go index 3a7a02969a0..c7c6384a088 100644 --- a/test/envoye2e/stackdriver_plugin/stackdriver_test.go +++ b/test/envoye2e/stackdriver_plugin/stackdriver_test.go @@ -29,7 +29,6 @@ func TestStackdriverPayload(t *testing.T) { params := driver.NewTestParams(t, map[string]string{ "ServiceAuthenticationPolicy": "NONE", "SDLogStatusCode": "200", - "EnableMetadataExchange": "true", "StackdriverRootCAFile": driver.TestPath("testdata/certs/stackdriver.pem"), "StackdriverTokenFile": driver.TestPath("testdata/certs/access-token"), "StatsConfig": driver.LoadTestData("testdata/bootstrap/stats.yaml.tmpl"), @@ -41,8 +40,10 @@ func TestStackdriverPayload(t *testing.T) { params.Vars["STSPort"] = strconv.Itoa(int(stsPort)) params.Vars["ClientMetadata"] = params.LoadTestData("testdata/client_node_metadata.json.tmpl") params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl") - params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") - params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") + params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") + params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") sd := &Stackdriver{Port: sdPort} @@ -80,20 +81,21 @@ func TestStackdriverPayload(t *testing.T) { func TestStackdriverPayloadGateway(t *testing.T) { t.Parallel() params := driver.NewTestParams(t, map[string]string{ - "RequestPath": "echo", - "SDLogStatusCode": "200", - "EnableMetadataExchange": "true", - "StackdriverRootCAFile": driver.TestPath("testdata/certs/stackdriver.pem"), - "StackdriverTokenFile": driver.TestPath("testdata/certs/access-token"), - "StatsConfig": driver.LoadTestData("testdata/bootstrap/stats.yaml.tmpl"), + "RequestPath": "echo", + "SDLogStatusCode": "200", + "StackdriverRootCAFile": driver.TestPath("testdata/certs/stackdriver.pem"), + "StackdriverTokenFile": driver.TestPath("testdata/certs/access-token"), + "StatsConfig": driver.LoadTestData("testdata/bootstrap/stats.yaml.tmpl"), }, envoye2e.ProxyE2ETests) sdPort := params.Ports.Max + 1 stsPort := params.Ports.Max + 2 params.Vars["SDPort"] = strconv.Itoa(int(sdPort)) params.Vars["STSPort"] = strconv.Itoa(int(stsPort)) params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl") - params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") - params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") + params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") + params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") sd := &Stackdriver{Port: sdPort} @@ -136,7 +138,6 @@ func TestStackdriverPayloadWithTLS(t *testing.T) { params := driver.NewTestParams(t, map[string]string{ "ServiceAuthenticationPolicy": "MUTUAL_TLS", "SDLogStatusCode": "200", - "EnableMetadataExchange": "true", "SourcePrincipal": "spiffe://cluster.local/ns/default/sa/client", "DestinationPrincipal": "spiffe://cluster.local/ns/default/sa/server", "StackdriverRootCAFile": driver.TestPath("testdata/certs/stackdriver.pem"), @@ -151,8 +152,10 @@ func TestStackdriverPayloadWithTLS(t *testing.T) { params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl") params.Vars["ClientTLSContext"] = params.LoadTestData("testdata/transport_socket/client.yaml.tmpl") params.Vars["ServerTLSContext"] = params.LoadTestData("testdata/transport_socket/server.yaml.tmpl") - params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") - params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") + params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") + params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") sd := &Stackdriver{Port: sdPort} @@ -194,7 +197,6 @@ func TestStackdriverReload(t *testing.T) { params := driver.NewTestParams(t, map[string]string{ "ServiceAuthenticationPolicy": "NONE", "SDLogStatusCode": "200", - "EnableMetadataExchange": "true", "StackdriverRootCAFile": driver.TestPath("testdata/certs/stackdriver.pem"), "StackdriverTokenFile": driver.TestPath("testdata/certs/access-token"), }, envoye2e.ProxyE2ETests) @@ -204,8 +206,10 @@ func TestStackdriverReload(t *testing.T) { params.Vars["STSPort"] = strconv.Itoa(int(stsPort)) params.Vars["ClientMetadata"] = params.LoadTestData("testdata/client_node_metadata.json.tmpl") params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl") - params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") - params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") + params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") + params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") sd := &Stackdriver{Port: sdPort} if err := (&driver.Scenario{ @@ -246,7 +250,6 @@ func TestStackdriverVMReload(t *testing.T) { params := driver.NewTestParams(t, map[string]string{ "ServiceAuthenticationPolicy": "NONE", "SDLogStatusCode": "200", - "EnableMetadataExchange": "true", "StackdriverRootCAFile": driver.TestPath("testdata/certs/stackdriver.pem"), "StackdriverTokenFile": driver.TestPath("testdata/certs/access-token"), "ReloadVM": "true", @@ -257,8 +260,10 @@ func TestStackdriverVMReload(t *testing.T) { params.Vars["STSPort"] = strconv.Itoa(int(stsPort)) params.Vars["ClientMetadata"] = params.LoadTestData("testdata/client_node_metadata.json.tmpl") params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl") - params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") - params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") + params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") + params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") sd := &Stackdriver{Port: sdPort} @@ -306,7 +311,6 @@ func TestStackdriverGCEInstances(t *testing.T) { params := driver.NewTestParams(t, map[string]string{ "ServiceAuthenticationPolicy": "NONE", "SDLogStatusCode": "200", - "EnableMetadataExchange": "true", "StackdriverRootCAFile": driver.TestPath("testdata/certs/stackdriver.pem"), "StackdriverTokenFile": driver.TestPath("testdata/certs/access-token"), }, envoye2e.ProxyE2ETests) @@ -316,8 +320,10 @@ func TestStackdriverGCEInstances(t *testing.T) { params.Vars["STSPort"] = strconv.Itoa(int(stsPort)) params.Vars["ClientMetadata"] = params.LoadTestData("testdata/gce_client_node_metadata.json.tmpl") params.Vars["ServerMetadata"] = params.LoadTestData("testdata/gce_server_node_metadata.json.tmpl") - params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") - params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") + params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") + params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") sd := &Stackdriver{Port: sdPort} if err := (&driver.Scenario{ @@ -351,10 +357,9 @@ func TestStackdriverGCEInstances(t *testing.T) { func TestStackdriverParallel(t *testing.T) { t.Parallel() params := driver.NewTestParams(t, map[string]string{ - "SDLogStatusCode": "200", - "EnableMetadataExchange": "true", - "StackdriverRootCAFile": driver.TestPath("testdata/certs/stackdriver.pem"), - "StackdriverTokenFile": driver.TestPath("testdata/certs/access-token"), + "SDLogStatusCode": "200", + "StackdriverRootCAFile": driver.TestPath("testdata/certs/stackdriver.pem"), + "StackdriverTokenFile": driver.TestPath("testdata/certs/access-token"), }, envoye2e.ProxyE2ETests) sdPort := params.Ports.Max + 1 stsPort := params.Ports.Max + 2 @@ -362,8 +367,10 @@ func TestStackdriverParallel(t *testing.T) { params.Vars["STSPort"] = strconv.Itoa(int(stsPort)) params.Vars["ClientMetadata"] = params.LoadTestData("testdata/client_node_metadata.json.tmpl") params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl") - params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") - params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") + params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") + params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") sd := &Stackdriver{Port: sdPort, Delay: 100 * time.Millisecond} @@ -430,7 +437,6 @@ func TestStackdriverAccessLog(t *testing.T) { t.Run(tt.name, func(t *testing.T) { params := driver.NewTestParams(t, map[string]string{ "LogWindowDuration": tt.logWindowDuration, - "EnableMetadataExchange": "true", "ServiceAuthenticationPolicy": "NONE", "DirectResponseCode": tt.respCode, "SDLogStatusCode": tt.respCode, @@ -444,9 +450,11 @@ func TestStackdriverAccessLog(t *testing.T) { params.Vars["STSPort"] = strconv.Itoa(int(stsPort)) params.Vars["ClientMetadata"] = params.LoadTestData("testdata/client_node_metadata.json.tmpl") params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl") - params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/access_log_policy.yaml.tmpl") + "\n" + + params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/access_log_policy.yaml.tmpl") + "\n" + params.LoadTestData("testdata/filters/stackdriver_inbound.yaml.tmpl") - params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") + params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stackdriver_outbound.yaml.tmpl") sd := &Stackdriver{Port: sdPort} respCode, _ := strconv.Atoi(tt.respCode) @@ -515,7 +523,6 @@ func TestStackdriverTCPMetadataExchange(t *testing.T) { params := driver.NewTestParams(t, map[string]string{ "ServiceAuthenticationPolicy": "MUTUAL_TLS", "SDLogStatusCode": "200", - "EnableMetadataExchange": "true", "StackdriverRootCAFile": driver.TestPath("testdata/certs/stackdriver.pem"), "StackdriverTokenFile": driver.TestPath("testdata/certs/access-token"), "SourcePrincipal": "spiffe://cluster.local/ns/default/sa/client", diff --git a/test/envoye2e/stats_plugin/README.md b/test/envoye2e/stats_plugin/README.md index ae194650df6..c5f48b07c9c 100644 --- a/test/envoye2e/stats_plugin/README.md +++ b/test/envoye2e/stats_plugin/README.md @@ -98,7 +98,6 @@ params := driver.NewTestParams(t, map[string]string{ "StatsFilterCode": "inline_string: \"envoy.wasm.stats\"", "AttributeGenFilterConfig": runtime.AttributeGenFilterCode, "AttributeGenWasmRuntime": runtime.WasmRuntime, - "EnableMetadataExchange": "true", "WasmRuntime": "envoy.wasm.runtime.null", "StatsConfig": driver.LoadTestData("testdata/bootstrap/stats.yaml.tmpl"), "StatsFilterClientConfig": driver.LoadTestJSON("testdata/stats/client_config.yaml"), diff --git a/test/envoye2e/stats_plugin/stats_test.go b/test/envoye2e/stats_plugin/stats_test.go index d9299d81770..98dc1d0f6c6 100644 --- a/test/envoye2e/stats_plugin/stats_test.go +++ b/test/envoye2e/stats_plugin/stats_test.go @@ -64,13 +64,13 @@ var Runtimes = []struct { WasmRuntime: "envoy.wasm.runtime.null", }, { - MetadataExchangeFilterCode: "filename: " + filepath.Join(env.GetBazelOptOut(), "extensions/metadata_exchange.wasm"), - StatsFilterCode: "filename: " + filepath.Join(env.GetBazelOptOut(), "extensions/stats.wasm"), + MetadataExchangeFilterCode: "filename: " + filepath.Join(env.GetBazelBin(), "extensions/metadata_exchange.wasm"), + StatsFilterCode: "filename: " + filepath.Join(env.GetBazelBin(), "extensions/stats.wasm"), WasmRuntime: "envoy.wasm.runtime.v8", }, { - MetadataExchangeFilterCode: "filename: " + filepath.Join(env.GetBazelOptOut(), "extensions/metadata_exchange.compiled.wasm"), - StatsFilterCode: "filename: " + filepath.Join(env.GetBazelOptOut(), "extensions/stats.compiled.wasm"), + MetadataExchangeFilterCode: "filename: " + filepath.Join(env.GetBazelBin(), "extensions/metadata_exchange.compiled.wasm"), + StatsFilterCode: "filename: " + filepath.Join(env.GetBazelBin(), "extensions/stats.compiled.wasm"), WasmRuntime: "envoy.wasm.runtime.v8", }, } @@ -137,7 +137,7 @@ var AttributeGenRuntimes = []struct { WasmRuntime: "envoy.wasm.runtime.null", }, { - AttributeGenFilterCode: "filename: " + filepath.Join(env.GetBazelOptOut(), "extensions/attributegen.wasm"), + AttributeGenFilterCode: "filename: " + filepath.Join(env.GetBazelBin(), "extensions/attributegen.wasm"), WasmRuntime: "envoy.wasm.runtime.v8", }, } @@ -150,7 +150,6 @@ func TestStatsPayload(t *testing.T) { skipWasm(t, runtime.WasmRuntime) params := driver.NewTestParams(t, map[string]string{ "RequestCount": "10", - "EnableMetadataExchange": "true", "MetadataExchangeFilterCode": runtime.MetadataExchangeFilterCode, "StatsFilterCode": runtime.StatsFilterCode, "WasmRuntime": runtime.WasmRuntime, @@ -161,8 +160,10 @@ func TestStatsPayload(t *testing.T) { }, envoye2e.ProxyE2ETests) params.Vars["ClientMetadata"] = params.LoadTestData("testdata/client_node_metadata.json.tmpl") params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl") - params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/stats_inbound.yaml.tmpl") - params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/stats_outbound.yaml.tmpl") + params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stats_inbound.yaml.tmpl") + params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stats_outbound.yaml.tmpl") if err := (&driver.Scenario{ []driver.Step{ &driver.XDS{}, @@ -204,7 +205,6 @@ func TestStatsParallel(t *testing.T) { "MetadataExchangeFilterCode": "inline_string: \"envoy.wasm.metadata_exchange\"", "StatsFilterCode": "inline_string: \"envoy.wasm.stats\"", "WasmRuntime": "envoy.wasm.runtime.null", - "EnableMetadataExchange": "true", "StatsConfig": driver.LoadTestData("testdata/bootstrap/stats.yaml.tmpl"), "StatsFilterClientConfig": driver.LoadTestJSON(testCase.ClientConfig), "StatsFilterServerConfig": driver.LoadTestJSON("testdata/stats/server_config.yaml"), @@ -215,8 +215,10 @@ func TestStatsParallel(t *testing.T) { serverRequestTotal := &dto.MetricFamily{} params.LoadTestProto("testdata/metric/client_request_total.yaml.tmpl", clientRequestTotal) params.LoadTestProto("testdata/metric/server_request_total.yaml.tmpl", serverRequestTotal) - params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/stats_inbound.yaml.tmpl") - params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/stats_outbound.yaml.tmpl") + params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stats_inbound.yaml.tmpl") + params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stats_outbound.yaml.tmpl") if err := (&driver.Scenario{ []driver.Step{ @@ -277,15 +279,16 @@ func TestStatsGrpc(t *testing.T) { "DisableDirectResponse": "true", "UsingGrpcBackend": "true", "GrpcResponseStatus": "7", - "EnableMetadataExchange": "true", "StatsConfig": driver.LoadTestData("testdata/bootstrap/stats.yaml.tmpl"), "StatsFilterClientConfig": driver.LoadTestJSON("testdata/stats/client_config.yaml"), "StatsFilterServerConfig": driver.LoadTestJSON("testdata/stats/server_config.yaml"), }, envoye2e.ProxyE2ETests) params.Vars["ClientMetadata"] = params.LoadTestData("testdata/client_node_metadata.json.tmpl") params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl") - params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/stats_inbound.yaml.tmpl") - params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/stats_outbound.yaml.tmpl") + params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stats_inbound.yaml.tmpl") + params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stats_outbound.yaml.tmpl") if err := (&driver.Scenario{ Steps: []driver.Step{ &driver.XDS{}, @@ -315,7 +318,7 @@ func TestStatsGrpc(t *testing.T) { } } -func TestAttributeGen(t *testing.T) { +func TestAttributeGenIntegration(t *testing.T) { for _, runtime := range AttributeGenRuntimes { t.Run(runtime.WasmRuntime, func(t *testing.T) { skipWasm(t, runtime.WasmRuntime) @@ -325,7 +328,6 @@ func TestAttributeGen(t *testing.T) { "StatsFilterCode": "inline_string: \"envoy.wasm.stats\"", "AttributeGenFilterConfig": runtime.AttributeGenFilterCode, "AttributeGenWasmRuntime": runtime.WasmRuntime, - "EnableMetadataExchange": "true", "WasmRuntime": "envoy.wasm.runtime.null", "StatsConfig": driver.LoadTestData("testdata/bootstrap/stats.yaml.tmpl"), "StatsFilterClientConfig": driver.LoadTestJSON("testdata/stats/client_config.yaml"), @@ -334,9 +336,11 @@ func TestAttributeGen(t *testing.T) { }, envoye2e.ProxyE2ETests) params.Vars["ClientMetadata"] = params.LoadTestData("testdata/client_node_metadata.json.tmpl") params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl") - params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/attributegen.yaml.tmpl") + "\n" + + params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/attributegen.yaml.tmpl") + "\n" + params.LoadTestData("testdata/filters/stats_inbound.yaml.tmpl") - params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/stats_outbound.yaml.tmpl") + params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl") + "\n" + + params.LoadTestData("testdata/filters/stats_outbound.yaml.tmpl") if err := (&driver.Scenario{ []driver.Step{ &driver.XDS{}, @@ -361,3 +365,63 @@ func TestAttributeGen(t *testing.T) { }) } } + +func TestStatsECDS(t *testing.T) { + env.SkipTSanASan(t) + for _, runtime := range Runtimes { + t.Run(runtime.WasmRuntime, func(t *testing.T) { + skipWasm(t, runtime.WasmRuntime) + params := driver.NewTestParams(t, map[string]string{ + "RequestCount": "10", + "MetadataExchangeFilterCode": runtime.MetadataExchangeFilterCode, + "StatsFilterCode": runtime.StatsFilterCode, + "WasmRuntime": runtime.WasmRuntime, + "StatsConfig": driver.LoadTestData("testdata/bootstrap/stats.yaml.tmpl"), + "StatsFilterClientConfig": driver.LoadTestJSON("testdata/stats/client_config.yaml"), + "StatsFilterServerConfig": driver.LoadTestJSON("testdata/stats/server_config.yaml"), + }, envoye2e.ProxyE2ETests) + params.Vars["ClientMetadata"] = params.LoadTestData("testdata/client_node_metadata.json.tmpl") + params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl") + params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/extension_config_inbound.yaml.tmpl") + params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/extension_config_outbound.yaml.tmpl") + + updateExtensions := + &driver.UpdateExtensions{Extensions: []string{ + driver.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl"), + driver.LoadTestData("testdata/filters/stats_inbound.yaml.tmpl"), + driver.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl"), + driver.LoadTestData("testdata/filters/stats_outbound.yaml.tmpl"), + }, + } + if err := (&driver.Scenario{ + []driver.Step{ + &driver.XDS{}, + &driver.Update{ + Node: "client", + Version: "0", + Clusters: []string{params.LoadTestData("testdata/cluster/server.yaml.tmpl")}, + Listeners: []string{params.LoadTestData("testdata/listener/client.yaml.tmpl")}}, + &driver.Update{Node: "server", Version: "0", Listeners: []string{params.LoadTestData("testdata/listener/server.yaml.tmpl")}}, + updateExtensions, + &driver.Envoy{Bootstrap: params.LoadTestData("testdata/bootstrap/server.yaml.tmpl")}, + &driver.Envoy{Bootstrap: params.LoadTestData("testdata/bootstrap/client.yaml.tmpl")}, + &driver.Sleep{1 * time.Second}, + &driver.Repeat{N: 10, + Step: &driver.HTTPCall{ + Port: params.Ports.ClientPort, + Body: "hello, world!", + }, + }, + &driver.Stats{params.Ports.ClientAdmin, map[string]driver.StatMatcher{ + "istio_requests_total": &driver.ExactStat{"testdata/metric/client_request_total.yaml.tmpl"}, + }}, + &driver.Stats{params.Ports.ServerAdmin, map[string]driver.StatMatcher{ + "istio_requests_total": &driver.ExactStat{"testdata/metric/server_request_total.yaml.tmpl"}, + }}, + }, + }).Run(params); err != nil { + t.Fatal(err) + } + }) + } +} diff --git a/testdata/filters/extension_config_inbound.yaml.tmpl b/testdata/filters/extension_config_inbound.yaml.tmpl new file mode 100644 index 00000000000..80893f06c9d --- /dev/null +++ b/testdata/filters/extension_config_inbound.yaml.tmpl @@ -0,0 +1,20 @@ +- name: mx_inbound{{.N}} + config_discovery: + config_source: + api_config_source: + api_type: GRPC + transport_api_version: V3 + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + type_urls: ["envoy.extensions.filters.http.wasm.v3.Wasm"] +- name: stats_inbound{{.N}} + config_discovery: + config_source: + api_config_source: + api_type: GRPC + transport_api_version: V3 + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + type_urls: ["envoy.extensions.filters.http.wasm.v3.Wasm"] diff --git a/testdata/filters/extension_config_outbound.yaml.tmpl b/testdata/filters/extension_config_outbound.yaml.tmpl new file mode 100644 index 00000000000..1f534997e49 --- /dev/null +++ b/testdata/filters/extension_config_outbound.yaml.tmpl @@ -0,0 +1,20 @@ +- name: mx_outbound{{.N}} + config_discovery: + config_source: + api_config_source: + api_type: GRPC + transport_api_version: V3 + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + type_urls: ["envoy.extensions.filters.http.wasm.v3.Wasm"] +- name: stats_outbound{{.N}} + config_discovery: + config_source: + api_config_source: + api_type: GRPC + transport_api_version: V3 + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + type_urls: ["envoy.extensions.filters.http.wasm.v3.Wasm"] diff --git a/testdata/filters/mx_inbound.yaml.tmpl b/testdata/filters/mx_inbound.yaml.tmpl new file mode 100644 index 00000000000..65623bfeac9 --- /dev/null +++ b/testdata/filters/mx_inbound.yaml.tmpl @@ -0,0 +1,23 @@ +- name: mx_inbound{{.N}} + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + vm_config: + {{- if .Vars.WasmRuntime }} + runtime: {{ .Vars.WasmRuntime }} + {{- else }} + runtime: envoy.wasm.runtime.null + {{- end }} + code: + {{- if .Vars.MetadataExchangeFilterCode }} + local: { {{ .Vars.MetadataExchangeFilterCode }} } + {{- else }} + local: { inline_string: "envoy.wasm.metadata_exchange" } + {{- end }} + allow_precompiled: true + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + { "max_peer_cache_size": 20 } diff --git a/testdata/filters/mx_outbound.yaml.tmpl b/testdata/filters/mx_outbound.yaml.tmpl new file mode 100644 index 00000000000..9ce71775372 --- /dev/null +++ b/testdata/filters/mx_outbound.yaml.tmpl @@ -0,0 +1,23 @@ +- name: mx_outbound{{.N}} + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + vm_config: + {{- if .Vars.WasmRuntime }} + runtime: {{ .Vars.WasmRuntime }} + {{- else }} + runtime: envoy.wasm.runtime.null + {{- end }} + code: + {{- if .Vars.MetadataExchangeFilterCode }} + local: { {{ .Vars.MetadataExchangeFilterCode }} } + {{- else }} + local: { inline_string: "envoy.wasm.metadata_exchange" } + {{- end }} + allow_precompiled: true + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + { "max_peer_cache_size": 20 } diff --git a/testdata/filters/stats_inbound.yaml.tmpl b/testdata/filters/stats_inbound.yaml.tmpl index 773fff98f79..19a63bef1ae 100644 --- a/testdata/filters/stats_inbound.yaml.tmpl +++ b/testdata/filters/stats_inbound.yaml.tmpl @@ -1,4 +1,4 @@ -- name: envoy.filters.http.wasm +- name: stats_inbound{{.N}} typed_config: "@type": type.googleapis.com/udpa.type.v1.TypedStruct type_url: envoy.extensions.filters.http.wasm.v3.Wasm diff --git a/testdata/filters/stats_outbound.yaml.tmpl b/testdata/filters/stats_outbound.yaml.tmpl index 7e227c51bb9..15540d2ebed 100644 --- a/testdata/filters/stats_outbound.yaml.tmpl +++ b/testdata/filters/stats_outbound.yaml.tmpl @@ -1,4 +1,4 @@ -- name: envoy.filters.http.wasm +- name: stats_outbound{{.N}} typed_config: "@type": type.googleapis.com/udpa.type.v1.TypedStruct type_url: envoy.extensions.filters.http.wasm.v3.Wasm diff --git a/testdata/listener/client.yaml.tmpl b/testdata/listener/client.yaml.tmpl index 24db65a587c..92ac86ac4b0 100644 --- a/testdata/listener/client.yaml.tmpl +++ b/testdata/listener/client.yaml.tmpl @@ -15,31 +15,6 @@ filter_chains: codec_type: AUTO stat_prefix: client http_filters: -{{- if eq .Vars.EnableMetadataExchange "true" }} - - name: envoy.filters.http.wasm - typed_config: - "@type": type.googleapis.com/udpa.type.v1.TypedStruct - type_url: envoy.extensions.filters.http.wasm.v3.Wasm - value: - config: - vm_config: - {{- if .Vars.WasmRuntime }} - runtime: {{ .Vars.WasmRuntime }} - {{- else }} - runtime: envoy.wasm.runtime.null - {{- end }} - code: - {{- if .Vars.MetadataExchangeFilterCode }} - local: { {{ .Vars.MetadataExchangeFilterCode }} } - {{- else }} - local: { inline_string: "envoy.wasm.metadata_exchange" } - {{- end }} - allow_precompiled: true - configuration: - "@type": "type.googleapis.com/google.protobuf.StringValue" - value: | - { "max_peer_cache_size": 20 } -{{- end }} {{- if ne .Vars.ClientHTTPFilters "" }} {{ .Vars.ClientHTTPFilters | indent 6 }} {{- end }} diff --git a/testdata/listener/server.yaml.tmpl b/testdata/listener/server.yaml.tmpl index a8f431c4f87..63e79c9039a 100644 --- a/testdata/listener/server.yaml.tmpl +++ b/testdata/listener/server.yaml.tmpl @@ -15,31 +15,6 @@ filter_chains: codec_type: AUTO stat_prefix: server http_filters: -{{- if eq .Vars.EnableMetadataExchange "true" }} - - name: envoy.filters.http.wasm - typed_config: - "@type": type.googleapis.com/udpa.type.v1.TypedStruct - type_url: envoy.extensions.filters.http.wasm.v3.Wasm - value: - config: - vm_config: - {{- if .Vars.WasmRuntime }} - runtime: {{ .Vars.WasmRuntime }} - {{- else }} - runtime: envoy.wasm.runtime.null - {{- end }} - code: - {{- if .Vars.MetadataExchangeFilterCode }} - local: { {{ .Vars.MetadataExchangeFilterCode }} } - {{- else }} - local: { inline_string: "envoy.wasm.metadata_exchange" } - {{- end }} - allow_precompiled: true - configuration: - "@type": "type.googleapis.com/google.protobuf.StringValue" - value: | - { "max_peer_cache_size": 20 } -{{- end }} {{- if ne .Vars.ServerHTTPFilters "" }} {{ .Vars.ServerHTTPFilters | indent 6 }} {{- end }} diff --git a/tools/extensionserver/config.go b/tools/extensionserver/config.go new file mode 100644 index 00000000000..58a8b8f33bf --- /dev/null +++ b/tools/extensionserver/config.go @@ -0,0 +1,118 @@ +// Copyright Istio 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 extensionserver + +import ( + "encoding/json" + "io/ioutil" + "log" + "os" + "path/filepath" + "reflect" + + "github.com/fsnotify/fsnotify" + "github.com/ghodss/yaml" +) + +// Extension configuration +type Extension struct { + // Name of the extension + Name string `json:"name"` + // Configuration passed as JSON string + Configuration json.RawMessage `json:"configuration"` + // Path to the extension code + Path string `json:"path,omitempty"` + // VMID (optional) + VMID string `json:"vm_id,omitempty"` + // RootID (optional) + RootID string `json:"root_id,omitempty"` +} + +// Config for the extension server +type Config struct { + // Extensions list + Extensions []*Extension `json:"extensions"` +} + +func (c *Config) merge(that *Config) { + c.Extensions = append(c.Extensions, that.Extensions...) +} + +// Read loads a configuration +func Read(data []byte) (*Config, error) { + config := &Config{} + return config, yaml.Unmarshal(data, config) +} + +// Load configuration files from a directory +func Load(dir string) *Config { + out := &Config{} + _ = filepath.Walk(dir, func(path string, info os.FileInfo, _ error) error { + if info != nil && info.IsDir() { + return nil + } + ext := filepath.Ext(path) + if ext != ".json" && ext != ".yaml" && ext != ".yml" { + return nil + } + data, err := ioutil.ReadFile(path) + if err != nil { + log.Printf("error loading file %q: %v\n", path, err) + return nil + } + config, err := Read(data) + if err != nil { + log.Printf("error parsing file %q: %v\n", path, err) + return nil + } + out.merge(config) + return nil + }) + return out +} + +// Watch configuration files for changes (blocking call) +func Watch(dir string, apply func(*Config)) error { + watcher, err := fsnotify.NewWatcher() + if err != nil { + return err + } + err = watcher.Add(dir) + if err != nil { + return err + } + defer watcher.Close() + current := Load(dir) + apply(current) + for { + select { + case _, ok := <-watcher.Events: + if !ok { + return nil + } + next := Load(dir) + if reflect.DeepEqual(next, current) { + continue + } + current = next + apply(current) + case err, ok := <-watcher.Errors: + if !ok { + return nil + } + log.Printf("watch error: %v\n", err) + } + } +} diff --git a/tools/extensionserver/config_test.go b/tools/extensionserver/config_test.go new file mode 100644 index 00000000000..5482f4fee1f --- /dev/null +++ b/tools/extensionserver/config_test.go @@ -0,0 +1,41 @@ +// Copyright Istio 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 extensionserver_test + +import ( + "encoding/json" + "io/ioutil" + "testing" + + "istio.io/proxy/tools/extensionserver" +) + +func TestRead(t *testing.T) { + for _, file := range []string{"metadata_exchange", "stats"} { + data, err := ioutil.ReadFile("testdata/" + file + ".yaml") + if err != nil { + t.Fatal(err) + } + out, err := extensionserver.Read(data) + if err != nil { + t.Fatal(err) + } + js, err := json.Marshal(out) + if err != nil { + t.Fatal(err) + } + t.Log(string(js)) + } +} diff --git a/tools/extensionserver/convert.go b/tools/extensionserver/convert.go new file mode 100644 index 00000000000..653564a219d --- /dev/null +++ b/tools/extensionserver/convert.go @@ -0,0 +1,78 @@ +// Copyright Istio 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 extensionserver + +import ( + "io/ioutil" + + core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + wasm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/wasm/v3" + v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/wasm/v3" + ptypes "github.com/golang/protobuf/ptypes" + "github.com/golang/protobuf/ptypes/wrappers" +) + +// Convert to an envoy config. +// It so happens that 1.7 and 1.8 match in terms protobuf bytes, but not JSON. +func Convert(ext *Extension) (*core.TypedExtensionConfig, error) { + // wrap configuration into StringValue + json, err := ext.Configuration.MarshalJSON() + if err != nil { + return nil, err + } + configuration, err := ptypes.MarshalAny(&wrappers.StringValue{Value: string(json)}) + if err != nil { + return nil, err + } + + // load code as bytes + code, err := ioutil.ReadFile(ext.Path) + if err != nil { + return nil, err + } + + // create plugin config + plugin := &wasm.Wasm{ + Config: &v3.PluginConfig{ + RootId: ext.RootID, + VmConfig: &v3.PluginConfig_InlineVmConfig{ + InlineVmConfig: &v3.VmConfig{ + VmId: ext.VMID, + Runtime: "envoy.wasm.runtime.v8", + Code: &core.AsyncDataSource{ + Specifier: &core.AsyncDataSource_Local{ + Local: &core.DataSource{ + Specifier: &core.DataSource_InlineBytes{ + InlineBytes: code, + }, + }, + }, + }, + AllowPrecompiled: true, + }, + }, + Configuration: configuration, + }, + } + + typed, err := ptypes.MarshalAny(plugin) + if err != nil { + return nil, err + } + return &core.TypedExtensionConfig{ + Name: ext.Name, + TypedConfig: typed, + }, nil +} diff --git a/tools/extensionserver/envoy.yaml b/tools/extensionserver/envoy.yaml new file mode 100644 index 00000000000..c0e7a8154dc --- /dev/null +++ b/tools/extensionserver/envoy.yaml @@ -0,0 +1,96 @@ +static_resources: + listeners: + - address: + socket_address: + address: 0.0.0.0 + port_value: 8081 + traffic_direction: INBOUND + filter_chains: + - filters: + - name: inbound-http-proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + codec_type: auto + stat_prefix: ingress_http + route_config: + name: local_route + virtual_hosts: + - name: backend + domains: + - "*" + routes: + - match: + prefix: "/" + direct_response: + status: 200 + body: + inline_string: "hello, world!\n" + http_filters: + - name: metadata_exchange + config_discovery: + config_source: + api_config_source: + api_type: GRPC + transport_api_version: V3 + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + type_urls: ["envoy.extensions.filters.http.wasm.v3.Wasm"] + - name: stats + config_discovery: + config_source: + api_config_source: + api_type: GRPC + transport_api_version: V3 + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + type_urls: ["envoy.extensions.filters.http.wasm.v3.Wasm"] + - name: front-router + typed_config: + "@type": type.googleapis.com/envoy.config.filter.http.router.v2.Router + clusters: + - connect_timeout: 1s + http2_protocol_options: {} + name: xds_cluster + load_assignment: + cluster_name: xds_cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 8080 +admin: + access_log_path: "/dev/null" + address: + socket_address: + address: 0.0.0.0 + port_value: 8001 +node: + id: test + cluster: test + metadata: { + "EXCHANGE_KEYS": "NAME,NAMESPACE,INSTANCE_IPS,LABELS,OWNER,PLATFORM_METADATA,WORKLOAD_NAME,CANONICAL_TELEMETRY_SERVICE,MESH_ID,SERVICE_ACCOUNT", + "INSTANCE_IPS": "10.52.0.34,fe80::a075:11ff:fe5e:f1cd", + "LABELS": { + "app": "ratings", + "pod-template-hash": "84975bc778", + "version": "v1", + "service.istio.io/canonical-name": "ratings", + "service.istio.io/canonical-revision": "version-1" + }, + "MESH_ID": "mesh", + "NAME": "ratings-v1-84975bc778-pxz2w", + "NAMESPACE": "default", + "OWNER": "kubernetes://apis/apps/v1/namespaces/default/deployments/ratings-v1", + "PLATFORM_METADATA": { + "gcp_gke_cluster_name": "test-cluster", + "gcp_location": "us-east4-b", + "gcp_project": "test-project" + }, + "POD_NAME": "ratings-v1-84975bc778-pxz2w", + "SERVICE_ACCOUNT": "bookinfo-ratings", + "WORKLOAD_NAME": "ratings-v1", + } diff --git a/tools/extensionserver/main/main.go b/tools/extensionserver/main/main.go new file mode 100644 index 00000000000..917cbb9ccff --- /dev/null +++ b/tools/extensionserver/main/main.go @@ -0,0 +1,95 @@ +// Copyright Istio 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 main + +import ( + "context" + "flag" + "fmt" + "log" + "net" + "reflect" + + "google.golang.org/grpc" + + discoveryservice "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" + extensionservice "github.com/envoyproxy/go-control-plane/envoy/service/extension/v3" + "istio.io/proxy/tools/extensionserver" +) + +const ( + grpcMaxConcurrentStreams = 100000 +) + +var ( + port uint + dir string + server *extensionserver.ExtensionServer + names = make(map[string]struct{}) +) + +func init() { + flag.UintVar(&port, "port", 8080, "xDS management server port") + flag.StringVar(&dir, "c", "", "Configuration file directory") +} + +func apply(config *extensionserver.Config) { + next := make(map[string]struct{}) + for _, ext := range config.Extensions { + config, err := extensionserver.Convert(ext) + if err != nil { + log.Printf("error loading extension %q: %v\n", ext.Name, err) + continue + } + if err = server.Update(config); err != nil { + log.Printf("error updating extension %q: %v\n", ext.Name, err) + } + next[ext.Name] = struct{}{} + delete(names, ext.Name) + } + for name := range names { + if err := server.Delete(name); err != nil { + log.Printf("error deleting extension %q: %v\n", name, err) + } + } + names = next + log.Printf("loaded extensions %v\n", reflect.ValueOf(names).MapKeys()) +} + +func main() { + flag.Parse() + + grpcServer := grpc.NewServer(grpc.MaxConcurrentStreams(grpcMaxConcurrentStreams)) + lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err != nil { + log.Fatal(err) + } + server = extensionserver.New(context.Background()) + discoveryservice.RegisterAggregatedDiscoveryServiceServer(grpcServer, server) + extensionservice.RegisterExtensionConfigDiscoveryServiceServer(grpcServer, server) + + log.Printf("watching directory %q\n", dir) + go func() { + err := extensionserver.Watch(dir, apply) + if err != nil { + log.Println(err) + } + }() + + log.Printf("management server listening on %d\n", port) + if err = grpcServer.Serve(lis); err != nil { + log.Println(err) + } +} diff --git a/tools/extensionserver/server.go b/tools/extensionserver/server.go new file mode 100644 index 00000000000..89f4e674049 --- /dev/null +++ b/tools/extensionserver/server.go @@ -0,0 +1,65 @@ +// Copyright Istio 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 extensionserver + +import ( + "context" + + core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + discovery "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" + extensionservice "github.com/envoyproxy/go-control-plane/envoy/service/extension/v3" + "github.com/envoyproxy/go-control-plane/pkg/cache/v3" + "github.com/envoyproxy/go-control-plane/pkg/server/v3" + "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +const ( + // APIType for extension configs. + APIType = "type.googleapis.com/envoy.config.core.v3.TypedExtensionConfig" +) + +// ExtensionServer is the main server instance. +type ExtensionServer struct { + server.Server + server.CallbackFuncs + cache *cache.LinearCache +} + +var _ extensionservice.ExtensionConfigDiscoveryServiceServer = &ExtensionServer{} + +func New(ctx context.Context) *ExtensionServer { + out := &ExtensionServer{} + out.cache = cache.NewLinearCache(APIType, nil) + out.Server = server.NewServer(ctx, out.cache, out) + return out +} + +func (es *ExtensionServer) StreamExtensionConfigs(stream extensionservice.ExtensionConfigDiscoveryService_StreamExtensionConfigsServer) error { + return es.Server.StreamHandler(stream, APIType) +} +func (es *ExtensionServer) DeltaExtensionConfigs(_ extensionservice.ExtensionConfigDiscoveryService_DeltaExtensionConfigsServer) error { + return status.Errorf(codes.Unimplemented, "not implemented") +} +func (es *ExtensionServer) FetchExtensionConfigs(ctx context.Context, req *discovery.DiscoveryRequest) (*discovery.DiscoveryResponse, error) { + req.TypeUrl = APIType + return es.Server.Fetch(ctx, req) +} +func (es *ExtensionServer) Update(config *core.TypedExtensionConfig) error { + return es.cache.UpdateResource(config.Name, config) +} +func (es *ExtensionServer) Delete(name string) error { + return es.cache.DeleteResource(name) +} diff --git a/tools/extensionserver/testdata/metadata_exchange.yaml b/tools/extensionserver/testdata/metadata_exchange.yaml new file mode 100644 index 00000000000..4d0ce2cf1bd --- /dev/null +++ b/tools/extensionserver/testdata/metadata_exchange.yaml @@ -0,0 +1,6 @@ +extensions: +- name: metadata_exchange + path: bazel-bin/extensions/metadata_exchange.wasm + vm_id: id1597352232945182978 + configuration: + max_peer_cache_size: 60 diff --git a/tools/extensionserver/testdata/stats.yaml b/tools/extensionserver/testdata/stats.yaml new file mode 100644 index 00000000000..521efecfa20 --- /dev/null +++ b/tools/extensionserver/testdata/stats.yaml @@ -0,0 +1,8 @@ +extensions: +- name: stats + path: bazel-bin/extensions/stats.wasm + vm_id: stats_inbound + root_id: stats_inbound + configuration: + debug: false + field_separator: ";.;"