diff --git a/.github/workflows/build_daily.yaml b/.github/workflows/build_daily.yaml index d67ab9f1dd7..f7a83ad8da8 100644 --- a/.github/workflows/build_daily.yaml +++ b/.github/workflows/build_daily.yaml @@ -16,42 +16,6 @@ env: GO_VERSION: 1.22.5 jobs: - e2e-contour-xds: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - persist-credentials: false - - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 - with: - # * Module download cache - # * Build cache (Linux) - path: | - ~/go/pkg/mod - ~/.cache/go-build - key: ${{ runner.os }}-${{ github.job }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-${{ github.job }}-go- - - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 - with: - go-version: ${{ env.GO_VERSION }} - cache: false - - name: add deps to path - run: | - ./hack/actions/install-kubernetes-toolchain.sh $GITHUB_WORKSPACE/bin - echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH - - name: e2e tests - env: - CONTOUR_E2E_IMAGE: ghcr.io/projectcontour/contour:main - CONTOUR_E2E_XDS_SERVER_TYPE: contour - run: | - make setup-kind-cluster run-e2e cleanup-kind - - uses: act10ns/slack@44541246747a30eb3102d87f7a4cc5471b0ffb7d # v2.1.0 - with: - status: ${{ job.status }} - steps: ${{ toJson(steps) }} - channel: '#contour-ci-notifications' - if: ${{ failure() && github.ref == 'refs/heads/main' }} e2e-envoy-deployment: runs-on: ubuntu-latest steps: diff --git a/apis/projectcontour/v1alpha1/contourconfig.go b/apis/projectcontour/v1alpha1/contourconfig.go index 0af7a50e08a..0c193b0641f 100644 --- a/apis/projectcontour/v1alpha1/contourconfig.go +++ b/apis/projectcontour/v1alpha1/contourconfig.go @@ -97,16 +97,6 @@ type ContourConfigurationSpec struct { // to toggle new contour features. type FeatureFlags []string -// XDSServerType is the type of xDS server implementation. -type XDSServerType string - -const ( - // Use Contour's xDS server (deprecated). - ContourServerType XDSServerType = "contour" - // Use the upstream `go-control-plane`-based xDS server. - EnvoyServerType XDSServerType = "envoy" -) - type CircuitBreakers struct { // The maximum number of connections that a single Envoy instance allows to the Kubernetes Service; defaults to 1024. // +optional @@ -128,17 +118,6 @@ type CircuitBreakers struct { // XDSServerConfig holds the config for the Contour xDS server. type XDSServerConfig struct { - // Defines the XDSServer to use for `contour serve`. - // - // Values: `envoy` (default), `contour (deprecated)`. - // - // Other values will produce an error. - // - // Deprecated: this field will be removed in a future release when - // the `contour` xDS server implementation is removed. - // +optional - Type XDSServerType `json:"type,omitempty"` - // Defines the xDS gRPC API address which Contour will serve. // // Contour's default is "0.0.0.0". diff --git a/apis/projectcontour/v1alpha1/contourconfig_helpers.go b/apis/projectcontour/v1alpha1/contourconfig_helpers.go index 4969279bc65..53f772552de 100644 --- a/apis/projectcontour/v1alpha1/contourconfig_helpers.go +++ b/apis/projectcontour/v1alpha1/contourconfig_helpers.go @@ -37,9 +37,6 @@ func (c *ContourConfigurationSpec) Validate() error { // Validation of nested configuration structs. var validateFuncs []func() error - if c.XDSServer != nil { - validateFuncs = append(validateFuncs, c.XDSServer.Type.Validate) - } if c.Envoy != nil { validateFuncs = append(validateFuncs, c.Envoy.Validate) } @@ -100,15 +97,6 @@ func (t *TracingConfig) Validate() error { return nil } -func (x XDSServerType) Validate() error { - switch x { - case ContourServerType, EnvoyServerType: - return nil - default: - return fmt.Errorf("invalid xDS server type %q", x) - } -} - func (d ClusterDNSFamilyType) Validate() error { switch d { case AutoClusterDNSFamily, IPv4ClusterDNSFamily, IPv6ClusterDNSFamily, AllClusterDNSFamily: diff --git a/apis/projectcontour/v1alpha1/contourconfig_helpers_test.go b/apis/projectcontour/v1alpha1/contourconfig_helpers_test.go index d4713df4c8e..6aa25cfbf72 100644 --- a/apis/projectcontour/v1alpha1/contourconfig_helpers_test.go +++ b/apis/projectcontour/v1alpha1/contourconfig_helpers_test.go @@ -25,21 +25,6 @@ import ( ) func TestContourConfigurationSpecValidate(t *testing.T) { - t.Run("xds server type validation", func(t *testing.T) { - c := contour_v1alpha1.ContourConfigurationSpec{ - XDSServer: &contour_v1alpha1.XDSServerConfig{}, - } - - c.XDSServer.Type = contour_v1alpha1.ContourServerType - require.NoError(t, c.Validate()) - - c.XDSServer.Type = contour_v1alpha1.EnvoyServerType - require.NoError(t, c.Validate()) - - c.XDSServer.Type = "foo" - require.Error(t, c.Validate()) - }) - t.Run("envoy validation", func(t *testing.T) { c := contour_v1alpha1.ContourConfigurationSpec{ Envoy: &contour_v1alpha1.EnvoyConfig{ diff --git a/cmd/contour/serve.go b/cmd/contour/serve.go index 1c48f9fce88..b88f3423a59 100644 --- a/cmd/contour/serve.go +++ b/cmd/contour/serve.go @@ -507,15 +507,10 @@ func (s *Server) doServe() error { // snapshotHandler triggers go-control-plane Snapshots based on // the contents of the Contour xDS caches after the DAG is built. - var snapshotHandler *xdscache_v3.SnapshotHandler + snapshotHandler := xdscache_v3.NewSnapshotHandler(resources, s.log.WithField("context", "snapshotHandler")) - // nolint:staticcheck - if contourConfiguration.XDSServer.Type == contour_v1alpha1.EnvoyServerType { - snapshotHandler = xdscache_v3.NewSnapshotHandler(resources, s.log.WithField("context", "snapshotHandler")) - - // register observer for endpoints updates. - endpointHandler.SetObserver(contour.ComposeObservers(snapshotHandler)) - } + // register observer for endpoints updates. + endpointHandler.SetObserver(contour.ComposeObservers(snapshotHandler)) // Log that we're using the fallback certificate if configured. if contourConfiguration.HTTPProxy.FallbackCertificate != nil { @@ -923,18 +918,7 @@ func (x *xdsServer) Start(ctx context.Context) error { log.Info("the initial dag is built") grpcServer := xds.NewServer(x.registry, grpcOptions(log, x.config.TLS)...) - - // nolint:staticcheck - switch x.config.Type { - case contour_v1alpha1.EnvoyServerType: - contour_xds_v3.RegisterServer(envoy_server_v3.NewServer(ctx, x.snapshotHandler.GetCache(), contour_xds_v3.NewRequestLoggingCallbacks(log)), grpcServer) - case contour_v1alpha1.ContourServerType: - contour_xds_v3.RegisterServer(contour_xds_v3.NewContourServer(log, xdscache.ResourcesOf(x.resources)...), grpcServer) - default: - // This can't happen due to config validation. - // nolint:staticcheck - log.Fatalf("invalid xDS server type %q", x.config.Type) - } + contour_xds_v3.RegisterServer(envoy_server_v3.NewServer(ctx, x.snapshotHandler.GetCache(), contour_xds_v3.NewRequestLoggingCallbacks(log)), grpcServer) addr := net.JoinHostPort(x.config.Address, strconv.Itoa(x.config.Port)) l, err := net.Listen("tcp", addr) @@ -947,8 +931,7 @@ func (x *xdsServer) Start(ctx context.Context) error { log = log.WithField("insecure", true) } - // nolint:staticcheck - log.Infof("started xDS server type: %q", x.config.Type) + log.Info("started xDS server") defer log.Info("stopped xDS server") go func() { diff --git a/cmd/contour/servecontext.go b/cmd/contour/servecontext.go index 3a1057b6479..0c406ed43a4 100644 --- a/cmd/contour/servecontext.go +++ b/cmd/contour/servecontext.go @@ -597,13 +597,7 @@ func (ctx *serveContext) convertToContourConfigurationSpec() contour_v1alpha1.Co FeatureFlags: ctx.Config.FeatureFlags, } - xdsServerType := contour_v1alpha1.ContourServerType - if ctx.Config.Server.XDSServerType == config.EnvoyServerType { - xdsServerType = contour_v1alpha1.EnvoyServerType - } - contourConfiguration.XDSServer = &contour_v1alpha1.XDSServerConfig{ - Type: xdsServerType, Address: ctx.xdsAddr, Port: ctx.xdsPort, TLS: &contour_v1alpha1.TLS{ diff --git a/cmd/contour/servecontext_test.go b/cmd/contour/servecontext_test.go index cf205d81a46..4a58e3355a5 100644 --- a/cmd/contour/servecontext_test.go +++ b/cmd/contour/servecontext_test.go @@ -379,7 +379,6 @@ func TestConvertServeContext(t *testing.T) { defaultContourConfiguration := func() contour_v1alpha1.ContourConfigurationSpec { return contour_v1alpha1.ContourConfigurationSpec{ XDSServer: &contour_v1alpha1.XDSServerConfig{ - Type: contour_v1alpha1.EnvoyServerType, Address: "127.0.0.1", Port: 8001, TLS: &contour_v1alpha1.TLS{ diff --git a/examples/contour/01-contour-config.yaml b/examples/contour/01-contour-config.yaml index 6eb7720b92b..a8c7c3fea7a 100644 --- a/examples/contour/01-contour-config.yaml +++ b/examples/contour/01-contour-config.yaml @@ -6,11 +6,6 @@ metadata: namespace: projectcontour data: contour.yaml: | - # - # server: - # determine which XDS Server implementation to utilize in Contour. - # xds-server-type: envoy - # # Specify the Gateway API configuration. # gateway: # namespace: projectcontour diff --git a/examples/contour/01-crds.yaml b/examples/contour/01-crds.yaml index 0beece5bc51..858873dd460 100644 --- a/examples/contour/01-crds.yaml +++ b/examples/contour/01-crds.yaml @@ -1144,14 +1144,6 @@ spec: description: Client key filename. type: string type: object - type: - description: |- - Defines the XDSServer to use for `contour serve`. - Values: `envoy` (default), `contour (deprecated)`. - Other values will produce an error. - Deprecated: this field will be removed in a future release when - the `contour` xDS server implementation is removed. - type: string type: object type: object status: @@ -4928,14 +4920,6 @@ spec: description: Client key filename. type: string type: object - type: - description: |- - Defines the XDSServer to use for `contour serve`. - Values: `envoy` (default), `contour (deprecated)`. - Other values will produce an error. - Deprecated: this field will be removed in a future release when - the `contour` xDS server implementation is removed. - type: string type: object type: object type: object diff --git a/examples/render/contour-deployment.yaml b/examples/render/contour-deployment.yaml index 1e085adae27..b06c0aeca3e 100644 --- a/examples/render/contour-deployment.yaml +++ b/examples/render/contour-deployment.yaml @@ -39,11 +39,6 @@ metadata: namespace: projectcontour data: contour.yaml: | - # - # server: - # determine which XDS Server implementation to utilize in Contour. - # xds-server-type: envoy - # # Specify the Gateway API configuration. # gateway: # namespace: projectcontour @@ -1364,14 +1359,6 @@ spec: description: Client key filename. type: string type: object - type: - description: |- - Defines the XDSServer to use for `contour serve`. - Values: `envoy` (default), `contour (deprecated)`. - Other values will produce an error. - Deprecated: this field will be removed in a future release when - the `contour` xDS server implementation is removed. - type: string type: object type: object status: @@ -5148,14 +5135,6 @@ spec: description: Client key filename. type: string type: object - type: - description: |- - Defines the XDSServer to use for `contour serve`. - Values: `envoy` (default), `contour (deprecated)`. - Other values will produce an error. - Deprecated: this field will be removed in a future release when - the `contour` xDS server implementation is removed. - type: string type: object type: object type: object diff --git a/examples/render/contour-gateway-provisioner.yaml b/examples/render/contour-gateway-provisioner.yaml index b3633a2e0cd..dc702aa534a 100644 --- a/examples/render/contour-gateway-provisioner.yaml +++ b/examples/render/contour-gateway-provisioner.yaml @@ -1155,14 +1155,6 @@ spec: description: Client key filename. type: string type: object - type: - description: |- - Defines the XDSServer to use for `contour serve`. - Values: `envoy` (default), `contour (deprecated)`. - Other values will produce an error. - Deprecated: this field will be removed in a future release when - the `contour` xDS server implementation is removed. - type: string type: object type: object status: @@ -4939,14 +4931,6 @@ spec: description: Client key filename. type: string type: object - type: - description: |- - Defines the XDSServer to use for `contour serve`. - Values: `envoy` (default), `contour (deprecated)`. - Other values will produce an error. - Deprecated: this field will be removed in a future release when - the `contour` xDS server implementation is removed. - type: string type: object type: object type: object diff --git a/examples/render/contour-gateway.yaml b/examples/render/contour-gateway.yaml index 0db31e989d5..d4c8b9a5fce 100644 --- a/examples/render/contour-gateway.yaml +++ b/examples/render/contour-gateway.yaml @@ -1180,14 +1180,6 @@ spec: description: Client key filename. type: string type: object - type: - description: |- - Defines the XDSServer to use for `contour serve`. - Values: `envoy` (default), `contour (deprecated)`. - Other values will produce an error. - Deprecated: this field will be removed in a future release when - the `contour` xDS server implementation is removed. - type: string type: object type: object status: @@ -4964,14 +4956,6 @@ spec: description: Client key filename. type: string type: object - type: - description: |- - Defines the XDSServer to use for `contour serve`. - Values: `envoy` (default), `contour (deprecated)`. - Other values will produce an error. - Deprecated: this field will be removed in a future release when - the `contour` xDS server implementation is removed. - type: string type: object type: object type: object diff --git a/examples/render/contour.yaml b/examples/render/contour.yaml index d78bac68c7b..f2cac03d590 100644 --- a/examples/render/contour.yaml +++ b/examples/render/contour.yaml @@ -39,11 +39,6 @@ metadata: namespace: projectcontour data: contour.yaml: | - # - # server: - # determine which XDS Server implementation to utilize in Contour. - # xds-server-type: envoy - # # Specify the Gateway API configuration. # gateway: # namespace: projectcontour @@ -1364,14 +1359,6 @@ spec: description: Client key filename. type: string type: object - type: - description: |- - Defines the XDSServer to use for `contour serve`. - Values: `envoy` (default), `contour (deprecated)`. - Other values will produce an error. - Deprecated: this field will be removed in a future release when - the `contour` xDS server implementation is removed. - type: string type: object type: object status: @@ -5148,14 +5135,6 @@ spec: description: Client key filename. type: string type: object - type: - description: |- - Defines the XDSServer to use for `contour serve`. - Values: `envoy` (default), `contour (deprecated)`. - Other values will produce an error. - Deprecated: this field will be removed in a future release when - the `contour` xDS server implementation is removed. - type: string type: object type: object type: object diff --git a/internal/contour/cond.go b/internal/contour/cond.go deleted file mode 100644 index 031c57ed4cf..00000000000 --- a/internal/contour/cond.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright Project Contour 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 contour - -import "sync" - -// Cond implements a condition variable, a rendezvous point for goroutines -// waiting for or announcing the ocurence of an event. -// -// Unlike sync.Cond, Cond communciates with waiters via channels registered by -// the waiters. This permits goroutines to wait on Cond events using select. -type Cond struct { - mu sync.Mutex - waiters []waiter - last int -} - -type waiter struct { - ch chan int - hints []string -} - -// Register registers ch to receive a value when Notify is called. -// The value of last is the count of the times Notify has been called on this Cond. -// It functions of a sequence counter, if the value of last supplied to Register -// is less than the Conds internal counter, then the caller has missed at least -// one notification and will fire immediately. -// -// Sends by the broadcaster to ch must not block, therefore ch must have a capacity -// of at least 1. -func (c *Cond) Register(ch chan int, last int, hints ...string) { - c.mu.Lock() - defer c.mu.Unlock() - - if last < c.last { - // notify this channel immediately - ch <- c.last - return - } - c.waiters = append(c.waiters, waiter{ - ch: ch, - hints: hints, - }) -} - -// Notify notifies all interested waiters that an event has ocured. -func (c *Cond) Notify(hints ...string) { - c.mu.Lock() - defer c.mu.Unlock() - c.last++ - - notify := c.waiters - c.waiters = nil - - for _, waiter := range notify { - if len(hints) == 0 { - // notify unconditionally - waiter.ch <- c.last - continue - } - if intersection(hints, waiter.hints) { - // one of the hints registered has been notified - waiter.ch <- c.last - continue - } - - // not notified this time, put back on the list - c.waiters = append(c.waiters, waiter) - } -} - -// intersection returns true if the set of elements in left -// intersects with the set in right. -func intersection(left, right []string) bool { - for _, l := range left { - for _, r := range right { - if l == r { - return true - } - } - } - return false -} diff --git a/internal/contour/cond_test.go b/internal/contour/cond_test.go deleted file mode 100644 index 8ff9d6d74f9..00000000000 --- a/internal/contour/cond_test.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright Project Contour 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 contour - -import ( - "testing" -) - -func TestCondRegisterBeforeNotifyShouldNotBroadcast(t *testing.T) { - var c Cond - ch := make(chan int, 1) - c.Register(ch, 0) - select { - case <-ch: - t.Fatal("ch was notified before broadcast") - default: - } -} - -func TestCondRegisterAfterNotifyShouldBroadcast(t *testing.T) { - var c Cond - ch := make(chan int, 1) - c.Notify() - c.Register(ch, 0) - select { - case v := <-ch: - if v != 1 { - t.Fatal("ch was notified with the wrong sequence number", v) - } - default: - t.Fatal("ch was not notified on registration") - } -} - -func TestCondRegisterAfterNotifyWithCorrectSequenceShouldNotBroadcast(t *testing.T) { - var c Cond - ch := make(chan int, 1) - c.Notify() - c.Register(ch, 0) - seq := <-ch - - c.Register(ch, seq) - select { - case v := <-ch: - t.Fatal("ch was notified immediately with seq", v) - default: - } -} - -func TestCondRegisterWithHintShouldNotifyWithoutHint(t *testing.T) { - var c Cond - ch := make(chan int, 1) - c.Register(ch, 1, "ingress_https") - c.Notify() - select { - case v := <-ch: - if v != 1 { - t.Fatal("ch was notified with the wrong sequence number", v) - } - default: - t.Fatal("ch was not notified") - } -} - -func TestCondRegisterWithHintShouldNotifyWithHint(t *testing.T) { - var c Cond - ch := make(chan int, 1) - c.Register(ch, 1, "ingress_https") - c.Notify("ingress_https") - select { - case v := <-ch: - if v != 1 { - t.Fatal("ch was notified with the wrong sequence number", v) - } - default: - t.Fatal("ch was not notified") - } -} - -func TestCondRegisterWithHintShouldNotNotifyWithWrongHint(t *testing.T) { - var c Cond - ch := make(chan int, 1) - c.Register(ch, 1, "ingress_https") - c.Notify("banana") - select { - case v := <-ch: - t.Fatal("ch was notified when it should not be", v) - default: - } - c.Notify("ingress_https") - select { - case v := <-ch: - if v != 2 { - t.Fatal("ch was notified with the wrong sequence number", v) - } - default: - t.Fatal("ch was not notified") - } -} diff --git a/internal/contour/example_test.go b/internal/contour/example_test.go deleted file mode 100644 index 5d0a5f94916..00000000000 --- a/internal/contour/example_test.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright Project Contour 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 contour - -import ( - "context" - "fmt" - "time" -) - -func ExampleCond() { - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) - defer cancel() - ch := make(chan int, 1) - last := 0 - var c Cond - go func() { - for { - time.Sleep(100 * time.Millisecond) - c.Notify() - } - }() - - for { - c.Register(ch, last) - select { - case last = <-ch: - fmt.Println("notification received:", last) - case <-ctx.Done(): - fmt.Println("timeout") - return - } - } -} diff --git a/internal/contourconfig/contourconfiguration.go b/internal/contourconfig/contourconfiguration.go index 0c369f170cb..44539247e0f 100644 --- a/internal/contourconfig/contourconfiguration.go +++ b/internal/contourconfig/contourconfiguration.go @@ -41,7 +41,6 @@ func OverlayOnDefaults(spec contour_v1alpha1.ContourConfigurationSpec) (contour_ func Defaults() contour_v1alpha1.ContourConfigurationSpec { return contour_v1alpha1.ContourConfigurationSpec{ XDSServer: &contour_v1alpha1.XDSServerConfig{ - Type: contour_v1alpha1.EnvoyServerType, Address: "0.0.0.0", Port: 8001, TLS: &contour_v1alpha1.TLS{ diff --git a/internal/contourconfig/contourconfiguration_test.go b/internal/contourconfig/contourconfiguration_test.go index bb13b8229da..8b7c6fb6495 100644 --- a/internal/contourconfig/contourconfiguration_test.go +++ b/internal/contourconfig/contourconfiguration_test.go @@ -30,7 +30,6 @@ import ( func TestOverlayOnDefaults(t *testing.T) { allFieldsSpecified := contour_v1alpha1.ContourConfigurationSpec{ XDSServer: &contour_v1alpha1.XDSServerConfig{ - Type: contour_v1alpha1.EnvoyServerType, Address: "7.7.7.7", Port: 7777, TLS: &contour_v1alpha1.TLS{ diff --git a/internal/xds/resource.go b/internal/xds/resource.go index a7191f0018d..0bc7568c7bc 100644 --- a/internal/xds/resource.go +++ b/internal/xds/resource.go @@ -14,8 +14,6 @@ package xds import ( - "sync/atomic" - "google.golang.org/protobuf/proto" ) @@ -25,19 +23,6 @@ type Resource interface { // Contents returns the contents of this resource. Contents() []proto.Message - // Query returns an entry for each resource name supplied. - Query(names []string) []proto.Message - - // Register registers ch to receive a value when Notify is called. - Register(chan int, int, ...string) - // TypeURL returns the typeURL of messages returned from Values. TypeURL() string } - -// Counter holds an atomically incrementing counter. -type Counter uint64 - -func (c *Counter) Next() uint64 { - return atomic.AddUint64((*uint64)(c), 1) -} diff --git a/internal/xds/resource_test.go b/internal/xds/resource_test.go deleted file mode 100644 index 61e4cc2b937..00000000000 --- a/internal/xds/resource_test.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright Project Contour 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 xds - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestCounterNext(t *testing.T) { - var c Counter - // not a map this time as we want tests to execute - // in sequence. - tests := []struct { - fn func() uint64 - want uint64 - }{{ - fn: c.Next, - want: 1, - }, { - fn: c.Next, - want: 2, - }, { - fn: c.Next, - want: 3, - }} - - for _, tc := range tests { - got := tc.fn() - assert.Equal(t, tc.want, got) - } -} diff --git a/internal/xds/v3/callbacks.go b/internal/xds/v3/callbacks.go index 546105afba7..4801f87a010 100644 --- a/internal/xds/v3/callbacks.go +++ b/internal/xds/v3/callbacks.go @@ -61,9 +61,8 @@ func logStreamClosedDetails(l logrus.FieldLogger, streamID int64, node *envoy_co } // Helper function for use in the Envoy xDS server callbacks and the Contour -// xDS server to log request details. Returns logger with fields added for any -// subsequent error handling and logging. -func logDiscoveryRequestDetails(l logrus.FieldLogger, req *envoy_service_discovery_v3.DiscoveryRequest) *logrus.Entry { +// xDS server to log request details. +func logDiscoveryRequestDetails(l logrus.FieldLogger, req *envoy_service_discovery_v3.DiscoveryRequest) { log := l.WithField("version_info", req.VersionInfo).WithField("response_nonce", req.ResponseNonce) if req.Node != nil { log = log.WithField("node_id", req.Node.Id) @@ -82,6 +81,4 @@ func logDiscoveryRequestDetails(l logrus.FieldLogger, req *envoy_service_discove log = log.WithField("resource_names", req.ResourceNames).WithField("type_url", req.GetTypeUrl()) log.Debug("handling v3 xDS resource request") - - return log } diff --git a/internal/xds/v3/contour.go b/internal/xds/v3/contour.go deleted file mode 100644 index ce00f6b93ee..00000000000 --- a/internal/xds/v3/contour.go +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright Project Contour 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 v3 - -import ( - "context" - "fmt" - "strconv" - - envoy_service_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/service/cluster/v3" - envoy_service_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" - envoy_service_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/service/endpoint/v3" - envoy_service_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/service/listener/v3" - envoy_service_route_v3 "github.com/envoyproxy/go-control-plane/envoy/service/route/v3" - envoy_service_runtime_v3 "github.com/envoyproxy/go-control-plane/envoy/service/runtime/v3" - envoy_service_secret_v3 "github.com/envoyproxy/go-control-plane/envoy/service/secret/v3" - "github.com/sirupsen/logrus" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/projectcontour/contour/internal/xds" -) - -type grpcStream interface { - Context() context.Context - Send(*envoy_service_discovery_v3.DiscoveryResponse) error - Recv() (*envoy_service_discovery_v3.DiscoveryRequest, error) -} - -// NewContourServer creates an internally implemented Server that streams the -// provided set of Resource objects. The returned Server implements the xDS -// State of the World (SotW) variant. -func NewContourServer(log logrus.FieldLogger, resources ...xds.Resource) Server { - c := contourServer{ - FieldLogger: log, - resources: map[string]xds.Resource{}, - } - - for i, r := range resources { - c.resources[r.TypeURL()] = resources[i] - } - - return &c -} - -type contourServer struct { - // Since we only implement the streaming state of the world - // protocol, embed the default null implementations to handle - // the unimplemented gRPC endpoints. - envoy_service_discovery_v3.UnimplementedAggregatedDiscoveryServiceServer - envoy_service_secret_v3.UnimplementedSecretDiscoveryServiceServer - envoy_service_route_v3.UnimplementedRouteDiscoveryServiceServer - envoy_service_endpoint_v3.UnimplementedEndpointDiscoveryServiceServer - envoy_service_cluster_v3.UnimplementedClusterDiscoveryServiceServer - envoy_service_listener_v3.UnimplementedListenerDiscoveryServiceServer - envoy_service_runtime_v3.UnimplementedRuntimeDiscoveryServiceServer - - logrus.FieldLogger - resources map[string]xds.Resource - connections xds.Counter -} - -// stream processes a stream of DiscoveryRequests. -func (s *contourServer) stream(st grpcStream) error { - // Bump connection counter and set it as a field on the logger. - log := s.WithField("connection", s.connections.Next()) - - // Notify whether the stream terminated on error. - done := func(log logrus.FieldLogger, err error) error { - // If the stream has been closed by the client "gracefully", - // do not log as an error. - if err != nil && err != context.Canceled && status.Code(err) != codes.Canceled { - log.WithError(err).Error("stream terminated") - return err - } - log.Debug("stream terminated") - return nil - } - - ch := make(chan int, 1) - - // internally all registration values start at zero so sending - // a last that is less than zero will guarantee that each stream - // will generate a response immediately, then wait. - last := -1 - ctx := st.Context() - - // now stick in this loop until the client disconnects. - for { - // first we wait for the request from Envoy, this is part of - // the xDS protocol. - req, err := st.Recv() - if err != nil { - return done(log, err) - } - - // Note: redeclare log in this scope so the next time around the loop all is forgotten. - log := logDiscoveryRequestDetails(log, req) - - // From the request we derive the resource to stream which have - // been registered according to the typeURL. - r, ok := s.resources[req.GetTypeUrl()] - if !ok { - return done(log, fmt.Errorf("no resource registered for typeURL %q", req.GetTypeUrl())) - } - - // now we wait for a notification, if this is the first request received on this - // connection last will be less than zero and that will trigger a response immediately. - r.Register(ch, last, req.ResourceNames...) - select { - case last = <-ch: - // boom, something in the cache has changed. - // TODO(dfc) the thing that has changed may not be in the scope of the filter - // so we're going to be sending an update that is a no-op. See #426 - - var resources []proto.Message - switch len(req.ResourceNames) { - case 0: - // no resource hints supplied, return the full - // contents of the resource - resources = r.Contents() - default: - // resource hints supplied, return exactly those - resources = r.Query(req.ResourceNames) - } - - anyResources := make([]*anypb.Any, 0, len(resources)) - for _, r := range resources { - a, err := anypb.New(r) - if err != nil { - return done(log, err) - } - anyResources = append(anyResources, a) - } - - resp := &envoy_service_discovery_v3.DiscoveryResponse{ - VersionInfo: strconv.Itoa(last), - Resources: anyResources, - TypeUrl: req.GetTypeUrl(), - Nonce: strconv.Itoa(last), - } - - if err := st.Send(resp); err != nil { - return done(log, err) - } - - case <-ctx.Done(): - return done(log, ctx.Err()) - } - } -} - -func (s *contourServer) StreamClusters(srv envoy_service_cluster_v3.ClusterDiscoveryService_StreamClustersServer) error { - return s.stream(srv) -} - -func (s *contourServer) StreamEndpoints(srv envoy_service_endpoint_v3.EndpointDiscoveryService_StreamEndpointsServer) error { - return s.stream(srv) -} - -func (s *contourServer) StreamListeners(srv envoy_service_listener_v3.ListenerDiscoveryService_StreamListenersServer) error { - return s.stream(srv) -} - -func (s *contourServer) StreamRoutes(srv envoy_service_route_v3.RouteDiscoveryService_StreamRoutesServer) error { - return s.stream(srv) -} - -func (s *contourServer) StreamSecrets(srv envoy_service_secret_v3.SecretDiscoveryService_StreamSecretsServer) error { - return s.stream(srv) -} - -func (s *contourServer) StreamRuntime(srv envoy_service_runtime_v3.RuntimeDiscoveryService_StreamRuntimeServer) error { - return s.stream(srv) -} diff --git a/internal/xds/v3/contour_test.go b/internal/xds/v3/contour_test.go deleted file mode 100644 index d2587b6dfa1..00000000000 --- a/internal/xds/v3/contour_test.go +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright Project Contour 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 v3 - -import ( - "context" - "errors" - "fmt" - "io" - "testing" - - envoy_config_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" - envoy_service_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" - "github.com/sirupsen/logrus" - "github.com/sirupsen/logrus/hooks/test" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/runtime/protoimpl" - - "github.com/projectcontour/contour/internal/fixture" - "github.com/projectcontour/contour/internal/xds" -) - -func TestXDSHandlerStream(t *testing.T) { - log := fixture.NewDiscardLogger() - tests := map[string]struct { - xh contourServer - stream grpcStream - want error - }{ - "recv returns error immediately": { - xh: contourServer{FieldLogger: log}, - stream: &mockStream{ - context: context.Background, - recv: func() (*envoy_service_discovery_v3.DiscoveryRequest, error) { - return nil, io.EOF - }, - }, - want: io.EOF, - }, - "no registered typeURL": { - xh: contourServer{FieldLogger: log}, - stream: &mockStream{ - context: context.Background, - recv: func() (*envoy_service_discovery_v3.DiscoveryRequest, error) { - return &envoy_service_discovery_v3.DiscoveryRequest{ - TypeUrl: "io.projectcontour.potato", - }, nil - }, - }, - want: fmt.Errorf("no resource registered for typeURL %q", "io.projectcontour.potato"), - }, - "failed to convert values to any": { - xh: contourServer{ - FieldLogger: log, - resources: map[string]xds.Resource{ - "io.projectcontour.potato": &mockResource{ - register: func(ch chan int, i int) { - ch <- i + 1 - }, - contents: func() []proto.Message { - return []proto.Message{nil} - }, - typeurl: func() string { return "io.projectcontour.potato" }, - }, - }, - }, - stream: &mockStream{ - context: context.Background, - recv: func() (*envoy_service_discovery_v3.DiscoveryRequest, error) { - return &envoy_service_discovery_v3.DiscoveryRequest{ - TypeUrl: "io.projectcontour.potato", - }, nil - }, - }, - want: protoimpl.X.NewError("invalid nil source message"), - }, - "failed to send": { - xh: contourServer{ - FieldLogger: log, - resources: map[string]xds.Resource{ - "io.projectcontour.potato": &mockResource{ - register: func(ch chan int, i int) { - ch <- i + 1 - }, - contents: func() []proto.Message { - return []proto.Message{new(envoy_config_endpoint_v3.ClusterLoadAssignment)} - }, - typeurl: func() string { return "io.projectcontour.potato" }, - }, - }, - }, - stream: &mockStream{ - context: context.Background, - recv: func() (*envoy_service_discovery_v3.DiscoveryRequest, error) { - return &envoy_service_discovery_v3.DiscoveryRequest{ - TypeUrl: "io.projectcontour.potato", - }, nil - }, - send: func(*envoy_service_discovery_v3.DiscoveryResponse) error { - return io.EOF - }, - }, - want: io.EOF, - }, - "context canceled": { - xh: contourServer{ - FieldLogger: log, - resources: map[string]xds.Resource{ - "io.projectcontour.potato": &mockResource{ - register: func(chan int, int) { - // do nothing - }, - typeurl: func() string { return "io.projectcontour.potato" }, - }, - }, - }, - stream: &mockStream{ - context: func() context.Context { - ctx := context.Background() - ctx, cancel := context.WithCancel(ctx) - cancel() - return ctx - }, - recv: func() (*envoy_service_discovery_v3.DiscoveryRequest, error) { - return &envoy_service_discovery_v3.DiscoveryRequest{ - TypeUrl: "io.projectcontour.potato", - }, nil - }, - send: func(*envoy_service_discovery_v3.DiscoveryResponse) error { - return io.EOF - }, - }, - want: nil, - }, - } - - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - got := tc.xh.stream(tc.stream) - assert.Equal(t, tc.want, got) - }) - } -} - -func TestStreamLoggingConnectionClose(t *testing.T) { - log, logHook := test.NewNullLogger() - log.SetLevel(logrus.DebugLevel) - - tests := map[string]struct { - closeErr error - wantErr bool - wantLogLevel logrus.Level - }{ - "connection closed w/ context.Canceled": { - closeErr: context.Canceled, - wantLogLevel: logrus.DebugLevel, - }, - "connection closed w/ rpc error": { - closeErr: status.Error(codes.Canceled, "error canceled"), - wantLogLevel: logrus.DebugLevel, - }, - "connection closed w/ some other error": { - closeErr: errors.New("some other error"), - wantLogLevel: logrus.ErrorLevel, - wantErr: true, - }, - } - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - server := contourServer{FieldLogger: log} - stream := &mockStream{ - context: context.Background, - recv: func() (*envoy_service_discovery_v3.DiscoveryRequest, error) { - return nil, tc.closeErr - }, - } - err := server.stream(stream) - - assert.Len(t, logHook.AllEntries(), 1) - entry := logHook.AllEntries()[0] - assert.Equal(t, "stream terminated", entry.Message) - assert.Equal(t, tc.wantLogLevel, entry.Level) - - if tc.wantErr { - assert.Equal(t, tc.closeErr, err) - assert.Equal(t, tc.closeErr, entry.Data["error"]) - } else { - require.NoError(t, err) - } - - logHook.Reset() - }) - } -} - -type mockStream struct { - context func() context.Context - send func(*envoy_service_discovery_v3.DiscoveryResponse) error - recv func() (*envoy_service_discovery_v3.DiscoveryRequest, error) -} - -func (m *mockStream) Context() context.Context { return m.context() } -func (m *mockStream) Send(resp *envoy_service_discovery_v3.DiscoveryResponse) error { - return m.send(resp) -} -func (m *mockStream) Recv() (*envoy_service_discovery_v3.DiscoveryRequest, error) { return m.recv() } - -type mockResource struct { - contents func() []proto.Message - query func([]string) []proto.Message - register func(chan int, int) - typeurl func() string -} - -func (m *mockResource) Contents() []proto.Message { return m.contents() } -func (m *mockResource) Query(names []string) []proto.Message { return m.query(names) } -func (m *mockResource) Register(ch chan int, last int, _ ...string) { m.register(ch, last) } -func (m *mockResource) TypeURL() string { return m.typeurl() } diff --git a/internal/xdscache/v3/cluster.go b/internal/xdscache/v3/cluster.go index 115f96d01e4..da0e3ba6824 100644 --- a/internal/xdscache/v3/cluster.go +++ b/internal/xdscache/v3/cluster.go @@ -21,7 +21,6 @@ import ( resource "github.com/envoyproxy/go-control-plane/pkg/resource/v3" "google.golang.org/protobuf/proto" - "github.com/projectcontour/contour/internal/contour" "github.com/projectcontour/contour/internal/dag" "github.com/projectcontour/contour/internal/envoy" envoy_v3 "github.com/projectcontour/contour/internal/envoy/v3" @@ -33,7 +32,6 @@ import ( type ClusterCache struct { mu sync.Mutex values map[string]*envoy_config_cluster_v3.Cluster - contour.Cond } // Update replaces the contents of the cache with the supplied map. @@ -42,7 +40,6 @@ func (c *ClusterCache) Update(v map[string]*envoy_config_cluster_v3.Cluster) { defer c.mu.Unlock() c.values = v - c.Cond.Notify() } // Contents returns a copy of the cache's contents. @@ -57,24 +54,6 @@ func (c *ClusterCache) Contents() []proto.Message { return protobuf.AsMessages(values) } -func (c *ClusterCache) Query(names []string) []proto.Message { - c.mu.Lock() - defer c.mu.Unlock() - var values []*envoy_config_cluster_v3.Cluster - for _, n := range names { - // if the cluster is not registered we cannot return - // a blank cluster because each cluster has a required - // discovery type; DNS, EDS, etc. We cannot determine the - // correct value for this property from the cluster's name - // provided by the query so we must not return a blank cluster. - if v, ok := c.values[n]; ok { - values = append(values, v) - } - } - sort.Stable(sorter.For(values)) - return protobuf.AsMessages(values) -} - func (*ClusterCache) TypeURL() string { return resource.ClusterType } func (c *ClusterCache) OnChange(root *dag.DAG) { diff --git a/internal/xdscache/v3/cluster_test.go b/internal/xdscache/v3/cluster_test.go index b370948c6e8..026e8e67d41 100644 --- a/internal/xdscache/v3/cluster_test.go +++ b/internal/xdscache/v3/cluster_test.go @@ -78,86 +78,6 @@ func TestClusterCacheContents(t *testing.T) { } } -func TestClusterCacheQuery(t *testing.T) { - tests := map[string]struct { - contents map[string]*envoy_config_cluster_v3.Cluster - query []string - want []proto.Message - }{ - "exact match": { - contents: clustermap( - &envoy_config_cluster_v3.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy_v3.ClusterDiscoveryType(envoy_config_cluster_v3.Cluster_EDS), - EdsClusterConfig: &envoy_config_cluster_v3.Cluster_EdsClusterConfig{ - EdsConfig: envoy_v3.ConfigSource("contour"), - ServiceName: "default/kuard", - }, - }), - query: []string{"default/kuard/443/da39a3ee5e"}, - want: []proto.Message{ - cluster(&envoy_config_cluster_v3.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy_v3.ClusterDiscoveryType(envoy_config_cluster_v3.Cluster_EDS), - EdsClusterConfig: &envoy_config_cluster_v3.Cluster_EdsClusterConfig{ - EdsConfig: envoy_v3.ConfigSource("contour"), - ServiceName: "default/kuard", - }, - }), - }, - }, - "partial match": { - contents: clustermap( - &envoy_config_cluster_v3.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy_v3.ClusterDiscoveryType(envoy_config_cluster_v3.Cluster_EDS), - EdsClusterConfig: &envoy_config_cluster_v3.Cluster_EdsClusterConfig{ - EdsConfig: envoy_v3.ConfigSource("contour"), - ServiceName: "default/kuard", - }, - }), - query: []string{"default/kuard/443/da39a3ee5e", "foo/bar/baz"}, - want: []proto.Message{ - cluster(&envoy_config_cluster_v3.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy_v3.ClusterDiscoveryType(envoy_config_cluster_v3.Cluster_EDS), - EdsClusterConfig: &envoy_config_cluster_v3.Cluster_EdsClusterConfig{ - EdsConfig: envoy_v3.ConfigSource("contour"), - ServiceName: "default/kuard", - }, - }), - }, - }, - "no match": { - contents: clustermap( - &envoy_config_cluster_v3.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy_v3.ClusterDiscoveryType(envoy_config_cluster_v3.Cluster_EDS), - EdsClusterConfig: &envoy_config_cluster_v3.Cluster_EdsClusterConfig{ - EdsConfig: envoy_v3.ConfigSource("contour"), - ServiceName: "default/kuard", - }, - }), - query: []string{"foo/bar/baz"}, - want: nil, - }, - } - - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - var cc ClusterCache - cc.Update(tc.contents) - got := cc.Query(tc.query) - protobuf.ExpectEqual(t, tc.want, got) - }) - } -} - func TestClusterVisit(t *testing.T) { tests := map[string]struct { objs []any diff --git a/internal/xdscache/v3/endpointslicetranslator.go b/internal/xdscache/v3/endpointslicetranslator.go index a4266ea7f9b..0e2fcb9740c 100644 --- a/internal/xdscache/v3/endpointslicetranslator.go +++ b/internal/xdscache/v3/endpointslicetranslator.go @@ -271,7 +271,6 @@ func (c *EndpointSliceCache) DeleteEndpointSlice(endpointSlice *discovery_v1.End // NewEndpointSliceTranslator allocates a new endpointsSlice translator. func NewEndpointSliceTranslator(log logrus.FieldLogger) *EndpointSliceTranslator { return &EndpointSliceTranslator{ - Cond: contour.Cond{}, FieldLogger: log, entries: map[string]*envoy_config_endpoint_v3.ClusterLoadAssignment{}, cache: EndpointSliceCache{ @@ -288,7 +287,6 @@ type EndpointSliceTranslator struct { // Observer notifies when the endpointSlice cache has been updated. Observer contour.Observer - contour.Cond logrus.FieldLogger cache EndpointSliceCache @@ -350,7 +348,6 @@ func (e *EndpointSliceTranslator) OnChange(root *dag.DAG) { if changed { e.Debug("cluster load assignments changed, notifying waiters") - e.Notify() if e.Observer != nil { e.Observer.Refresh() } @@ -368,7 +365,6 @@ func (e *EndpointSliceTranslator) OnAdd(obj any, _ bool) { e.WithField("endpointSlice", k8s.NamespacedNameOf(obj)).Debug("EndpointSlice is in use by a ServiceCluster, recalculating ClusterLoadAssignments") e.Merge(e.cache.Recalculate()) - e.Notify() if e.Observer != nil { e.Observer.Refresh() } @@ -405,7 +401,6 @@ func (e *EndpointSliceTranslator) OnUpdate(oldObj, newObj any) { e.WithField("endpointSlice", k8s.NamespacedNameOf(newObj)).Debug("EndpointSlice is in use by a ServiceCluster, recalculating ClusterLoadAssignments") e.Merge(e.cache.Recalculate()) - e.Notify() if e.Observer != nil { e.Observer.Refresh() } @@ -423,7 +418,6 @@ func (e *EndpointSliceTranslator) OnDelete(obj any) { e.WithField("endpointSlice", k8s.NamespacedNameOf(obj)).Debug("EndpointSlice was in use by a ServiceCluster, recalculating ClusterLoadAssignments") e.Merge(e.cache.Recalculate()) - e.Notify() if e.Observer != nil { e.Observer.Refresh() } @@ -448,26 +442,6 @@ func (e *EndpointSliceTranslator) Contents() []proto.Message { return protobuf.AsMessages(values) } -func (e *EndpointSliceTranslator) Query(names []string) []proto.Message { - e.mu.Lock() - defer e.mu.Unlock() - - values := make([]*envoy_config_endpoint_v3.ClusterLoadAssignment, 0, len(names)) - for _, n := range names { - v, ok := e.entries[n] - if !ok { - e.Debugf("no cache entry for %q", n) - v = &envoy_config_endpoint_v3.ClusterLoadAssignment{ - ClusterName: n, - } - } - values = append(values, v) - } - - sort.Stable(sorter.For(values)) - return protobuf.AsMessages(values) -} - func (*EndpointSliceTranslator) TypeURL() string { return resource.EndpointType } func (e *EndpointSliceTranslator) SetObserver(observer contour.Observer) { e.Observer = observer } diff --git a/internal/xdscache/v3/endpointslicetranslator_test.go b/internal/xdscache/v3/endpointslicetranslator_test.go index 70250a02f6a..a902b5ae4f9 100644 --- a/internal/xdscache/v3/endpointslicetranslator_test.go +++ b/internal/xdscache/v3/endpointslicetranslator_test.go @@ -62,62 +62,6 @@ func TestEndpointSliceTranslatorContents(t *testing.T) { } } -func TestEndpointSliceCacheQuery(t *testing.T) { - tests := map[string]struct { - contents map[string]*envoy_config_endpoint_v3.ClusterLoadAssignment - query []string - want []proto.Message - }{ - "exact match": { - contents: clusterloadassignments( - envoy_v3.ClusterLoadAssignment("default/httpbin-org", - envoy_v3.SocketAddress("10.10.10.10", 80), - ), - ), - query: []string{"default/httpbin-org"}, - want: []proto.Message{ - envoy_v3.ClusterLoadAssignment("default/httpbin-org", - envoy_v3.SocketAddress("10.10.10.10", 80), - ), - }, - }, - "partial match": { - contents: clusterloadassignments( - envoy_v3.ClusterLoadAssignment("default/httpbin-org", - envoy_v3.SocketAddress("10.10.10.10", 80), - ), - ), - query: []string{"default/kuard/8080", "default/httpbin-org"}, - want: []proto.Message{ - envoy_v3.ClusterLoadAssignment("default/httpbin-org", - envoy_v3.SocketAddress("10.10.10.10", 80), - ), - envoy_v3.ClusterLoadAssignment("default/kuard/8080"), - }, - }, - "no match": { - contents: clusterloadassignments( - envoy_v3.ClusterLoadAssignment("default/httpbin-org", - envoy_v3.SocketAddress("10.10.10.10", 80), - ), - ), - query: []string{"default/kuard/8080"}, - want: []proto.Message{ - envoy_v3.ClusterLoadAssignment("default/kuard/8080"), - }, - }, - } - - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - endpointSliceTranslator := NewEndpointSliceTranslator(fixture.NewTestLogger(t)) - endpointSliceTranslator.entries = tc.contents - got := endpointSliceTranslator.Query(tc.query) - protobuf.ExpectEqual(t, tc.want, got) - }) - } -} - func TestEndpointSliceTranslatorAddEndpoints(t *testing.T) { clusters := []*dag.ServiceCluster{ { diff --git a/internal/xdscache/v3/endpointstranslator.go b/internal/xdscache/v3/endpointstranslator.go index 5095dc84ce3..6a588c3ebdb 100644 --- a/internal/xdscache/v3/endpointstranslator.go +++ b/internal/xdscache/v3/endpointstranslator.go @@ -246,7 +246,6 @@ func (c *EndpointsCache) DeleteEndpoint(eps *core_v1.Endpoints) bool { // NewEndpointsTranslator allocates a new endpoints translator. func NewEndpointsTranslator(log logrus.FieldLogger) *EndpointsTranslator { return &EndpointsTranslator{ - Cond: contour.Cond{}, FieldLogger: log, entries: map[string]*envoy_config_endpoint_v3.ClusterLoadAssignment{}, cache: EndpointsCache{ @@ -263,7 +262,6 @@ type EndpointsTranslator struct { // Observer notifies when the endpoints cache has been updated. Observer contour.Observer - contour.Cond logrus.FieldLogger cache EndpointsCache @@ -325,7 +323,6 @@ func (e *EndpointsTranslator) OnChange(root *dag.DAG) { if changed { e.Debug("cluster load assignments changed, notifying waiters") - e.Notify() if e.Observer != nil { e.Observer.Refresh() } @@ -363,7 +360,6 @@ func (e *EndpointsTranslator) OnAdd(obj any, _ bool) { e.WithField("endpoint", k8s.NamespacedNameOf(obj)).Debug("Endpoint is in use by a ServiceCluster, recalculating ClusterLoadAssignments") e.Merge(e.cache.Recalculate()) - e.Notify() if e.Observer != nil { e.Observer.Refresh() } @@ -400,7 +396,6 @@ func (e *EndpointsTranslator) OnUpdate(oldObj, newObj any) { e.WithField("endpoint", k8s.NamespacedNameOf(newObj)).Debug("Endpoint is in use by a ServiceCluster, recalculating ClusterLoadAssignments") e.Merge(e.cache.Recalculate()) - e.Notify() if e.Observer != nil { e.Observer.Refresh() } @@ -418,7 +413,6 @@ func (e *EndpointsTranslator) OnDelete(obj any) { e.WithField("endpoint", k8s.NamespacedNameOf(obj)).Debug("Endpoint was in use by a ServiceCluster, recalculating ClusterLoadAssignments") e.Merge(e.cache.Recalculate()) - e.Notify() if e.Observer != nil { e.Observer.Refresh() } @@ -443,26 +437,6 @@ func (e *EndpointsTranslator) Contents() []proto.Message { return protobuf.AsMessages(values) } -func (e *EndpointsTranslator) Query(names []string) []proto.Message { - e.mu.Lock() - defer e.mu.Unlock() - - values := make([]*envoy_config_endpoint_v3.ClusterLoadAssignment, 0, len(names)) - for _, n := range names { - v, ok := e.entries[n] - if !ok { - e.Debugf("no cache entry for %q", n) - v = &envoy_config_endpoint_v3.ClusterLoadAssignment{ - ClusterName: n, - } - } - values = append(values, v) - } - - sort.Stable(sorter.For(values)) - return protobuf.AsMessages(values) -} - func (*EndpointsTranslator) TypeURL() string { return resource.EndpointType } func (e *EndpointsTranslator) SetObserver(observer contour.Observer) { e.Observer = observer } diff --git a/internal/xdscache/v3/endpointstranslator_test.go b/internal/xdscache/v3/endpointstranslator_test.go index b4be3ab5c0b..5446bd4b519 100644 --- a/internal/xdscache/v3/endpointstranslator_test.go +++ b/internal/xdscache/v3/endpointstranslator_test.go @@ -63,62 +63,6 @@ func TestEndpointsTranslatorContents(t *testing.T) { } } -func TestEndpointCacheQuery(t *testing.T) { - tests := map[string]struct { - contents map[string]*envoy_config_endpoint_v3.ClusterLoadAssignment - query []string - want []proto.Message - }{ - "exact match": { - contents: clusterloadassignments( - envoy_v3.ClusterLoadAssignment("default/httpbin-org", - envoy_v3.SocketAddress("10.10.10.10", 80), - ), - ), - query: []string{"default/httpbin-org"}, - want: []proto.Message{ - envoy_v3.ClusterLoadAssignment("default/httpbin-org", - envoy_v3.SocketAddress("10.10.10.10", 80), - ), - }, - }, - "partial match": { - contents: clusterloadassignments( - envoy_v3.ClusterLoadAssignment("default/httpbin-org", - envoy_v3.SocketAddress("10.10.10.10", 80), - ), - ), - query: []string{"default/kuard/8080", "default/httpbin-org"}, - want: []proto.Message{ - envoy_v3.ClusterLoadAssignment("default/httpbin-org", - envoy_v3.SocketAddress("10.10.10.10", 80), - ), - envoy_v3.ClusterLoadAssignment("default/kuard/8080"), - }, - }, - "no match": { - contents: clusterloadassignments( - envoy_v3.ClusterLoadAssignment("default/httpbin-org", - envoy_v3.SocketAddress("10.10.10.10", 80), - ), - ), - query: []string{"default/kuard/8080"}, - want: []proto.Message{ - envoy_v3.ClusterLoadAssignment("default/kuard/8080"), - }, - }, - } - - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - et := NewEndpointsTranslator(fixture.NewTestLogger(t)) - et.entries = tc.contents - got := et.Query(tc.query) - protobuf.ExpectEqual(t, tc.want, got) - }) - } -} - func TestEndpointsTranslatorAddEndpoints(t *testing.T) { clusters := []*dag.ServiceCluster{ { diff --git a/internal/xdscache/v3/listener.go b/internal/xdscache/v3/listener.go index 6176fdcaad0..2c9db5b9ca3 100644 --- a/internal/xdscache/v3/listener.go +++ b/internal/xdscache/v3/listener.go @@ -26,7 +26,6 @@ import ( "k8s.io/apimachinery/pkg/types" contour_v1alpha1 "github.com/projectcontour/contour/apis/projectcontour/v1alpha1" - "github.com/projectcontour/contour/internal/contour" "github.com/projectcontour/contour/internal/contourconfig" "github.com/projectcontour/contour/internal/dag" envoy_v3 "github.com/projectcontour/contour/internal/envoy/v3" @@ -282,7 +281,6 @@ type ListenerCache struct { staticValues map[string]*envoy_config_listener_v3.Listener Config ListenerConfig - contour.Cond } // NewListenerCache returns an instance of a ListenerCache @@ -317,7 +315,6 @@ func (c *ListenerCache) Update(v map[string]*envoy_config_listener_v3.Listener) defer c.mu.Unlock() c.values = v - c.Cond.Notify() } // Contents returns a copy of the cache's contents. @@ -335,31 +332,6 @@ func (c *ListenerCache) Contents() []proto.Message { return protobuf.AsMessages(values) } -// Query returns the proto.Messages in the ListenerCache that match -// a slice of strings -func (c *ListenerCache) Query(names []string) []proto.Message { - c.mu.Lock() - defer c.mu.Unlock() - var values []*envoy_config_listener_v3.Listener - for _, n := range names { - v, ok := c.values[n] - if !ok { - v, ok = c.staticValues[n] - if !ok { - // if the listener is not registered in - // dynamic or static values then skip it - // as there is no way to return a blank - // listener because the listener address - // field is required. - continue - } - } - values = append(values, v) - } - sort.Stable(sorter.For(values)) - return protobuf.AsMessages(values) -} - func (*ListenerCache) TypeURL() string { return resource.ListenerType } func (c *ListenerCache) OnChange(root *dag.DAG) { diff --git a/internal/xdscache/v3/listener_test.go b/internal/xdscache/v3/listener_test.go index 095f248210a..bb9eafef30c 100644 --- a/internal/xdscache/v3/listener_test.go +++ b/internal/xdscache/v3/listener_test.go @@ -82,68 +82,6 @@ func TestListenerCacheContents(t *testing.T) { } } -func TestListenerCacheQuery(t *testing.T) { - tests := map[string]struct { - contents map[string]*envoy_config_listener_v3.Listener - query []string - want []proto.Message - }{ - "exact match": { - contents: listenermap(&envoy_config_listener_v3.Listener{ - Name: ENVOY_HTTP_LISTENER, - Address: envoy_v3.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, contour_v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), - }), - query: []string{ENVOY_HTTP_LISTENER}, - want: []proto.Message{ - &envoy_config_listener_v3.Listener{ - Name: ENVOY_HTTP_LISTENER, - Address: envoy_v3.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, contour_v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), - }, - }, - }, - "partial match": { - contents: listenermap(&envoy_config_listener_v3.Listener{ - Name: ENVOY_HTTP_LISTENER, - Address: envoy_v3.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, contour_v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), - }), - query: []string{ENVOY_HTTP_LISTENER, "stats-listener"}, - want: []proto.Message{ - &envoy_config_listener_v3.Listener{ - Name: ENVOY_HTTP_LISTENER, - Address: envoy_v3.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, contour_v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), - }, - }, - }, - "no match": { - contents: listenermap(&envoy_config_listener_v3.Listener{ - Name: ENVOY_HTTP_LISTENER, - Address: envoy_v3.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy_v3.FilterChains(envoy_v3.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy_v3.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG, "", nil, contour_v1alpha1.LogLevelInfo), 0)), - SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(), - }), - query: []string{"stats-listener"}, - want: nil, - }, - } - - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - var lc ListenerCache - lc.Update(tc.contents) - got := lc.Query(tc.query) - protobuf.ExpectEqual(t, tc.want, got) - }) - } -} - func TestListenerVisit(t *testing.T) { httpsFilterFor := func(vhost string) *envoy_config_listener_v3.Filter { return envoy_v3.HTTPConnectionManagerBuilder(). diff --git a/internal/xdscache/v3/route.go b/internal/xdscache/v3/route.go index 42c4202a7ca..3e0b21b629a 100644 --- a/internal/xdscache/v3/route.go +++ b/internal/xdscache/v3/route.go @@ -22,7 +22,6 @@ import ( resource "github.com/envoyproxy/go-control-plane/pkg/resource/v3" "google.golang.org/protobuf/proto" - "github.com/projectcontour/contour/internal/contour" "github.com/projectcontour/contour/internal/dag" envoy_v3 "github.com/projectcontour/contour/internal/envoy/v3" "github.com/projectcontour/contour/internal/protobuf" @@ -33,7 +32,6 @@ import ( type RouteCache struct { mu sync.Mutex values map[string]*envoy_config_route_v3.RouteConfiguration - contour.Cond } // Update replaces the contents of the cache with the supplied map. @@ -42,7 +40,6 @@ func (c *RouteCache) Update(v map[string]*envoy_config_route_v3.RouteConfigurati defer c.mu.Unlock() c.values = v - c.Cond.Notify() } // Contents returns a copy of the cache's contents. @@ -59,31 +56,6 @@ func (c *RouteCache) Contents() []proto.Message { return protobuf.AsMessages(values) } -// Query searches the RouteCache for the named RouteConfiguration entries. -func (c *RouteCache) Query(names []string) []proto.Message { - c.mu.Lock() - defer c.mu.Unlock() - - var values []*envoy_config_route_v3.RouteConfiguration - for _, n := range names { - v, ok := c.values[n] - if !ok { - // if there is no route registered with the cache - // we return a blank route configuration. This is - // not the same as returning nil, we're choosing to - // say "the configuration you asked for _does exists_, - // but it contains no useful information. - v = &envoy_config_route_v3.RouteConfiguration{ - Name: n, - } - } - values = append(values, v) - } - - sort.Stable(sorter.For(values)) - return protobuf.AsMessages(values) -} - // TypeURL returns the string type of RouteCache Resource. func (*RouteCache) TypeURL() string { return resource.RouteType } diff --git a/internal/xdscache/v3/route_test.go b/internal/xdscache/v3/route_test.go index b043c4a5a98..496a64d3723 100644 --- a/internal/xdscache/v3/route_test.go +++ b/internal/xdscache/v3/route_test.go @@ -83,66 +83,6 @@ func TestRouteCacheContents(t *testing.T) { } } -func TestRouteCacheQuery(t *testing.T) { - tests := map[string]struct { - contents map[string]*envoy_config_route_v3.RouteConfiguration - query []string - want []proto.Message - }{ - "exact match": { - contents: map[string]*envoy_config_route_v3.RouteConfiguration{ - "ingress_http": { - Name: "ingress_http", - }, - }, - query: []string{"ingress_http"}, - want: []proto.Message{ - &envoy_config_route_v3.RouteConfiguration{ - Name: "ingress_http", - }, - }, - }, - "partial match": { - contents: map[string]*envoy_config_route_v3.RouteConfiguration{ - "ingress_http": { - Name: "ingress_http", - }, - }, - query: []string{"stats-handler", "ingress_http"}, - want: []proto.Message{ - &envoy_config_route_v3.RouteConfiguration{ - Name: "ingress_http", - }, - &envoy_config_route_v3.RouteConfiguration{ - Name: "stats-handler", - }, - }, - }, - "no match": { - contents: map[string]*envoy_config_route_v3.RouteConfiguration{ - "ingress_http": { - Name: "ingress_http", - }, - }, - query: []string{"stats-handler"}, - want: []proto.Message{ - &envoy_config_route_v3.RouteConfiguration{ - Name: "stats-handler", - }, - }, - }, - } - - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - var rc RouteCache - rc.Update(tc.contents) - got := rc.Query(tc.query) - protobuf.ExpectEqual(t, tc.want, got) - }) - } -} - func TestRouteVisit(t *testing.T) { tests := map[string]struct { objs []any diff --git a/internal/xdscache/v3/runtime.go b/internal/xdscache/v3/runtime.go index ce8415f33d5..f062debcb79 100644 --- a/internal/xdscache/v3/runtime.go +++ b/internal/xdscache/v3/runtime.go @@ -21,7 +21,6 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/structpb" - "github.com/projectcontour/contour/internal/contour" "github.com/projectcontour/contour/internal/dag" envoy_v3 "github.com/projectcontour/contour/internal/envoy/v3" "github.com/projectcontour/contour/internal/protobuf" @@ -34,7 +33,6 @@ type ConfigurableRuntimeSettings struct { // RuntimeCache manages the contents of the gRPC RTDS cache. type RuntimeCache struct { - contour.Cond runtimeKV map[string]*structpb.Value dynamicRuntimeKV map[string]*structpb.Value @@ -76,16 +74,6 @@ func (c *RuntimeCache) Contents() []proto.Message { return c.buildDynamicLayer() } -// Query returns only the "dynamic" layer if requested, otherwise empty. -func (c *RuntimeCache) Query(names []string) []proto.Message { - for _, name := range names { - if name == envoy_v3.DynamicRuntimeLayerName { - return c.buildDynamicLayer() - } - } - return []proto.Message{} -} - func (*RuntimeCache) TypeURL() string { return resource.RuntimeType } // Update replaces the contents of the cache with the supplied map. @@ -94,7 +82,6 @@ func (c *RuntimeCache) Update(v map[string]*structpb.Value) { defer c.mu.Unlock() c.dynamicRuntimeKV = v - c.Cond.Notify() } func (c *RuntimeCache) OnChange(root *dag.DAG) { diff --git a/internal/xdscache/v3/runtime_test.go b/internal/xdscache/v3/runtime_test.go index da68821341f..aded8fb4526 100644 --- a/internal/xdscache/v3/runtime_test.go +++ b/internal/xdscache/v3/runtime_test.go @@ -77,43 +77,6 @@ func TestRuntimeCacheContents(t *testing.T) { } } -func TestRuntimeCacheQuery(t *testing.T) { - baseRuntimeLayers := []proto.Message{ - &envoy_service_runtime_v3.Runtime{ - Name: "dynamic", - Layer: &structpb.Struct{ - Fields: map[string]*structpb.Value{ - "re2.max_program_size.error_level": structpb.NewNumberValue(1 << 20), - "re2.max_program_size.warn_level": structpb.NewNumberValue(1000), - }, - }, - }, - } - testCases := map[string]struct { - names []string - expected []proto.Message - }{ - "empty names": { - names: []string{}, - expected: []proto.Message{}, - }, - "names include dynamic": { - names: []string{"foo", "dynamic", "bar"}, - expected: baseRuntimeLayers, - }, - "names excludes dynamic": { - names: []string{"foo", "bar", "baz"}, - expected: []proto.Message{}, - }, - } - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - rc := NewRuntimeCache(ConfigurableRuntimeSettings{}) - protobuf.ExpectEqual(t, tc.expected, rc.Query(tc.names)) - }) - } -} - func TestRuntimeVisit(t *testing.T) { service := &core_v1.Service{ ObjectMeta: meta_v1.ObjectMeta{ @@ -247,7 +210,7 @@ func TestRuntimeVisit(t *testing.T) { t.Run(name, func(t *testing.T) { rc := NewRuntimeCache(tc.ConfigurableRuntimeSettings) rc.OnChange(buildDAGFallback(t, tc.fallbackCertificate, tc.objs...)) - protobuf.ExpectEqual(t, tc.expected, rc.Query([]string{"dynamic"})) + protobuf.ExpectEqual(t, tc.expected, rc.Contents()) }) } } @@ -305,7 +268,7 @@ func TestRuntimeCacheOnChangeDelete(t *testing.T) { }, }, }, - }, rc.Query([]string{"dynamic"})) + }, rc.Contents()) rc.OnChange(buildDAGFallback(t, nil, nil)) protobuf.ExpectEqual(t, []proto.Message{ @@ -318,5 +281,5 @@ func TestRuntimeCacheOnChangeDelete(t *testing.T) { }, }, }, - }, rc.Query([]string{"dynamic"})) + }, rc.Contents()) } diff --git a/internal/xdscache/v3/secret.go b/internal/xdscache/v3/secret.go index c6359e17991..9d7fda801df 100644 --- a/internal/xdscache/v3/secret.go +++ b/internal/xdscache/v3/secret.go @@ -21,7 +21,6 @@ import ( resource "github.com/envoyproxy/go-control-plane/pkg/resource/v3" "google.golang.org/protobuf/proto" - "github.com/projectcontour/contour/internal/contour" "github.com/projectcontour/contour/internal/dag" "github.com/projectcontour/contour/internal/envoy" envoy_v3 "github.com/projectcontour/contour/internal/envoy/v3" @@ -34,7 +33,6 @@ type SecretCache struct { mu sync.Mutex values map[string]*envoy_transport_socket_tls_v3.Secret staticValues map[string]*envoy_transport_socket_tls_v3.Secret - contour.Cond } func NewSecretsCache(secrets []*envoy_transport_socket_tls_v3.Secret) *SecretCache { @@ -54,7 +52,6 @@ func (c *SecretCache) Update(v map[string]*envoy_transport_socket_tls_v3.Secret) defer c.mu.Unlock() c.values = v - c.Cond.Notify() } // Contents returns a copy of the cache's contents. @@ -72,27 +69,6 @@ func (c *SecretCache) Contents() []proto.Message { return protobuf.AsMessages(values) } -func (c *SecretCache) Query(names []string) []proto.Message { - c.mu.Lock() - defer c.mu.Unlock() - var values []*envoy_transport_socket_tls_v3.Secret - for _, n := range names { - // we can only return secrets where their value is - // known. if the secret is not registered in the cache - // we return nothing. - v, ok := c.values[n] - if !ok { - v, ok = c.staticValues[n] - if !ok { - continue - } - } - values = append(values, v) - } - sort.Stable(sorter.For(values)) - return protobuf.AsMessages(values) -} - func (*SecretCache) TypeURL() string { return resource.SecretType } func (c *SecretCache) OnChange(root *dag.DAG) { diff --git a/internal/xdscache/v3/secret_test.go b/internal/xdscache/v3/secret_test.go index 1aa187047fc..6c0788a1c20 100644 --- a/internal/xdscache/v3/secret_test.go +++ b/internal/xdscache/v3/secret_test.go @@ -60,50 +60,6 @@ func TestSecretCacheContents(t *testing.T) { } } -func TestSecretCacheQuery(t *testing.T) { - tests := map[string]struct { - contents map[string]*envoy_transport_socket_tls_v3.Secret - query []string - want []proto.Message - }{ - "exact match": { - contents: secretmap( - secret("default/secret/0567f551af", secretdata(CERTIFICATE, RSA_PRIVATE_KEY)), - ), - query: []string{"default/secret/0567f551af"}, - want: []proto.Message{ - secret("default/secret/0567f551af", secretdata(CERTIFICATE, RSA_PRIVATE_KEY)), - }, - }, - "partial match": { - contents: secretmap( - secret("default/secret-a/0567f551af", secretdata(CERTIFICATE, RSA_PRIVATE_KEY)), - secret("default/secret-b/5397c67313", secretdata(CERTIFICATE_2, RSA_PRIVATE_KEY_2)), - ), - query: []string{"default/secret/0567f551af", "default/secret-b/5397c67313"}, - want: []proto.Message{ - secret("default/secret-b/5397c67313", secretdata(CERTIFICATE_2, RSA_PRIVATE_KEY_2)), - }, - }, - "no match": { - contents: secretmap( - secret("default/secret/0567f551af", secretdata(CERTIFICATE, RSA_PRIVATE_KEY)), - ), - query: []string{"default/secret-b/5397c67313"}, - want: nil, - }, - } - - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - var sc SecretCache - sc.Update(tc.contents) - got := sc.Query(tc.query) - protobuf.ExpectEqual(t, tc.want, got) - }) - } -} - func TestSecretVisit(t *testing.T) { tests := map[string]struct { objs []any diff --git a/internal/xdscache/v3/server_test.go b/internal/xdscache/v3/server_test.go deleted file mode 100644 index 71d4cec431d..00000000000 --- a/internal/xdscache/v3/server_test.go +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright Project Contour 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 v3 - -import ( - "context" - "net" - "testing" - "time" - - envoy_service_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/service/cluster/v3" - envoy_service_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" - envoy_service_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/service/endpoint/v3" - envoy_service_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/service/listener/v3" - envoy_service_route_v3 "github.com/envoyproxy/go-control-plane/envoy/service/route/v3" - envoy_service_runtime_v3 "github.com/envoyproxy/go-control-plane/envoy/service/runtime/v3" - envoy_service_secret_v3 "github.com/envoyproxy/go-control-plane/envoy/service/secret/v3" - resource "github.com/envoyproxy/go-control-plane/pkg/resource/v3" - "github.com/stretchr/testify/require" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/credentials/insecure" - "google.golang.org/grpc/status" - core_v1 "k8s.io/api/core/v1" - discovery_v1 "k8s.io/api/discovery/v1" - networking_v1 "k8s.io/api/networking/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/utils/ptr" - - "github.com/projectcontour/contour/internal/contour" - "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/fixture" - "github.com/projectcontour/contour/internal/xds" - contour_xds_v3 "github.com/projectcontour/contour/internal/xds/v3" - "github.com/projectcontour/contour/internal/xdscache" -) - -func TestGRPC(t *testing.T) { - // tr and et is recreated before the start of each test. - var et *EndpointsTranslator - var eh *contour.EventHandler - var est *EndpointSliceTranslator - - tests := map[string]func(*testing.T, *grpc.ClientConn){ - "StreamClusters": func(t *testing.T, cc *grpc.ClientConn) { - eh.OnAdd(&core_v1.Service{ - ObjectMeta: meta_v1.ObjectMeta{ - Name: "simple", - Namespace: "default", - }, - Spec: core_v1.ServiceSpec{ - Selector: map[string]string{ - "app": "simple", - }, - Ports: []core_v1.ServicePort{{ - Protocol: "TCP", - Port: 80, - TargetPort: intstr.FromInt(6502), - }}, - }, - }, false) - - sds := envoy_service_cluster_v3.NewClusterDiscoveryServiceClient(cc) - ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) - defer cancel() - stream, err := sds.StreamClusters(ctx) - require.NoError(t, err) - sendreq(t, stream, resource.ClusterType) // send initial notification - checkrecv(t, stream) // check we receive one notification - checktimeout(t, stream) // check that the second receive times out - }, - "StreamEndpoints": func(t *testing.T, cc *grpc.ClientConn) { - et.OnAdd(&core_v1.Endpoints{ - ObjectMeta: meta_v1.ObjectMeta{ - Name: "kube-scheduler", - Namespace: "kube-system", - }, - Subsets: []core_v1.EndpointSubset{{ - Addresses: []core_v1.EndpointAddress{{ - IP: "130.211.139.167", - }}, - Ports: []core_v1.EndpointPort{{ - Port: 80, - }, { - Port: 443, - }}, - }}, - }, false) - - eds := envoy_service_endpoint_v3.NewEndpointDiscoveryServiceClient(cc) - ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) - defer cancel() - stream, err := eds.StreamEndpoints(ctx) - require.NoError(t, err) - sendreq(t, stream, resource.EndpointType) // send initial notification - checkrecv(t, stream) // check we receive one notification - checktimeout(t, stream) // check that the second receive times out - }, - "StreamEndpointSlices": func(t *testing.T, cc *grpc.ClientConn) { - et.OnAdd(&discovery_v1.EndpointSlice{ - ObjectMeta: meta_v1.ObjectMeta{ - Name: "kube-scheduler", - Namespace: "kube-system", - }, - AddressType: discovery_v1.AddressTypeIPv4, - Endpoints: []discovery_v1.Endpoint{ - { - Addresses: []string{ - "130.211.139.167", - }, - }, - }, - Ports: []discovery_v1.EndpointPort{ - { - Port: ptr.To[int32](80), - }, - { - Port: ptr.To[int32](80), - }, - }, - }, false) - - eds := envoy_service_endpoint_v3.NewEndpointDiscoveryServiceClient(cc) - ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) - defer cancel() - stream, err := eds.StreamEndpoints(ctx) - require.NoError(t, err) - sendreq(t, stream, resource.EndpointType) // send initial notification - checkrecv(t, stream) // check we receive one notification - checktimeout(t, stream) // check that the second receive times out - }, - "StreamListeners": func(t *testing.T, cc *grpc.ClientConn) { - // add an ingress, which will create a non tls listener - eh.OnAdd(&networking_v1.Ingress{ - ObjectMeta: meta_v1.ObjectMeta{ - Name: "httpbin-org", - Namespace: "default", - }, - Spec: networking_v1.IngressSpec{ - Rules: []networking_v1.IngressRule{{ - Host: "httpbin.org", - IngressRuleValue: networking_v1.IngressRuleValue{ - HTTP: &networking_v1.HTTPIngressRuleValue{ - Paths: []networking_v1.HTTPIngressPath{{ - Backend: *backend("httpbin-org", 80), - }}, - }, - }, - }}, - }, - }, false) - - lds := envoy_service_listener_v3.NewListenerDiscoveryServiceClient(cc) - ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) - defer cancel() - stream, err := lds.StreamListeners(ctx) - require.NoError(t, err) - sendreq(t, stream, resource.ListenerType) // send initial notification - checkrecv(t, stream) // check we receive one notification - checktimeout(t, stream) // check that the second receive times out - }, - "StreamRoutes": func(t *testing.T, cc *grpc.ClientConn) { - eh.OnAdd(&networking_v1.Ingress{ - ObjectMeta: meta_v1.ObjectMeta{ - Name: "httpbin-org", - Namespace: "default", - }, - Spec: networking_v1.IngressSpec{ - Rules: []networking_v1.IngressRule{{ - Host: "httpbin.org", - IngressRuleValue: networking_v1.IngressRuleValue{ - HTTP: &networking_v1.HTTPIngressRuleValue{ - Paths: []networking_v1.HTTPIngressPath{{ - Backend: *backend("httpbin-org", 80), - }}, - }, - }, - }}, - }, - }, false) - - rds := envoy_service_route_v3.NewRouteDiscoveryServiceClient(cc) - ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) - defer cancel() - stream, err := rds.StreamRoutes(ctx) - require.NoError(t, err) - sendreq(t, stream, resource.RouteType) // send initial notification - checkrecv(t, stream) // check we receive one notification - checktimeout(t, stream) // check that the second receive times out - }, - "StreamSecrets": func(t *testing.T, cc *grpc.ClientConn) { - eh.OnAdd(&core_v1.Secret{ - ObjectMeta: meta_v1.ObjectMeta{ - Name: "secret", - Namespace: "default", - }, - Data: map[string][]byte{ - core_v1.TLSCertKey: []byte("certificate"), - core_v1.TLSPrivateKeyKey: []byte("key"), - }, - }, false) - - sds := envoy_service_secret_v3.NewSecretDiscoveryServiceClient(cc) - ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) - defer cancel() - stream, err := sds.StreamSecrets(ctx) - require.NoError(t, err) - sendreq(t, stream, resource.SecretType) // send initial notification - checkrecv(t, stream) // check we receive one notification - checktimeout(t, stream) // check that the second receive times out - }, - "StreamRuntime": func(t *testing.T, cc *grpc.ClientConn) { - rtds := envoy_service_runtime_v3.NewRuntimeDiscoveryServiceClient(cc) - ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) - defer cancel() - stream, err := rtds.StreamRuntime(ctx) - require.NoError(t, err) - sendreq(t, stream, resource.RuntimeType) // send initial notification - checkrecv(t, stream) // check we receive one notification - checktimeout(t, stream) // check that the second receive times out - }, - } - - log := fixture.NewDiscardLogger() - for name, fn := range tests { - t.Run(name, func(t *testing.T) { - et = NewEndpointsTranslator(fixture.NewTestLogger(t)) - est = NewEndpointSliceTranslator(fixture.NewTestLogger(t)) - - resources := []xdscache.ResourceCache{ - &ListenerCache{}, - &SecretCache{}, - &RouteCache{}, - &ClusterCache{}, - est, - et, - NewRuntimeCache(ConfigurableRuntimeSettings{}), - } - - eh = contour.NewEventHandler(contour.EventHandlerConfig{ - Logger: log, - Builder: new(dag.Builder), - Observer: dag.ComposeObservers(xdscache.ObserversOf(resources)...), - }, func() bool { return true }) - - srv := xds.NewServer(nil) - contour_xds_v3.RegisterServer(contour_xds_v3.NewContourServer(log, xdscache.ResourcesOf(resources)...), srv) - l, err := net.Listen("tcp", "127.0.0.1:0") - require.NoError(t, err) - done := make(chan error, 1) - ctx, cancel := context.WithCancel(context.Background()) - go eh.Start(ctx) // nolint:errcheck - go func() { - done <- srv.Serve(l) - }() - defer func() { - srv.GracefulStop() - cancel() - <-done - }() - cc, err := grpc.NewClient(l.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) - require.NoError(t, err) - defer cc.Close() - fn(t, cc) - }) - } -} - -func sendreq(t *testing.T, stream interface { - Send(*envoy_service_discovery_v3.DiscoveryRequest) error -}, typeurl string, -) { - t.Helper() - err := stream.Send(&envoy_service_discovery_v3.DiscoveryRequest{ - TypeUrl: typeurl, - }) - require.NoError(t, err) -} - -func checkrecv(t *testing.T, stream interface { - Recv() (*envoy_service_discovery_v3.DiscoveryResponse, error) -}, -) { - t.Helper() - _, err := stream.Recv() - require.NoError(t, err) -} - -func checktimeout(t *testing.T, stream interface { - Recv() (*envoy_service_discovery_v3.DiscoveryResponse, error) -}, -) { - t.Helper() - _, err := stream.Recv() - require.Errorf(t, err, "expected timeout") - s, ok := status.FromError(err) - require.Truef(t, ok, "Error wasn't what was expected: %T %v", err, err) - - // Work around grpc/grpc-go#1645 which sometimes seems to - // set the status code to Unknown, even when the message is derived from context.DeadlineExceeded. - if s.Code() != codes.DeadlineExceeded && s.Message() != context.DeadlineExceeded.Error() { - t.Fatalf("expected %q, got %q %T %v", codes.DeadlineExceeded, s.Code(), err, err) - } -} diff --git a/pkg/config/parameters.go b/pkg/config/parameters.go index 04931c8d349..e6fa67302d1 100644 --- a/pkg/config/parameters.go +++ b/pkg/config/parameters.go @@ -29,24 +29,6 @@ import ( contour_v1alpha1 "github.com/projectcontour/contour/apis/projectcontour/v1alpha1" ) -// ServerType is the name of a xDS server implementation. -type ServerType string - -const ( - ContourServerType ServerType = "contour" - EnvoyServerType ServerType = "envoy" -) - -// Validate the xDS server type. -func (s ServerType) Validate() error { - switch s { - case ContourServerType, EnvoyServerType: - return nil - default: - return fmt.Errorf("invalid xDS server type %q", s) - } -} - // Validate ensures that GatewayRef namespace/name is specified. func (g *GatewayParameters) Validate() error { if g != nil && (g.GatewayRef.Namespace == "" || g.GatewayRef.Name == "") { @@ -239,13 +221,7 @@ func (t ProtocolParameters) Validate() error { } // ServerParameters holds the configuration for the Contour xDS server. -type ServerParameters struct { - // Defines the XDSServer to use for `contour serve`. - // Defaults to "envoy" - // Deprecated: this field will be removed in a future release when - // the `contour` xDS server implementation is removed. - XDSServerType ServerType `yaml:"xds-server-type,omitempty"` -} +type ServerParameters struct{} // GatewayParameters holds the configuration for Gateway API controllers. type GatewayParameters struct { @@ -972,10 +948,6 @@ func (p *Parameters) Validate() error { return err } - if err := p.Server.XDSServerType.Validate(); err != nil { - return err - } - if err := p.GatewayConfig.Validate(); err != nil { return err } @@ -1034,12 +1006,10 @@ func Defaults() Parameters { contourNamespace := GetenvOr("CONTOUR_NAMESPACE", "projectcontour") return Parameters{ - Debug: false, - InCluster: false, - Kubeconfig: filepath.Join(os.Getenv("HOME"), ".kube", "config"), - Server: ServerParameters{ - XDSServerType: EnvoyServerType, - }, + Debug: false, + InCluster: false, + Kubeconfig: filepath.Join(os.Getenv("HOME"), ".kube", "config"), + Server: ServerParameters{}, IngressStatusAddress: "", AccessLogFormat: DEFAULT_ACCESS_LOG_TYPE, AccessLogFields: DefaultFields, diff --git a/pkg/config/parameters_test.go b/pkg/config/parameters_test.go index 7f6ad7a7dcd..3580f0a36d4 100644 --- a/pkg/config/parameters_test.go +++ b/pkg/config/parameters_test.go @@ -47,8 +47,6 @@ func TestParseDefaults(t *testing.T) { expected := ` debug: false kubeconfig: TestParseDefaults/.kube/config -server: - xds-server-type: envoy accesslog-format: envoy json-fields: - '@timestamp' @@ -179,14 +177,6 @@ func TestValidateNamespacedName(t *testing.T) { require.Error(t, NamespacedName{Namespace: "ns"}.Validate()) } -func TestValidateServerType(t *testing.T) { - require.Error(t, ServerType("").Validate()) - require.Error(t, ServerType("foo").Validate()) - - require.NoError(t, EnvoyServerType.Validate()) - require.NoError(t, ContourServerType.Validate()) -} - func TestValidateGatewayParameters(t *testing.T) { // Not required if nothing is passed. var gw *GatewayParameters @@ -339,11 +329,6 @@ cluster: dns-lookup-family: stone `) - check(` -server: - xds-server-type: magic -`) - check(` accesslog-format: /dev/null `) diff --git a/site/content/docs/main/config/api-reference.html b/site/content/docs/main/config/api-reference.html index 57bc87795fd..fbec522ca29 100644 --- a/site/content/docs/main/config/api-reference.html +++ b/site/content/docs/main/config/api-reference.html @@ -9064,25 +9064,6 @@

XDSServerConfig -type -
- - -XDSServerType - - - - -(Optional) -

Defines the XDSServer to use for contour serve.

-

Values: envoy (default), contour (deprecated).

-

Other values will produce an error.

-

Deprecated: this field will be removed in a future release when -the contour xDS server implementation is removed.

- - - - address
@@ -9127,30 +9108,6 @@

XDSServerConfig -

XDSServerType -(string alias)

-

-(Appears on: -XDSServerConfig) -

-

-

XDSServerType is the type of xDS server implementation.

-

- - - - - - - - - - - - -
ValueDescription

"contour"

Use Contour’s xDS server (deprecated).

-

"envoy"

Use the upstream go-control-plane-based xDS server.

-

Generated with gen-crd-api-reference-docs. diff --git a/site/content/docs/main/configuration.md b/site/content/docs/main/configuration.md index 5277ab79e38..b49e47e3bf8 100644 --- a/site/content/docs/main/configuration.md +++ b/site/content/docs/main/configuration.md @@ -206,7 +206,7 @@ The server configuration block can be used to configure various settings for the | Field Name | Type | Default | Description | | --------------- | ------ | ------- | ----------------------------------------------------------------------------- | -| xds-server-type | string | envoy | This field specifies the xDS Server to use. Options are `envoy` or `contour` (deprecated). **This field is deprecated** and will be removed in a future release when the `contour` xDS server implementation is removed. | +| | | | | ### Gateway Configuration @@ -313,11 +313,6 @@ metadata: namespace: projectcontour data: contour.yaml: | - # - # server: - # determine which XDS Server implementation to utilize in Contour. - # xds-server-type: envoy - # # specify the gateway-api Gateway Contour should configure # gateway: # namespace: projectcontour diff --git a/test/e2e/fixtures.go b/test/e2e/fixtures.go index 4cc20831bf6..cb6a1070380 100644 --- a/test/e2e/fixtures.go +++ b/test/e2e/fixtures.go @@ -542,11 +542,7 @@ func (g *GRPC) Deploy(ns, name string) func() { // DefaultContourConfigFileParams returns a default configuration in a config // file params object. func DefaultContourConfigFileParams() *config.Parameters { - return &config.Parameters{ - Server: config.ServerParameters{ - XDSServerType: config.ServerType(XDSServerTypeFromEnv()), - }, - } + return &config.Parameters{} } // DefaultContourConfiguration returns a default ContourConfiguration object. @@ -558,7 +554,6 @@ func DefaultContourConfiguration() *contour_v1alpha1.ContourConfiguration { }, Spec: contour_v1alpha1.ContourConfigurationSpec{ XDSServer: &contour_v1alpha1.XDSServerConfig{ - Type: XDSServerTypeFromEnv(), Address: listenAllAddress(), Port: 8001, TLS: &contour_v1alpha1.TLS{ @@ -639,16 +634,6 @@ func DefaultContourConfiguration() *contour_v1alpha1.ContourConfiguration { } } -func XDSServerTypeFromEnv() contour_v1alpha1.XDSServerType { - // Default to envoy if not provided. - serverType := contour_v1alpha1.EnvoyServerType - typeFromEnv, found := os.LookupEnv("CONTOUR_E2E_XDS_SERVER_TYPE") - if found { - serverType = contour_v1alpha1.XDSServerType(typeFromEnv) - } - return serverType -} - func UseFeatureFlagsFromEnv() []string { flags := make([]string, 0) _, found := os.LookupEnv("CONTOUR_E2E_USE_ENDPOINTS")