From aae453fe1dc7c00d6149688b78917e1fd92f7558 Mon Sep 17 00:00:00 2001 From: Steve Sloka Date: Thu, 17 Sep 2020 18:02:41 -0400 Subject: [PATCH] internal: Refactor Envoy into v2 package Refactors the envoy package into a v2 package for Envoy API V2 types. Common items are kept in the envoy package for use by other versions. Updates: #1898 Signed-off-by: Steve Sloka --- cmd/contour/contour.go | 4 +- cmd/contour/servecontext_test.go | 5 +- internal/contour/cluster.go | 23 +- internal/contour/cluster_test.go | 204 ++--- internal/contour/endpointstranslator.go | 26 +- internal/contour/endpointstranslator_test.go | 184 ++-- internal/contour/listener.go | 69 +- internal/contour/listener_test.go | 554 ++++++------ internal/contour/route.go | 56 +- internal/contour/route_test.go | 244 +++--- internal/contour/secret.go | 3 +- internal/contour/visitor_test.go | 16 +- internal/envoy/accesslog.go | 60 -- internal/envoy/auth.go | 90 +- internal/envoy/bootstrap.go | 322 +------ internal/envoy/cluster.go | 218 +---- internal/envoy/cluster_test.go | 624 +------------- internal/envoy/healthcheck.go | 65 +- internal/envoy/listener.go | 516 +----------- internal/envoy/listener_test.go | 789 ----------------- internal/envoy/route.go | 304 +------ internal/envoy/secret.go | 38 +- internal/envoy/tcp_keepalive.go | 50 +- internal/envoy/v2/accesslog.go | 75 ++ internal/envoy/{ => v2}/accesslog_test.go | 7 +- internal/envoy/v2/auth.go | 101 +++ internal/envoy/{ => v2}/auth_test.go | 2 +- internal/envoy/v2/bootstrap.go | 319 +++++++ internal/envoy/{ => v2}/bootstrap_test.go | 25 +- internal/envoy/v2/cluster.go | 227 +++++ internal/envoy/v2/cluster_test.go | 584 +++++++++++++ internal/envoy/{ => v2}/endpoint.go | 2 +- internal/envoy/{ => v2}/endpoint_test.go | 2 +- internal/envoy/v2/healthcheck.go | 70 ++ internal/envoy/{ => v2}/healthcheck_test.go | 11 +- internal/envoy/v2/listener.go | 516 ++++++++++++ internal/envoy/v2/listener_test.go | 797 ++++++++++++++++++ internal/envoy/v2/route.go | 314 +++++++ internal/envoy/{ => v2}/route_test.go | 11 +- internal/envoy/v2/secret.go | 44 + internal/envoy/{ => v2}/secret_test.go | 6 +- internal/envoy/{ => v2}/socket.go | 2 +- internal/envoy/{ => v2}/socket_test.go | 2 +- internal/envoy/{ => v2}/stats.go | 2 +- internal/envoy/{ => v2}/stats_test.go | 2 +- internal/envoy/v2/tcp_keepalive.go | 62 ++ internal/featuretests/authorization_test.go | 74 +- .../featuretests/backendcavalidation_test.go | 50 +- internal/featuretests/cluster_test.go | 86 +- .../featuretests/downstreamvalidation_test.go | 26 +- internal/featuretests/endpoints_test.go | 64 +- internal/featuretests/envoy.go | 94 +-- .../featuretests/extensionservice_test.go | 36 +- internal/featuretests/externalname_test.go | 58 +- internal/featuretests/fallbackcert_test.go | 64 +- internal/featuretests/headercondition_test.go | 31 +- internal/featuretests/headerpolicy_test.go | 22 +- internal/featuretests/ingressclass_test.go | 114 +-- internal/featuretests/listeners_test.go | 336 ++++---- .../featuretests/loadbalancerpolicy_test.go | 16 +- internal/featuretests/mirrorpolicy_test.go | 12 +- internal/featuretests/replaceprefix_test.go | 146 ++-- internal/featuretests/retrypolicy_test.go | 28 +- internal/featuretests/rootnamespaces_test.go | 32 +- internal/featuretests/route_test.go | 212 ++--- internal/featuretests/secrets_test.go | 18 +- internal/featuretests/tcpproxy_test.go | 200 ++--- internal/featuretests/timeoutpolicy_test.go | 60 +- internal/featuretests/timeouts_test.go | 28 +- .../tlscertificatedelegation_test.go | 40 +- .../featuretests/tlsprotocolversion_test.go | 36 +- internal/featuretests/websockets_test.go | 28 +- 72 files changed, 4870 insertions(+), 4688 deletions(-) create mode 100644 internal/envoy/v2/accesslog.go rename internal/envoy/{ => v2}/accesslog_test.go (94%) create mode 100644 internal/envoy/v2/auth.go rename internal/envoy/{ => v2}/auth_test.go (99%) create mode 100644 internal/envoy/v2/bootstrap.go rename internal/envoy/{ => v2}/bootstrap_test.go (97%) create mode 100644 internal/envoy/v2/cluster.go create mode 100644 internal/envoy/v2/cluster_test.go rename internal/envoy/{ => v2}/endpoint.go (99%) rename internal/envoy/{ => v2}/endpoint_test.go (99%) create mode 100644 internal/envoy/v2/healthcheck.go rename internal/envoy/{ => v2}/healthcheck_test.go (91%) create mode 100644 internal/envoy/v2/listener.go create mode 100644 internal/envoy/v2/listener_test.go create mode 100644 internal/envoy/v2/route.go rename internal/envoy/{ => v2}/route_test.go (98%) create mode 100644 internal/envoy/v2/secret.go rename internal/envoy/{ => v2}/secret_test.go (96%) rename internal/envoy/{ => v2}/socket.go (99%) rename internal/envoy/{ => v2}/socket_test.go (99%) rename internal/envoy/{ => v2}/stats.go (99%) rename internal/envoy/{ => v2}/stats_test.go (99%) create mode 100644 internal/envoy/v2/tcp_keepalive.go diff --git a/cmd/contour/contour.go b/cmd/contour/contour.go index ea74d6187f1..6a935fc71e4 100644 --- a/cmd/contour/contour.go +++ b/cmd/contour/contour.go @@ -18,7 +18,7 @@ import ( resource "github.com/envoyproxy/go-control-plane/pkg/resource/v2" "github.com/projectcontour/contour/internal/build" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/k8s" "github.com/sirupsen/logrus" kingpin "gopkg.in/alecthomas/kingpin.v2" @@ -69,7 +69,7 @@ func main() { case sdmShutdown.FullCommand(): sdmShutdownCtx.shutdownHandler() case bootstrap.FullCommand(): - if err := envoy.WriteBootstrap(bootstrapCtx); err != nil { + if err := v2.WriteBootstrap(bootstrapCtx); err != nil { log.WithError(err).Fatal("failed to write bootstrap configuration") } case certgenApp.FullCommand(): diff --git a/cmd/contour/servecontext_test.go b/cmd/contour/servecontext_test.go index 04d4d1ad9f5..d318cff712c 100644 --- a/cmd/contour/servecontext_test.go +++ b/cmd/contour/servecontext_test.go @@ -27,14 +27,13 @@ import ( "testing" "time" + "github.com/google/go-cmp/cmp" "github.com/projectcontour/contour/internal/envoy" "github.com/projectcontour/contour/internal/fixture" - "k8s.io/apimachinery/pkg/types" - - "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" "google.golang.org/grpc" "gopkg.in/yaml.v2" + "k8s.io/apimachinery/pkg/types" ) func TestServeContextProxyRootNamespaces(t *testing.T) { diff --git a/internal/contour/cluster.go b/internal/contour/cluster.go index a26abb59d88..29f33f3f57c 100644 --- a/internal/contour/cluster.go +++ b/internal/contour/cluster.go @@ -17,11 +17,12 @@ import ( "sort" "sync" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" resource "github.com/envoyproxy/go-control-plane/pkg/resource/v2" "github.com/golang/protobuf/proto" "github.com/projectcontour/contour/internal/dag" "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/protobuf" "github.com/projectcontour/contour/internal/sorter" ) @@ -29,12 +30,12 @@ import ( // ClusterCache manages the contents of the gRPC CDS cache. type ClusterCache struct { mu sync.Mutex - values map[string]*v2.Cluster + values map[string]*envoy_api_v2.Cluster Cond } // Update replaces the contents of the cache with the supplied map. -func (c *ClusterCache) Update(v map[string]*v2.Cluster) { +func (c *ClusterCache) Update(v map[string]*envoy_api_v2.Cluster) { c.mu.Lock() defer c.mu.Unlock() @@ -46,7 +47,7 @@ func (c *ClusterCache) Update(v map[string]*v2.Cluster) { func (c *ClusterCache) Contents() []proto.Message { c.mu.Lock() defer c.mu.Unlock() - var values []*v2.Cluster + var values []*envoy_api_v2.Cluster for _, v := range c.values { values = append(values, v) } @@ -57,7 +58,7 @@ func (c *ClusterCache) Contents() []proto.Message { func (c *ClusterCache) Query(names []string) []proto.Message { c.mu.Lock() defer c.mu.Unlock() - var values []*v2.Cluster + var values []*envoy_api_v2.Cluster for _, n := range names { // if the cluster is not registered we cannot return // a blank cluster because each cluster has a required @@ -80,13 +81,13 @@ func (c *ClusterCache) OnChange(root *dag.DAG) { } type clusterVisitor struct { - clusters map[string]*v2.Cluster + clusters map[string]*envoy_api_v2.Cluster } -// visitCluster produces a map of *v2.Clusters. -func visitClusters(root dag.Vertex) map[string]*v2.Cluster { +// visitCluster produces a map of *envoy_api_v2.Clusters. +func visitClusters(root dag.Vertex) map[string]*envoy_api_v2.Cluster { cv := clusterVisitor{ - clusters: make(map[string]*v2.Cluster), + clusters: make(map[string]*envoy_api_v2.Cluster), } cv.visit(root) return cv.clusters @@ -97,12 +98,12 @@ func (v *clusterVisitor) visit(vertex dag.Vertex) { case *dag.Cluster: name := envoy.Clustername(cluster) if _, ok := v.clusters[name]; !ok { - v.clusters[name] = envoy.Cluster(cluster) + v.clusters[name] = v2.Cluster(cluster) } case *dag.ExtensionCluster: name := cluster.Name if _, ok := v.clusters[name]; !ok { - v.clusters[name] = envoy.ExtensionCluster(cluster) + v.clusters[name] = v2.ExtensionCluster(cluster) } } diff --git a/internal/contour/cluster_test.go b/internal/contour/cluster_test.go index c321b75e35e..396c1269d77 100644 --- a/internal/contour/cluster_test.go +++ b/internal/contour/cluster_test.go @@ -17,13 +17,13 @@ import ( "testing" "time" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_cluster "github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster" envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes/duration" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/protobuf" v1 "k8s.io/api/core/v1" "k8s.io/api/networking/v1beta1" @@ -33,7 +33,7 @@ import ( func TestClusterCacheContents(t *testing.T) { tests := map[string]struct { - contents map[string]*v2.Cluster + contents map[string]*envoy_api_v2.Cluster want []proto.Message }{ "empty": { @@ -42,22 +42,22 @@ func TestClusterCacheContents(t *testing.T) { }, "simple": { contents: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/kuard/443/da39a3ee5e", AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard", }, }), want: []proto.Message{ - cluster(&v2.Cluster{ + cluster(&envoy_api_v2.Cluster{ Name: "default/kuard/443/da39a3ee5e", AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard", }, }), @@ -77,29 +77,29 @@ func TestClusterCacheContents(t *testing.T) { func TestClusterCacheQuery(t *testing.T) { tests := map[string]struct { - contents map[string]*v2.Cluster + contents map[string]*envoy_api_v2.Cluster query []string want []proto.Message }{ "exact match": { contents: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/kuard/443/da39a3ee5e", AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard", }, }), query: []string{"default/kuard/443/da39a3ee5e"}, want: []proto.Message{ - cluster(&v2.Cluster{ + cluster(&envoy_api_v2.Cluster{ Name: "default/kuard/443/da39a3ee5e", AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard", }, }), @@ -107,23 +107,23 @@ func TestClusterCacheQuery(t *testing.T) { }, "partial match": { contents: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/kuard/443/da39a3ee5e", AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard", }, }), query: []string{"default/kuard/443/da39a3ee5e", "foo/bar/baz"}, want: []proto.Message{ - cluster(&v2.Cluster{ + cluster(&envoy_api_v2.Cluster{ Name: "default/kuard/443/da39a3ee5e", AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard", }, }), @@ -131,12 +131,12 @@ func TestClusterCacheQuery(t *testing.T) { }, "no match": { contents: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/kuard/443/da39a3ee5e", AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard", }, }), @@ -158,11 +158,11 @@ func TestClusterCacheQuery(t *testing.T) { func TestClusterVisit(t *testing.T) { tests := map[string]struct { objs []interface{} - want map[string]*v2.Cluster + want map[string]*envoy_api_v2.Cluster }{ "nothing": { objs: nil, - want: map[string]*v2.Cluster{}, + want: map[string]*envoy_api_v2.Cluster{}, }, "single unnamed service": { objs: []interface{}{ @@ -184,12 +184,12 @@ func TestClusterVisit(t *testing.T) { ), }, want: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/kuard/443/da39a3ee5e", AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard", }, }), @@ -218,12 +218,12 @@ func TestClusterVisit(t *testing.T) { ), }, want: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/kuard/443/da39a3ee5e", AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard/https", }, }), @@ -256,12 +256,12 @@ func TestClusterVisit(t *testing.T) { ), }, want: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/kuard/80/da39a3ee5e", AltStatName: "default_kuard_80", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard/http", }, Http2ProtocolOptions: &envoy_api_v2_core.Http2ProtocolOptions{}, @@ -289,12 +289,12 @@ func TestClusterVisit(t *testing.T) { ), }, want: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "beurocra-7fe4b4/tiny-cog-7fe4b4/443/da39a3ee5e", AltStatName: "beurocratic-company-test-domain-1_tiny-cog-department-test-instance_443", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "beurocratic-company-test-domain-1/tiny-cog-department-test-instance/svc-0", }, }), @@ -337,21 +337,21 @@ func TestClusterVisit(t *testing.T) { }), }, want: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/backend/80/da39a3ee5e", AltStatName: "default_backend_80", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/backend/http", }, }, - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/backend/8080/da39a3ee5e", AltStatName: "default_backend_8080", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/backend/alt", }, }, @@ -390,12 +390,12 @@ func TestClusterVisit(t *testing.T) { }), }, want: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/backend/80/c184349821", AltStatName: "default_backend_80", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/backend/http", }, HealthChecks: []*envoy_api_v2_core.HealthCheck{{ @@ -452,12 +452,12 @@ func TestClusterVisit(t *testing.T) { }), }, want: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/backend/80/7f8051653a", AltStatName: "default_backend_80", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/backend/http", }, HealthChecks: []*envoy_api_v2_core.HealthCheck{{ @@ -509,12 +509,12 @@ func TestClusterVisit(t *testing.T) { }), }, want: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/backend/80/da39a3ee5e", AltStatName: "default_backend_80", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/backend/http", }, }, @@ -553,15 +553,15 @@ func TestClusterVisit(t *testing.T) { }), }, want: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/backend/80/8bf87fefba", AltStatName: "default_backend_80", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/backend/http", }, - LbPolicy: v2.Cluster_LEAST_REQUEST, + LbPolicy: envoy_api_v2.Cluster_LEAST_REQUEST, }, ), }, @@ -598,15 +598,15 @@ func TestClusterVisit(t *testing.T) { }), }, want: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/backend/80/58d888c08a", AltStatName: "default_backend_80", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/backend/http", }, - LbPolicy: v2.Cluster_RANDOM, + LbPolicy: envoy_api_v2.Cluster_RANDOM, }, ), }, @@ -645,12 +645,12 @@ func TestClusterVisit(t *testing.T) { }), }, want: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/backend/80/da39a3ee5e", AltStatName: "default_backend_80", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/backend/http", }, }, @@ -687,12 +687,12 @@ func TestClusterVisit(t *testing.T) { ), }, want: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/kuard/80/da39a3ee5e", AltStatName: "default_kuard_80", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard/http", }, CircuitBreakers: &envoy_api_v2_cluster.CircuitBreakers{ @@ -734,12 +734,12 @@ func TestClusterVisit(t *testing.T) { ), }, want: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/kuard/443/da39a3ee5e", AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard/https", }, }), @@ -773,12 +773,12 @@ func TestClusterVisit(t *testing.T) { ), }, want: clustermap( - &v2.Cluster{ + &envoy_api_v2.Cluster{ Name: "default/kuard/443/da39a3ee5e", AltStatName: "default_kuard_443", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard/https", }, }), @@ -811,20 +811,20 @@ func serviceWithAnnotations(ns, name string, annotations map[string]string, port } } -func cluster(c *v2.Cluster) *v2.Cluster { +func cluster(c *envoy_api_v2.Cluster) *envoy_api_v2.Cluster { // NOTE: Keep this in sync with envoy.defaultCluster(). - defaults := &v2.Cluster{ + defaults := &envoy_api_v2.Cluster{ ConnectTimeout: protobuf.Duration(250 * time.Millisecond), - CommonLbConfig: envoy.ClusterCommonLBConfig(), - LbPolicy: v2.Cluster_ROUND_ROBIN, + CommonLbConfig: v2.ClusterCommonLBConfig(), + LbPolicy: envoy_api_v2.Cluster_ROUND_ROBIN, } proto.Merge(defaults, c) return defaults } -func clustermap(clusters ...*v2.Cluster) map[string]*v2.Cluster { - m := make(map[string]*v2.Cluster) +func clustermap(clusters ...*envoy_api_v2.Cluster) map[string]*envoy_api_v2.Cluster { + m := make(map[string]*envoy_api_v2.Cluster) for _, c := range clusters { m[c.Name] = cluster(c) } diff --git a/internal/contour/endpointstranslator.go b/internal/contour/endpointstranslator.go index db13078d63e..99893745763 100644 --- a/internal/contour/endpointstranslator.go +++ b/internal/contour/endpointstranslator.go @@ -18,12 +18,12 @@ import ( "sort" "sync" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_endpoint "github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint" resource "github.com/envoyproxy/go-control-plane/pkg/resource/v2" "github.com/golang/protobuf/proto" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/k8s" "github.com/projectcontour/contour/internal/protobuf" "github.com/projectcontour/contour/internal/sorter" @@ -70,8 +70,8 @@ func RecalculateEndpoints(port v1.ServicePort, ep *v1.Endpoints) []*LoadBalancin sort.Slice(addresses, func(i, j int) bool { return addresses[i].IP < addresses[j].IP }) for _, a := range addresses { - addr := envoy.SocketAddress(a.IP, int(p.Port)) - lb = append(lb, envoy.LBEndpoint(addr)) + addr := v2.SocketAddress(a.IP, int(p.Port)) + lb = append(lb, v2.LBEndpoint(addr)) } } } @@ -102,11 +102,11 @@ type EndpointsCache struct { // will be generated for every stale ServerCluster, however, if there // are no endpoints for the Services in the ServiceCluster, the // ClusterLoadAssignment wil be empty. -func (c *EndpointsCache) Recalculate() map[string]*v2.ClusterLoadAssignment { +func (c *EndpointsCache) Recalculate() map[string]*envoy_api_v2.ClusterLoadAssignment { c.mu.Lock() defer c.mu.Unlock() - assignments := map[string]*v2.ClusterLoadAssignment{} + assignments := map[string]*envoy_api_v2.ClusterLoadAssignment{} for _, cluster := range c.stale { // Clusters can be in the stale list multiple times; // skip to avoid duplicate recalculations. @@ -114,7 +114,7 @@ func (c *EndpointsCache) Recalculate() map[string]*v2.ClusterLoadAssignment { continue } - cla := v2.ClusterLoadAssignment{ + cla := envoy_api_v2.ClusterLoadAssignment{ ClusterName: cluster.ClusterName, Endpoints: nil, Policy: nil, @@ -224,7 +224,7 @@ func NewEndpointsTranslator(log logrus.FieldLogger) *EndpointsTranslator { return &EndpointsTranslator{ Cond: Cond{}, FieldLogger: log, - entries: map[string]*v2.ClusterLoadAssignment{}, + entries: map[string]*envoy_api_v2.ClusterLoadAssignment{}, cache: EndpointsCache{ stale: nil, services: map[types.NamespacedName][]*dag.ServiceCluster{}, @@ -245,13 +245,13 @@ type EndpointsTranslator struct { cache EndpointsCache mu sync.Mutex // Protects entries. - entries map[string]*v2.ClusterLoadAssignment + entries map[string]*envoy_api_v2.ClusterLoadAssignment } // Merge combines the given entries with the existing entries in the // EndpointsTranslator. If the same key exists in both maps, an existing entry // is replaced. -func (e *EndpointsTranslator) Merge(entries map[string]*v2.ClusterLoadAssignment) { +func (e *EndpointsTranslator) Merge(entries map[string]*envoy_api_v2.ClusterLoadAssignment) { e.mu.Lock() defer e.mu.Unlock() @@ -372,7 +372,7 @@ func (e *EndpointsTranslator) Contents() []proto.Message { e.mu.Lock() defer e.mu.Unlock() - values := make([]*v2.ClusterLoadAssignment, 0, len(e.entries)) + values := make([]*envoy_api_v2.ClusterLoadAssignment, 0, len(e.entries)) for _, v := range e.entries { values = append(values, v) } @@ -385,12 +385,12 @@ func (e *EndpointsTranslator) Query(names []string) []proto.Message { e.mu.Lock() defer e.mu.Unlock() - values := make([]*v2.ClusterLoadAssignment, 0, len(names)) + values := make([]*envoy_api_v2.ClusterLoadAssignment, 0, len(names)) for _, n := range names { v, ok := e.entries[n] if !ok { e.Debugf("no cache entry for %q", n) - v = &v2.ClusterLoadAssignment{ + v = &envoy_api_v2.ClusterLoadAssignment{ ClusterName: n, } } diff --git a/internal/contour/endpointstranslator_test.go b/internal/contour/endpointstranslator_test.go index 43753ea6a71..3a690415451 100644 --- a/internal/contour/endpointstranslator_test.go +++ b/internal/contour/endpointstranslator_test.go @@ -16,11 +16,11 @@ package contour import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_endpoint "github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint" "github.com/golang/protobuf/proto" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" "github.com/projectcontour/contour/internal/protobuf" "github.com/stretchr/testify/require" @@ -29,7 +29,7 @@ import ( func TestEndpointsTranslatorContents(t *testing.T) { tests := map[string]struct { - contents map[string]*v2.ClusterLoadAssignment + contents map[string]*envoy_api_v2.ClusterLoadAssignment want []proto.Message }{ "empty": { @@ -38,13 +38,13 @@ func TestEndpointsTranslatorContents(t *testing.T) { }, "simple": { contents: clusterloadassignments( - envoy.ClusterLoadAssignment("default/httpbin-org", - envoy.SocketAddress("10.10.10.10", 80), + v2.ClusterLoadAssignment("default/httpbin-org", + v2.SocketAddress("10.10.10.10", 80), ), ), want: []proto.Message{ - envoy.ClusterLoadAssignment("default/httpbin-org", - envoy.SocketAddress("10.10.10.10", 80), + v2.ClusterLoadAssignment("default/httpbin-org", + v2.SocketAddress("10.10.10.10", 80), ), }, }, @@ -62,46 +62,46 @@ func TestEndpointsTranslatorContents(t *testing.T) { func TestEndpointCacheQuery(t *testing.T) { tests := map[string]struct { - contents map[string]*v2.ClusterLoadAssignment + contents map[string]*envoy_api_v2.ClusterLoadAssignment query []string want []proto.Message }{ "exact match": { contents: clusterloadassignments( - envoy.ClusterLoadAssignment("default/httpbin-org", - envoy.SocketAddress("10.10.10.10", 80), + v2.ClusterLoadAssignment("default/httpbin-org", + v2.SocketAddress("10.10.10.10", 80), ), ), query: []string{"default/httpbin-org"}, want: []proto.Message{ - envoy.ClusterLoadAssignment("default/httpbin-org", - envoy.SocketAddress("10.10.10.10", 80), + v2.ClusterLoadAssignment("default/httpbin-org", + v2.SocketAddress("10.10.10.10", 80), ), }, }, "partial match": { contents: clusterloadassignments( - envoy.ClusterLoadAssignment("default/httpbin-org", - envoy.SocketAddress("10.10.10.10", 80), + v2.ClusterLoadAssignment("default/httpbin-org", + v2.SocketAddress("10.10.10.10", 80), ), ), query: []string{"default/kuard/8080", "default/httpbin-org"}, want: []proto.Message{ - envoy.ClusterLoadAssignment("default/httpbin-org", - envoy.SocketAddress("10.10.10.10", 80), + v2.ClusterLoadAssignment("default/httpbin-org", + v2.SocketAddress("10.10.10.10", 80), ), - envoy.ClusterLoadAssignment("default/kuard/8080"), + v2.ClusterLoadAssignment("default/kuard/8080"), }, }, "no match": { contents: clusterloadassignments( - envoy.ClusterLoadAssignment("default/httpbin-org", - envoy.SocketAddress("10.10.10.10", 80), + v2.ClusterLoadAssignment("default/httpbin-org", + v2.SocketAddress("10.10.10.10", 80), ), ), query: []string{"default/kuard/8080"}, want: []proto.Message{ - envoy.ClusterLoadAssignment("default/kuard/8080"), + v2.ClusterLoadAssignment("default/kuard/8080"), }, }, } @@ -165,11 +165,11 @@ func TestEndpointsTranslatorAddEndpoints(t *testing.T) { ), }), want: []proto.Message{ - &v2.ClusterLoadAssignment{ClusterName: "default/httpbin-org/a"}, - &v2.ClusterLoadAssignment{ClusterName: "default/httpbin-org/b"}, - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ClusterName: "default/httpbin-org/a"}, + &envoy_api_v2.ClusterLoadAssignment{ClusterName: "default/httpbin-org/b"}, + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/simple", - Endpoints: envoy.WeightedEndpoints(1, envoy.SocketAddress("192.168.183.24", 8080)), + Endpoints: v2.WeightedEndpoints(1, v2.SocketAddress("192.168.183.24", 8080)), }, }, }, @@ -186,15 +186,15 @@ func TestEndpointsTranslatorAddEndpoints(t *testing.T) { ), }), want: []proto.Message{ - &v2.ClusterLoadAssignment{ClusterName: "default/httpbin-org/a"}, - &v2.ClusterLoadAssignment{ClusterName: "default/httpbin-org/b"}, - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ClusterName: "default/httpbin-org/a"}, + &envoy_api_v2.ClusterLoadAssignment{ClusterName: "default/httpbin-org/b"}, + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/simple", - Endpoints: envoy.WeightedEndpoints(1, - envoy.SocketAddress("23.23.247.89", 80), // addresses should be sorted - envoy.SocketAddress("50.17.192.147", 80), - envoy.SocketAddress("50.17.206.192", 80), - envoy.SocketAddress("50.19.99.160", 80), + Endpoints: v2.WeightedEndpoints(1, + v2.SocketAddress("23.23.247.89", 80), // addresses should be sorted + v2.SocketAddress("50.17.192.147", 80), + v2.SocketAddress("50.17.206.192", 80), + v2.SocketAddress("50.19.99.160", 80), ), }, }, @@ -211,15 +211,15 @@ func TestEndpointsTranslatorAddEndpoints(t *testing.T) { }), want: []proto.Message{ // Results should be sorted by cluster name. - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/httpbin-org/a", - Endpoints: envoy.WeightedEndpoints(1, envoy.SocketAddress("10.10.1.1", 8675)), + Endpoints: v2.WeightedEndpoints(1, v2.SocketAddress("10.10.1.1", 8675)), }, - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/httpbin-org/b", - Endpoints: envoy.WeightedEndpoints(1, envoy.SocketAddress("10.10.1.1", 309)), + Endpoints: v2.WeightedEndpoints(1, v2.SocketAddress("10.10.1.1", 309)), }, - &v2.ClusterLoadAssignment{ClusterName: "default/simple"}, + &envoy_api_v2.ClusterLoadAssignment{ClusterName: "default/simple"}, }, }, "cartesian product": { @@ -234,21 +234,21 @@ func TestEndpointsTranslatorAddEndpoints(t *testing.T) { ), }), want: []proto.Message{ - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/httpbin-org/a", - Endpoints: envoy.WeightedEndpoints(1, - envoy.SocketAddress("10.10.1.1", 8675), // addresses should be sorted - envoy.SocketAddress("10.10.2.2", 8675), + Endpoints: v2.WeightedEndpoints(1, + v2.SocketAddress("10.10.1.1", 8675), // addresses should be sorted + v2.SocketAddress("10.10.2.2", 8675), ), }, - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/httpbin-org/b", - Endpoints: envoy.WeightedEndpoints(1, - envoy.SocketAddress("10.10.1.1", 309), - envoy.SocketAddress("10.10.2.2", 309), + Endpoints: v2.WeightedEndpoints(1, + v2.SocketAddress("10.10.1.1", 309), + v2.SocketAddress("10.10.2.2", 309), ), }, - &v2.ClusterLoadAssignment{ClusterName: "default/simple"}, + &envoy_api_v2.ClusterLoadAssignment{ClusterName: "default/simple"}, }, }, "not ready": { @@ -272,20 +272,20 @@ func TestEndpointsTranslatorAddEndpoints(t *testing.T) { ), }), want: []proto.Message{ - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/httpbin-org/a", - Endpoints: envoy.WeightedEndpoints(1, - envoy.SocketAddress("10.10.1.1", 8675), + Endpoints: v2.WeightedEndpoints(1, + v2.SocketAddress("10.10.1.1", 8675), ), }, - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/httpbin-org/b", - Endpoints: envoy.WeightedEndpoints(1, - envoy.SocketAddress("10.10.1.1", 309), - envoy.SocketAddress("10.10.2.2", 309), + Endpoints: v2.WeightedEndpoints(1, + v2.SocketAddress("10.10.1.1", 309), + v2.SocketAddress("10.10.2.2", 309), ), }, - &v2.ClusterLoadAssignment{ClusterName: "default/simple"}, + &envoy_api_v2.ClusterLoadAssignment{ClusterName: "default/simple"}, }, }, } @@ -359,9 +359,9 @@ func TestEndpointsTranslatorRemoveEndpoints(t *testing.T) { ), }), want: []proto.Message{ - envoy.ClusterLoadAssignment("default/simple"), - envoy.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/http"), - envoy.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/https"), + v2.ClusterLoadAssignment("default/simple"), + v2.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/http"), + v2.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/https"), }, }, "remove different": { @@ -380,12 +380,12 @@ func TestEndpointsTranslatorRemoveEndpoints(t *testing.T) { ), }), want: []proto.Message{ - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/simple", - Endpoints: envoy.WeightedEndpoints(1, envoy.SocketAddress("192.168.183.24", 8080)), + Endpoints: v2.WeightedEndpoints(1, v2.SocketAddress("192.168.183.24", 8080)), }, - envoy.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/http"), - envoy.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/https"), + v2.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/http"), + v2.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/https"), }, }, "remove non existent": { @@ -397,9 +397,9 @@ func TestEndpointsTranslatorRemoveEndpoints(t *testing.T) { ), }), want: []proto.Message{ - envoy.ClusterLoadAssignment("default/simple"), - envoy.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/http"), - envoy.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/https"), + v2.ClusterLoadAssignment("default/simple"), + v2.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/http"), + v2.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/https"), }, }, "remove long name": { @@ -435,9 +435,9 @@ func TestEndpointsTranslatorRemoveEndpoints(t *testing.T) { }, ), want: []proto.Message{ - envoy.ClusterLoadAssignment("default/simple"), - envoy.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/http"), - envoy.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/https"), + v2.ClusterLoadAssignment("default/simple"), + v2.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/http"), + v2.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/https"), }, }, } @@ -481,10 +481,10 @@ func TestEndpointsTranslatorRecomputeClusterLoadAssignment(t *testing.T) { ), }), want: []proto.Message{ - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/simple", - Endpoints: envoy.WeightedEndpoints(1, - envoy.SocketAddress("192.168.183.24", 8080)), + Endpoints: v2.WeightedEndpoints(1, + v2.SocketAddress("192.168.183.24", 8080)), }, }, }, @@ -509,13 +509,13 @@ func TestEndpointsTranslatorRecomputeClusterLoadAssignment(t *testing.T) { ), }), want: []proto.Message{ - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/httpbin-org", - Endpoints: envoy.WeightedEndpoints(1, - envoy.SocketAddress("23.23.247.89", 80), - envoy.SocketAddress("50.17.192.147", 80), - envoy.SocketAddress("50.17.206.192", 80), - envoy.SocketAddress("50.19.99.160", 80), + Endpoints: v2.WeightedEndpoints(1, + v2.SocketAddress("23.23.247.89", 80), + v2.SocketAddress("50.17.192.147", 80), + v2.SocketAddress("50.17.206.192", 80), + v2.SocketAddress("50.19.99.160", 80), ), }, }, @@ -537,10 +537,10 @@ func TestEndpointsTranslatorRecomputeClusterLoadAssignment(t *testing.T) { ), }), want: []proto.Message{ - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/secure/https", - Endpoints: envoy.WeightedEndpoints(1, - envoy.SocketAddress("192.168.183.24", 8443)), + Endpoints: v2.WeightedEndpoints(1, + v2.SocketAddress("192.168.183.24", 8443)), }, }, }, @@ -583,9 +583,9 @@ func TestEndpointsTranslatorScaleToZeroEndpoints(t *testing.T) { // Assert endpoint was added want := []proto.Message{ - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/simple", - Endpoints: envoy.WeightedEndpoints(1, envoy.SocketAddress("192.168.183.24", 8080)), + Endpoints: v2.WeightedEndpoints(1, v2.SocketAddress("192.168.183.24", 8080)), }, } @@ -597,7 +597,7 @@ func TestEndpointsTranslatorScaleToZeroEndpoints(t *testing.T) { // Assert endpoints are removed want = []proto.Message{ - &v2.ClusterLoadAssignment{ClusterName: "default/simple"}, + &envoy_api_v2.ClusterLoadAssignment{ClusterName: "default/simple"}, } protobuf.RequireEqual(t, want, et.Contents()) @@ -646,12 +646,12 @@ func TestEndpointsTranslatorWeightedService(t *testing.T) { // Each helper builds a `LocalityLbEndpoints` with one // entry, so we can compose the final result by reaching // in an taking the first element of each slice. - w0 := envoy.Endpoints(envoy.SocketAddress("192.168.183.24", 8080)) - w1 := envoy.WeightedEndpoints(1, envoy.SocketAddress("192.168.183.24", 8080)) - w2 := envoy.WeightedEndpoints(2, envoy.SocketAddress("192.168.183.24", 8080)) + w0 := v2.Endpoints(v2.SocketAddress("192.168.183.24", 8080)) + w1 := v2.WeightedEndpoints(1, v2.SocketAddress("192.168.183.24", 8080)) + w2 := v2.WeightedEndpoints(2, v2.SocketAddress("192.168.183.24", 8080)) want := []proto.Message{ - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/weighted", Endpoints: []*envoy_api_v2_endpoint.LocalityLbEndpoints{ w0[0], w1[0], w2[0], @@ -704,12 +704,12 @@ func TestEndpointsTranslatorDefaultWeightedService(t *testing.T) { // Each helper builds a `LocalityLbEndpoints` with one // entry, so we can compose the final result by reaching // in an taking the first element of each slice. - w0 := envoy.WeightedEndpoints(1, envoy.SocketAddress("192.168.183.24", 8080)) - w1 := envoy.WeightedEndpoints(1, envoy.SocketAddress("192.168.183.24", 8080)) - w2 := envoy.WeightedEndpoints(1, envoy.SocketAddress("192.168.183.24", 8080)) + w0 := v2.WeightedEndpoints(1, v2.SocketAddress("192.168.183.24", 8080)) + w1 := v2.WeightedEndpoints(1, v2.SocketAddress("192.168.183.24", 8080)) + w2 := v2.WeightedEndpoints(1, v2.SocketAddress("192.168.183.24", 8080)) want := []proto.Message{ - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/weighted", Endpoints: []*envoy_api_v2_endpoint.LocalityLbEndpoints{ w0[0], w1[0], w2[0], @@ -732,8 +732,8 @@ func port(name string, port int32) v1.EndpointPort { } } -func clusterloadassignments(clas ...*v2.ClusterLoadAssignment) map[string]*v2.ClusterLoadAssignment { - m := make(map[string]*v2.ClusterLoadAssignment) +func clusterloadassignments(clas ...*envoy_api_v2.ClusterLoadAssignment) map[string]*envoy_api_v2.ClusterLoadAssignment { + m := make(map[string]*envoy_api_v2.ClusterLoadAssignment) for _, cla := range clas { m[cla.ClusterName] = cla } diff --git a/internal/contour/listener.go b/internal/contour/listener.go index e742024325b..43dbcb1d74f 100644 --- a/internal/contour/listener.go +++ b/internal/contour/listener.go @@ -18,7 +18,7 @@ import ( "sort" "sync" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" envoy_api_v2_listener "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener" envoy_api_v2_accesslog "github.com/envoyproxy/go-control-plane/envoy/config/filter/accesslog/v2" @@ -27,6 +27,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/projectcontour/contour/internal/dag" "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/protobuf" "github.com/projectcontour/contour/internal/sorter" "github.com/projectcontour/contour/internal/timeout" @@ -190,18 +191,18 @@ func (lvc *ListenerConfig) accesslogFields() []string { func (lvc *ListenerConfig) newInsecureAccessLog() []*envoy_api_v2_accesslog.AccessLog { switch lvc.accesslogType() { case "json": - return envoy.FileAccessLogJSON(lvc.httpAccessLog(), lvc.accesslogFields()) + return v2.FileAccessLogJSON(lvc.httpAccessLog(), lvc.accesslogFields()) default: - return envoy.FileAccessLogEnvoy(lvc.httpAccessLog()) + return v2.FileAccessLogEnvoy(lvc.httpAccessLog()) } } func (lvc *ListenerConfig) newSecureAccessLog() []*envoy_api_v2_accesslog.AccessLog { switch lvc.accesslogType() { case "json": - return envoy.FileAccessLogJSON(lvc.httpsAccessLog(), lvc.accesslogFields()) + return v2.FileAccessLogJSON(lvc.httpsAccessLog(), lvc.accesslogFields()) default: - return envoy.FileAccessLogEnvoy(lvc.httpsAccessLog()) + return v2.FileAccessLogEnvoy(lvc.httpsAccessLog()) } } @@ -217,8 +218,8 @@ func (lvc *ListenerConfig) minTLSVersion() envoy_api_v2_auth.TlsParameters_TlsPr // ListenerCache manages the contents of the gRPC LDS cache. type ListenerCache struct { mu sync.Mutex - values map[string]*v2.Listener - staticValues map[string]*v2.Listener + values map[string]*envoy_api_v2.Listener + staticValues map[string]*envoy_api_v2.Listener Config ListenerConfig Cond @@ -226,17 +227,17 @@ type ListenerCache struct { // NewListenerCache returns an instance of a ListenerCache func NewListenerCache(config ListenerConfig, address string, port int) *ListenerCache { - stats := envoy.StatsListener(address, port) + stats := v2.StatsListener(address, port) return &ListenerCache{ Config: config, - staticValues: map[string]*v2.Listener{ + staticValues: map[string]*envoy_api_v2.Listener{ stats.Name: stats, }, } } // Update replaces the contents of the cache with the supplied map. -func (c *ListenerCache) Update(v map[string]*v2.Listener) { +func (c *ListenerCache) Update(v map[string]*envoy_api_v2.Listener) { c.mu.Lock() defer c.mu.Unlock() @@ -248,7 +249,7 @@ func (c *ListenerCache) Update(v map[string]*v2.Listener) { func (c *ListenerCache) Contents() []proto.Message { c.mu.Lock() defer c.mu.Unlock() - var values []*v2.Listener + var values []*envoy_api_v2.Listener for _, v := range c.values { values = append(values, v) } @@ -264,7 +265,7 @@ func (c *ListenerCache) Contents() []proto.Message { func (c *ListenerCache) Query(names []string) []proto.Message { c.mu.Lock() defer c.mu.Unlock() - var values []*v2.Listener + var values []*envoy_api_v2.Listener for _, n := range names { v, ok := c.values[n] if !ok { @@ -294,15 +295,15 @@ func (c *ListenerCache) OnChange(root *dag.DAG) { type listenerVisitor struct { *ListenerConfig - listeners map[string]*v2.Listener + listeners map[string]*envoy_api_v2.Listener http bool // at least one dag.VirtualHost encountered } -func visitListeners(root dag.Vertex, lvc *ListenerConfig) map[string]*v2.Listener { +func visitListeners(root dag.Vertex, lvc *ListenerConfig) map[string]*envoy_api_v2.Listener { lv := listenerVisitor{ ListenerConfig: lvc, - listeners: map[string]*v2.Listener{ - ENVOY_HTTPS_LISTENER: envoy.Listener( + listeners: map[string]*envoy_api_v2.Listener{ + ENVOY_HTTPS_LISTENER: v2.Listener( ENVOY_HTTPS_LISTENER, lvc.httpsAddress(), lvc.httpsPort(), @@ -315,7 +316,7 @@ func visitListeners(root dag.Vertex, lvc *ListenerConfig) map[string]*v2.Listene if lv.http { // Add a listener if there are vhosts bound to http. - cm := envoy.HTTPConnectionManagerBuilder(). + cm := v2.HTTPConnectionManagerBuilder(). Codec(envoy.CodecForVersions(lv.DefaultHTTPVersions...)). DefaultFilters(). RouteConfigName(ENVOY_HTTP_LISTENER). @@ -328,7 +329,7 @@ func visitListeners(root dag.Vertex, lvc *ListenerConfig) map[string]*v2.Listene ConnectionShutdownGracePeriod(lvc.ConnectionShutdownGracePeriod). Get() - lv.listeners[ENVOY_HTTP_LISTENER] = envoy.Listener( + lv.listeners[ENVOY_HTTP_LISTENER] = v2.Listener( ENVOY_HTTP_LISTENER, lvc.httpAddress(), lvc.httpPort(), @@ -351,15 +352,15 @@ func visitListeners(root dag.Vertex, lvc *ListenerConfig) map[string]*v2.Listene func proxyProtocol(useProxy bool) []*envoy_api_v2_listener.ListenerFilter { if useProxy { - return envoy.ListenerFilters( - envoy.ProxyProtocol(), + return v2.ListenerFilters( + v2.ProxyProtocol(), ) } return nil } func secureProxyProtocol(useProxy bool) []*envoy_api_v2_listener.ListenerFilter { - return append(proxyProtocol(useProxy), envoy.TLSInspector()) + return append(proxyProtocol(useProxy), v2.TLSInspector()) } func (v *listenerVisitor) visit(vertex dag.Vertex) { @@ -384,7 +385,7 @@ func (v *listenerVisitor) visit(vertex dag.Vertex) { var authFilter *http.HttpFilter if vh.AuthorizationService != nil { - authFilter = envoy.FilterExternalAuthz( + authFilter = v2.FilterExternalAuthz( vh.AuthorizationService.Name, vh.AuthorizationFailOpen, vh.AuthorizationResponseTimeout, @@ -398,10 +399,10 @@ func (v *listenerVisitor) visit(vertex dag.Vertex) { // metrics prefix to keep compatibility with previous // Contour versions since the metrics prefix will be // coded into monitoring dashboards. - filters = envoy.Filters( - envoy.HTTPConnectionManagerBuilder(). + filters = v2.Filters( + v2.HTTPConnectionManagerBuilder(). Codec(envoy.CodecForVersions(v.DefaultHTTPVersions...)). - AddFilter(envoy.FilterMisdirectedRequests(vh.VirtualHost.Name)). + AddFilter(v2.FilterMisdirectedRequests(vh.VirtualHost.Name)). DefaultFilters(). AddFilter(authFilter). RouteConfigName(path.Join("https", vh.VirtualHost.Name)). @@ -417,8 +418,8 @@ func (v *listenerVisitor) visit(vertex dag.Vertex) { alpnProtos = envoy.ProtoNamesForVersions(v.DefaultHTTPVersions...) } else { - filters = envoy.Filters( - envoy.TCPProxy(ENVOY_HTTPS_LISTENER, + filters = v2.Filters( + v2.TCPProxy(ENVOY_HTTPS_LISTENER, vh.TCPProxy, v.ListenerConfig.newSecureAccessLog()), ) @@ -435,7 +436,7 @@ func (v *listenerVisitor) visit(vertex dag.Vertex) { // Choose the higher of the configured or requested TLS version. vers := max(v.ListenerConfig.minTLSVersion(), vh.MinTLSVersion) - downstreamTLS = envoy.DownstreamTLSContext( + downstreamTLS = v2.DownstreamTLSContext( vh.Secret, vers, vh.DownstreamValidation, @@ -443,25 +444,25 @@ func (v *listenerVisitor) visit(vertex dag.Vertex) { } v.listeners[ENVOY_HTTPS_LISTENER].FilterChains = append(v.listeners[ENVOY_HTTPS_LISTENER].FilterChains, - envoy.FilterChainTLS(vh.VirtualHost.Name, downstreamTLS, filters)) + v2.FilterChainTLS(vh.VirtualHost.Name, downstreamTLS, filters)) // If this VirtualHost has enabled the fallback certificate then set a default // FilterChain which will allow routes with this vhost to accept non-SNI TLS requests. // Note that we don't add the misdirected requests filter on this chain because at this // point we don't actually know the full set of server names that will be bound to the // filter chain through the ENVOY_FALLBACK_ROUTECONFIG route configuration. - if vh.FallbackCertificate != nil && !envoy.ContainsFallbackFilterChain(v.listeners[ENVOY_HTTPS_LISTENER].FilterChains) { + if vh.FallbackCertificate != nil && !v2.ContainsFallbackFilterChain(v.listeners[ENVOY_HTTPS_LISTENER].FilterChains) { // Construct the downstreamTLSContext passing the configured fallbackCertificate. The TLS minProtocolVersion will use // the value defined in the Contour Configuration file if defined. - downstreamTLS = envoy.DownstreamTLSContext( + downstreamTLS = v2.DownstreamTLSContext( vh.FallbackCertificate, v.ListenerConfig.minTLSVersion(), vh.DownstreamValidation, alpnProtos...) // Default filter chain - filters = envoy.Filters( - envoy.HTTPConnectionManagerBuilder(). + filters = v2.Filters( + v2.HTTPConnectionManagerBuilder(). DefaultFilters(). RouteConfigName(ENVOY_FALLBACK_ROUTECONFIG). MetricsPrefix(ENVOY_HTTPS_LISTENER). @@ -475,7 +476,7 @@ func (v *listenerVisitor) visit(vertex dag.Vertex) { ) v.listeners[ENVOY_HTTPS_LISTENER].FilterChains = append(v.listeners[ENVOY_HTTPS_LISTENER].FilterChains, - envoy.FilterChainTLSFallback(downstreamTLS, filters)) + v2.FilterChainTLSFallback(downstreamTLS, filters)) } default: diff --git a/internal/contour/listener_test.go b/internal/contour/listener_test.go index cfd3bae1a1d..bf790a47070 100644 --- a/internal/contour/listener_test.go +++ b/internal/contour/listener_test.go @@ -18,14 +18,14 @@ import ( "testing" "time" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" envoy_api_v2_listener "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener" "github.com/golang/protobuf/proto" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/protobuf" "github.com/projectcontour/contour/internal/timeout" v1 "k8s.io/api/core/v1" @@ -36,7 +36,7 @@ import ( func TestListenerCacheContents(t *testing.T) { tests := map[string]struct { - contents map[string]*v2.Listener + contents map[string]*envoy_api_v2.Listener want []proto.Message }{ "empty": { @@ -44,18 +44,18 @@ func TestListenerCacheContents(t *testing.T) { want: nil, }, "simple": { - contents: listenermap(&v2.Listener{ + contents: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), want: []proto.Message{ - &v2.Listener{ + &envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, }, }, @@ -73,50 +73,50 @@ func TestListenerCacheContents(t *testing.T) { func TestListenerCacheQuery(t *testing.T) { tests := map[string]struct { - contents map[string]*v2.Listener + contents map[string]*envoy_api_v2.Listener query []string want []proto.Message }{ "exact match": { - contents: listenermap(&v2.Listener{ + contents: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), query: []string{ENVOY_HTTP_LISTENER}, want: []proto.Message{ - &v2.Listener{ + &envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, }, }, "partial match": { - contents: listenermap(&v2.Listener{ + contents: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), query: []string{ENVOY_HTTP_LISTENER, "stats-listener"}, want: []proto.Message{ - &v2.Listener{ + &envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, }, }, "no match": { - contents: listenermap(&v2.Listener{ + contents: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), query: []string{"stats-listener"}, want: nil, @@ -135,31 +135,31 @@ func TestListenerCacheQuery(t *testing.T) { func TestListenerVisit(t *testing.T) { httpsFilterFor := func(vhost string) *envoy_api_v2_listener.Filter { - return envoy.HTTPConnectionManagerBuilder(). - AddFilter(envoy.FilterMisdirectedRequests(vhost)). + return v2.HTTPConnectionManagerBuilder(). + AddFilter(v2.FilterMisdirectedRequests(vhost)). DefaultFilters(). MetricsPrefix(ENVOY_HTTPS_LISTENER). RouteConfigName(path.Join("https", vhost)). - AccessLoggers(envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). Get() } - fallbackCertFilter := envoy.HTTPConnectionManagerBuilder(). + fallbackCertFilter := v2.HTTPConnectionManagerBuilder(). DefaultFilters(). MetricsPrefix(ENVOY_HTTPS_LISTENER). RouteConfigName(ENVOY_FALLBACK_ROUTECONFIG). - AccessLoggers(envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). Get() tests := map[string]struct { ListenerConfig fallbackCertificate *types.NamespacedName objs []interface{} - want map[string]*v2.Listener + want map[string]*envoy_api_v2.Listener }{ "nothing": { objs: nil, - want: map[string]*v2.Listener{}, + want: map[string]*envoy_api_v2.Listener{}, }, "one http only ingress": { objs: []interface{}{ @@ -186,11 +186,11 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "one http only httpproxy": { @@ -229,11 +229,11 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "simple ingress with secret": { @@ -282,25 +282,25 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"whatever.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(httpsFilterFor("whatever.example.com")), + Filters: v2.Filters(httpsFilterFor("whatever.example.com")), }}, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "multiple tls ingress with secrets should be sorted": { @@ -371,31 +371,31 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"sortedfirst.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(httpsFilterFor("sortedfirst.example.com")), + Filters: v2.Filters(httpsFilterFor("sortedfirst.example.com")), }, { FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"sortedsecond.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(httpsFilterFor("sortedsecond.example.com")), + Filters: v2.Filters(httpsFilterFor("sortedsecond.example.com")), }}, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "simple ingress with missing secret": { @@ -444,11 +444,11 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "simple httpproxy with secret": { @@ -495,25 +495,25 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"www.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(httpsFilterFor("www.example.com")), + Filters: v2.Filters(httpsFilterFor("www.example.com")), }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "ingress with allow-http: false": { @@ -531,7 +531,7 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: map[string]*v2.Listener{}, + want: map[string]*envoy_api_v2.Listener{}, }, "simple tls ingress with allow-http:false": { objs: []interface{}{ @@ -582,20 +582,20 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"www.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(httpsFilterFor("www.example.com")), + Filters: v2.Filters(httpsFilterFor("www.example.com")), }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "http listener on non default port": { // issue 72 @@ -650,25 +650,25 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("127.0.0.100", 9100), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + Address: v2.SocketAddress("127.0.0.100", 9100), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("127.0.0.200", 9200), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("127.0.0.200", 9200), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"whatever.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(httpsFilterFor("whatever.example.com")), + Filters: v2.Filters(httpsFilterFor("whatever.example.com")), }}, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "use proxy proto": { @@ -720,29 +720,29 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - ListenerFilters: envoy.ListenerFilters( - envoy.ProxyProtocol(), + Address: v2.SocketAddress("0.0.0.0", 8080), + ListenerFilters: v2.ListenerFilters( + v2.ProxyProtocol(), ), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.ProxyProtocol(), - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.ProxyProtocol(), + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"whatever.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(httpsFilterFor("whatever.example.com")), + Filters: v2.Filters(httpsFilterFor("whatever.example.com")), }}, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "--envoy-http-access-log": { @@ -795,31 +795,31 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress(DEFAULT_HTTP_LISTENER_ADDRESS, DEFAULT_HTTP_LISTENER_PORT), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy("/tmp/http_access.log"), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + Address: v2.SocketAddress(DEFAULT_HTTP_LISTENER_ADDRESS, DEFAULT_HTTP_LISTENER_PORT), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy("/tmp/http_access.log"), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress(DEFAULT_HTTPS_LISTENER_ADDRESS, DEFAULT_HTTPS_LISTENER_PORT), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress(DEFAULT_HTTPS_LISTENER_ADDRESS, DEFAULT_HTTPS_LISTENER_PORT), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"whatever.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(envoy.HTTPConnectionManagerBuilder(). - AddFilter(envoy.FilterMisdirectedRequests("whatever.example.com")). + Filters: v2.Filters(v2.HTTPConnectionManagerBuilder(). + AddFilter(v2.FilterMisdirectedRequests("whatever.example.com")). DefaultFilters(). MetricsPrefix(ENVOY_HTTPS_LISTENER). RouteConfigName(path.Join("https", "whatever.example.com")). - AccessLoggers(envoy.FileAccessLogEnvoy("/tmp/https_access.log")). + AccessLoggers(v2.FileAccessLogEnvoy("/tmp/https_access.log")). Get()), }}, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "tls-min-protocol-version from config": { @@ -871,25 +871,25 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"whatever.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_3, "h2", "http/1.1"), - Filters: envoy.Filters(httpsFilterFor("whatever.example.com")), + Filters: v2.Filters(httpsFilterFor("whatever.example.com")), }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "tls-min-protocol-version from config overridden by annotation": { @@ -944,25 +944,25 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"whatever.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_3, "h2", "http/1.1"), // note, cannot downgrade from the configured version - Filters: envoy.Filters(httpsFilterFor("whatever.example.com")), + Filters: v2.Filters(httpsFilterFor("whatever.example.com")), }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "tls-min-protocol-version from config overridden by legacy annotation": { @@ -1017,25 +1017,25 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"whatever.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_3, "h2", "http/1.1"), // note, cannot downgrade from the configured version - Filters: envoy.Filters(httpsFilterFor("whatever.example.com")), + Filters: v2.Filters(httpsFilterFor("whatever.example.com")), }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "tls-min-protocol-version from config overridden by httpproxy": { @@ -1086,25 +1086,25 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"www.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_3, "h2", "http/1.1"), // note, cannot downgrade from the configured version - Filters: envoy.Filters(httpsFilterFor("www.example.com")), + Filters: v2.Filters(httpsFilterFor("www.example.com")), }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "httpproxy with fallback certificate": { @@ -1168,32 +1168,32 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"www.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(httpsFilterFor("www.example.com")), + Filters: v2.Filters(httpsFilterFor("www.example.com")), }, { FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ TransportProtocol: "tls", }, TransportSocket: transportSocket("fallbacksecret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(fallbackCertFilter), + Filters: v2.Filters(fallbackCertFilter), Name: "fallback-certificate", }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "multiple httpproxies with fallback certificate": { @@ -1282,41 +1282,41 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{ { FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"www.another.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(httpsFilterFor("www.another.com")), + Filters: v2.Filters(httpsFilterFor("www.another.com")), }, { FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"www.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(httpsFilterFor("www.example.com")), + Filters: v2.Filters(httpsFilterFor("www.example.com")), }, { FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ TransportProtocol: "tls", }, TransportSocket: transportSocket("fallbacksecret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(fallbackCertFilter), + Filters: v2.Filters(fallbackCertFilter), Name: "fallback-certificate", }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "httpproxy with fallback certificate - no cert passed": { @@ -1427,25 +1427,25 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager(ENVOY_HTTP_LISTENER, envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager(ENVOY_HTTP_LISTENER, v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"www.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(httpsFilterFor("www.example.com")), + Filters: v2.Filters(httpsFilterFor("www.example.com")), }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "httpproxy with connection idle timeout set in visitor config": { @@ -1487,19 +1487,19 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManagerBuilder(). + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManagerBuilder(). RouteConfigName(ENVOY_HTTP_LISTENER). MetricsPrefix(ENVOY_HTTP_LISTENER). - AccessLoggers(envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). DefaultFilters(). ConnectionIdleTimeout(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "httpproxy with stream idle timeout set in visitor config": { @@ -1541,19 +1541,19 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManagerBuilder(). + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManagerBuilder(). RouteConfigName(ENVOY_HTTP_LISTENER). MetricsPrefix(ENVOY_HTTP_LISTENER). - AccessLoggers(envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). DefaultFilters(). StreamIdleTimeout(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "httpproxy with max connection duration set in visitor config": { @@ -1595,19 +1595,19 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManagerBuilder(). + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManagerBuilder(). RouteConfigName(ENVOY_HTTP_LISTENER). MetricsPrefix(ENVOY_HTTP_LISTENER). - AccessLoggers(envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). DefaultFilters(). MaxConnectionDuration(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "httpproxy with connection shutdown grace period set in visitor config": { @@ -1649,19 +1649,19 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManagerBuilder(). + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManagerBuilder(). RouteConfigName(ENVOY_HTTP_LISTENER). MetricsPrefix(ENVOY_HTTP_LISTENER). - AccessLoggers(envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). DefaultFilters(). ConnectionShutdownGracePeriod(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "httpsproxy with secret with connection idle timeout set in visitor config": { @@ -1711,39 +1711,39 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManagerBuilder(). + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManagerBuilder(). RouteConfigName(ENVOY_HTTP_LISTENER). MetricsPrefix(ENVOY_HTTP_LISTENER). - AccessLoggers(envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). DefaultFilters(). ConnectionIdleTimeout(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"www.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(envoy.HTTPConnectionManagerBuilder(). - AddFilter(envoy.FilterMisdirectedRequests("www.example.com")). + Filters: v2.Filters(v2.HTTPConnectionManagerBuilder(). + AddFilter(v2.FilterMisdirectedRequests("www.example.com")). DefaultFilters(). MetricsPrefix(ENVOY_HTTPS_LISTENER). RouteConfigName(path.Join("https", "www.example.com")). - AccessLoggers(envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). ConnectionIdleTimeout(timeout.DurationSetting(90 * time.Second)). Get()), }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "httpsproxy with secret with stream idle timeout set in visitor config": { @@ -1793,39 +1793,39 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManagerBuilder(). + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManagerBuilder(). RouteConfigName(ENVOY_HTTP_LISTENER). MetricsPrefix(ENVOY_HTTP_LISTENER). - AccessLoggers(envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). DefaultFilters(). StreamIdleTimeout(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"www.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(envoy.HTTPConnectionManagerBuilder(). - AddFilter(envoy.FilterMisdirectedRequests("www.example.com")). + Filters: v2.Filters(v2.HTTPConnectionManagerBuilder(). + AddFilter(v2.FilterMisdirectedRequests("www.example.com")). DefaultFilters(). MetricsPrefix(ENVOY_HTTPS_LISTENER). RouteConfigName(path.Join("https", "www.example.com")). - AccessLoggers(envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). StreamIdleTimeout(timeout.DurationSetting(90 * time.Second)). Get()), }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "httpsproxy with secret with max connection duration set in visitor config": { @@ -1875,39 +1875,39 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManagerBuilder(). + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManagerBuilder(). RouteConfigName(ENVOY_HTTP_LISTENER). MetricsPrefix(ENVOY_HTTP_LISTENER). - AccessLoggers(envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). DefaultFilters(). MaxConnectionDuration(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"www.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(envoy.HTTPConnectionManagerBuilder(). - AddFilter(envoy.FilterMisdirectedRequests("www.example.com")). + Filters: v2.Filters(v2.HTTPConnectionManagerBuilder(). + AddFilter(v2.FilterMisdirectedRequests("www.example.com")). DefaultFilters(). MetricsPrefix(ENVOY_HTTPS_LISTENER). RouteConfigName(path.Join("https", "www.example.com")). - AccessLoggers(envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). MaxConnectionDuration(timeout.DurationSetting(90 * time.Second)). Get()), }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, "httpsproxy with secret with connection shutdown grace period set in visitor config": { @@ -1957,39 +1957,39 @@ func TestListenerVisit(t *testing.T) { }, }, }, - want: listenermap(&v2.Listener{ + want: listenermap(&envoy_api_v2.Listener{ Name: ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManagerBuilder(). + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManagerBuilder(). RouteConfigName(ENVOY_HTTP_LISTENER). MetricsPrefix(ENVOY_HTTP_LISTENER). - AccessLoggers(envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). DefaultFilters(). ConnectionShutdownGracePeriod(timeout.DurationSetting(90 * time.Second)). Get(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - }, &v2.Listener{ + SocketOptions: v2.TCPKeepaliveSocketOptions(), + }, &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"www.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1, "h2", "http/1.1"), - Filters: envoy.Filters(envoy.HTTPConnectionManagerBuilder(). - AddFilter(envoy.FilterMisdirectedRequests("www.example.com")). + Filters: v2.Filters(v2.HTTPConnectionManagerBuilder(). + AddFilter(v2.FilterMisdirectedRequests("www.example.com")). DefaultFilters(). MetricsPrefix(ENVOY_HTTPS_LISTENER). RouteConfigName(path.Join("https", "www.example.com")). - AccessLoggers(envoy.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(DEFAULT_HTTP_ACCESS_LOG)). ConnectionShutdownGracePeriod(timeout.DurationSetting(90 * time.Second)). Get()), }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }), }, } @@ -2014,13 +2014,13 @@ func transportSocket(secretname string, tlsMinProtoVersion envoy_api_v2_auth.Tls Data: secretdata(CERTIFICATE, RSA_PRIVATE_KEY), }, } - return envoy.DownstreamTLSTransportSocket( - envoy.DownstreamTLSContext(secret, tlsMinProtoVersion, nil, alpnprotos...), + return v2.DownstreamTLSTransportSocket( + v2.DownstreamTLSContext(secret, tlsMinProtoVersion, nil, alpnprotos...), ) } -func listenermap(listeners ...*v2.Listener) map[string]*v2.Listener { - m := make(map[string]*v2.Listener) +func listenermap(listeners ...*envoy_api_v2.Listener) map[string]*envoy_api_v2.Listener { + m := make(map[string]*envoy_api_v2.Listener) for _, l := range listeners { m[l.Name] = l } diff --git a/internal/contour/route.go b/internal/contour/route.go index d5e8530f1fa..3126cd3785b 100644 --- a/internal/contour/route.go +++ b/internal/contour/route.go @@ -18,13 +18,13 @@ import ( "sort" "sync" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" resource "github.com/envoyproxy/go-control-plane/pkg/resource/v2" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes/any" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/protobuf" "github.com/projectcontour/contour/internal/sorter" ) @@ -32,12 +32,12 @@ import ( // RouteCache manages the contents of the gRPC RDS cache. type RouteCache struct { mu sync.Mutex - values map[string]*v2.RouteConfiguration + values map[string]*envoy_api_v2.RouteConfiguration Cond } // Update replaces the contents of the cache with the supplied map. -func (c *RouteCache) Update(v map[string]*v2.RouteConfiguration) { +func (c *RouteCache) Update(v map[string]*envoy_api_v2.RouteConfiguration) { c.mu.Lock() defer c.mu.Unlock() @@ -50,7 +50,7 @@ func (c *RouteCache) Contents() []proto.Message { c.mu.Lock() defer c.mu.Unlock() - var values []*v2.RouteConfiguration + var values []*envoy_api_v2.RouteConfiguration for _, v := range c.values { values = append(values, v) } @@ -64,7 +64,7 @@ func (c *RouteCache) Query(names []string) []proto.Message { c.mu.Lock() defer c.mu.Unlock() - var values []*v2.RouteConfiguration + var values []*envoy_api_v2.RouteConfiguration for _, n := range names { v, ok := c.values[n] if !ok { @@ -73,7 +73,7 @@ func (c *RouteCache) Query(names []string) []proto.Message { // 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 = &v2.RouteConfiguration{ + v = &envoy_api_v2.RouteConfiguration{ Name: n, } } @@ -94,18 +94,18 @@ func (c *RouteCache) OnChange(root *dag.DAG) { } type routeVisitor struct { - routes map[string]*v2.RouteConfiguration + routes map[string]*envoy_api_v2.RouteConfiguration } -func visitRoutes(root dag.Vertex) map[string]*v2.RouteConfiguration { +func visitRoutes(root dag.Vertex) map[string]*envoy_api_v2.RouteConfiguration { // Collect the route configurations for all the routes we can // find. For HTTP hosts, the routes will all be collected on the // well-known ENVOY_HTTP_LISTENER, but for HTTPS hosts, we will // generate a per-vhost collection. This lets us keep different // SNI names disjoint when we later configure the listener. rv := routeVisitor{ - routes: map[string]*v2.RouteConfiguration{ - ENVOY_HTTP_LISTENER: envoy.RouteConfiguration(ENVOY_HTTP_LISTENER), + routes: map[string]*envoy_api_v2.RouteConfiguration{ + ENVOY_HTTP_LISTENER: v2.RouteConfiguration(ENVOY_HTTP_LISTENER), }, } @@ -132,20 +132,20 @@ func (v *routeVisitor) onVirtualHost(vh *dag.VirtualHost) { // to a SecureVirtualHost that requires upgrade, this logic can move to // envoy.RouteRoute. routes = append(routes, &envoy_api_v2_route.Route{ - Match: envoy.RouteMatch(route), - Action: envoy.UpgradeHTTPS(), + Match: v2.RouteMatch(route), + Action: v2.UpgradeHTTPS(), }) } else { rt := &envoy_api_v2_route.Route{ - Match: envoy.RouteMatch(route), - Action: envoy.RouteRoute(route), + Match: v2.RouteMatch(route), + Action: v2.RouteRoute(route), } if route.RequestHeadersPolicy != nil { - rt.RequestHeadersToAdd = envoy.HeaderValueList(route.RequestHeadersPolicy.Set, false) + rt.RequestHeadersToAdd = v2.HeaderValueList(route.RequestHeadersPolicy.Set, false) rt.RequestHeadersToRemove = route.RequestHeadersPolicy.Remove } if route.ResponseHeadersPolicy != nil { - rt.ResponseHeadersToAdd = envoy.HeaderValueList(route.ResponseHeadersPolicy.Set, false) + rt.ResponseHeadersToAdd = v2.HeaderValueList(route.ResponseHeadersPolicy.Set, false) rt.ResponseHeadersToRemove = route.ResponseHeadersPolicy.Remove } routes = append(routes, rt) @@ -156,7 +156,7 @@ func (v *routeVisitor) onVirtualHost(vh *dag.VirtualHost) { sortRoutes(routes) v.routes[ENVOY_HTTP_LISTENER].VirtualHosts = append(v.routes[ENVOY_HTTP_LISTENER].VirtualHosts, - envoy.VirtualHost(vh.Name, routes...)) + v2.VirtualHost(vh.Name, routes...)) } } @@ -170,15 +170,15 @@ func (v *routeVisitor) onSecureVirtualHost(svh *dag.SecureVirtualHost) { } rt := &envoy_api_v2_route.Route{ - Match: envoy.RouteMatch(route), - Action: envoy.RouteRoute(route), + Match: v2.RouteMatch(route), + Action: v2.RouteRoute(route), } if route.RequestHeadersPolicy != nil { - rt.RequestHeadersToAdd = envoy.HeaderValueList(route.RequestHeadersPolicy.Set, false) + rt.RequestHeadersToAdd = v2.HeaderValueList(route.RequestHeadersPolicy.Set, false) rt.RequestHeadersToRemove = route.RequestHeadersPolicy.Remove } if route.ResponseHeadersPolicy != nil { - rt.ResponseHeadersToAdd = envoy.HeaderValueList(route.ResponseHeadersPolicy.Set, false) + rt.ResponseHeadersToAdd = v2.HeaderValueList(route.ResponseHeadersPolicy.Set, false) rt.ResponseHeadersToRemove = route.ResponseHeadersPolicy.Remove } @@ -187,12 +187,12 @@ func (v *routeVisitor) onSecureVirtualHost(svh *dag.SecureVirtualHost) { // Apply per-route authorization policy modifications. if route.AuthDisabled { rt.TypedPerFilterConfig = map[string]*any.Any{ - "envoy.filters.http.ext_authz": envoy.RouteAuthzDisabled(), + "envoy.filters.http.ext_authz": v2.RouteAuthzDisabled(), } } else { if len(route.AuthContext) > 0 { rt.TypedPerFilterConfig = map[string]*any.Any{ - "envoy.filters.http.ext_authz": envoy.RouteAuthzContext(route.AuthContext), + "envoy.filters.http.ext_authz": v2.RouteAuthzContext(route.AuthContext), } } } @@ -207,11 +207,11 @@ func (v *routeVisitor) onSecureVirtualHost(svh *dag.SecureVirtualHost) { name := path.Join("https", svh.VirtualHost.Name) if _, ok := v.routes[name]; !ok { - v.routes[name] = envoy.RouteConfiguration(name) + v.routes[name] = v2.RouteConfiguration(name) } v.routes[name].VirtualHosts = append(v.routes[name].VirtualHosts, - envoy.VirtualHost(svh.VirtualHost.Name, routes...)) + v2.VirtualHost(svh.VirtualHost.Name, routes...)) // A fallback route configuration contains routes for all the vhosts that have the fallback certificate enabled. // When a request is received, the default TLS filterchain will accept the connection, @@ -219,11 +219,11 @@ func (v *routeVisitor) onSecureVirtualHost(svh *dag.SecureVirtualHost) { if svh.FallbackCertificate != nil { // Add fallback route if not already if _, ok := v.routes[ENVOY_FALLBACK_ROUTECONFIG]; !ok { - v.routes[ENVOY_FALLBACK_ROUTECONFIG] = envoy.RouteConfiguration(ENVOY_FALLBACK_ROUTECONFIG) + v.routes[ENVOY_FALLBACK_ROUTECONFIG] = v2.RouteConfiguration(ENVOY_FALLBACK_ROUTECONFIG) } v.routes[ENVOY_FALLBACK_ROUTECONFIG].VirtualHosts = append(v.routes[ENVOY_FALLBACK_ROUTECONFIG].VirtualHosts, - envoy.VirtualHost(svh.Name, routes...)) + v2.VirtualHost(svh.Name, routes...)) } } } diff --git a/internal/contour/route_test.go b/internal/contour/route_test.go index 153a9edafae..083d51b40ec 100644 --- a/internal/contour/route_test.go +++ b/internal/contour/route_test.go @@ -17,14 +17,14 @@ import ( "testing" "time" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes/wrappers" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/protobuf" v1 "k8s.io/api/core/v1" "k8s.io/api/networking/v1beta1" @@ -35,7 +35,7 @@ import ( func TestRouteCacheContents(t *testing.T) { tests := map[string]struct { - contents map[string]*v2.RouteConfiguration + contents map[string]*envoy_api_v2.RouteConfiguration want []proto.Message }{ "empty": { @@ -43,7 +43,7 @@ func TestRouteCacheContents(t *testing.T) { want: nil, }, "simple": { - contents: map[string]*v2.RouteConfiguration{ + contents: map[string]*envoy_api_v2.RouteConfiguration{ "ingress_http": { Name: "ingress_http", }, @@ -52,10 +52,10 @@ func TestRouteCacheContents(t *testing.T) { }, }, want: []proto.Message{ - &v2.RouteConfiguration{ + &envoy_api_v2.RouteConfiguration{ Name: "ingress_http", }, - &v2.RouteConfiguration{ + &envoy_api_v2.RouteConfiguration{ Name: "ingress_https", }, }, @@ -74,48 +74,48 @@ func TestRouteCacheContents(t *testing.T) { func TestRouteCacheQuery(t *testing.T) { tests := map[string]struct { - contents map[string]*v2.RouteConfiguration + contents map[string]*envoy_api_v2.RouteConfiguration query []string want []proto.Message }{ "exact match": { - contents: map[string]*v2.RouteConfiguration{ + contents: map[string]*envoy_api_v2.RouteConfiguration{ "ingress_http": { Name: "ingress_http", }, }, query: []string{"ingress_http"}, want: []proto.Message{ - &v2.RouteConfiguration{ + &envoy_api_v2.RouteConfiguration{ Name: "ingress_http", }, }, }, "partial match": { - contents: map[string]*v2.RouteConfiguration{ + contents: map[string]*envoy_api_v2.RouteConfiguration{ "ingress_http": { Name: "ingress_http", }, }, query: []string{"stats-handler", "ingress_http"}, want: []proto.Message{ - &v2.RouteConfiguration{ + &envoy_api_v2.RouteConfiguration{ Name: "ingress_http", }, - &v2.RouteConfiguration{ + &envoy_api_v2.RouteConfiguration{ Name: "stats-handler", }, }, }, "no match": { - contents: map[string]*v2.RouteConfiguration{ + contents: map[string]*envoy_api_v2.RouteConfiguration{ "ingress_http": { Name: "ingress_http", }, }, query: []string{"stats-handler"}, want: []proto.Message{ - &v2.RouteConfiguration{ + &envoy_api_v2.RouteConfiguration{ Name: "stats-handler", }, }, @@ -136,12 +136,12 @@ func TestRouteVisit(t *testing.T) { tests := map[string]struct { objs []interface{} fallbackCertificate *types.NamespacedName - want map[string]*v2.RouteConfiguration + want map[string]*envoy_api_v2.RouteConfiguration }{ "nothing": { objs: nil, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), }, "one http only ingress with service": { @@ -170,8 +170,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/8080/da39a3ee5e"), @@ -218,8 +218,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routeRegex("/[^/]+/invoices(/.*|/?)"), Action: routecluster("default/kuard/8080/da39a3ee5e"), @@ -262,8 +262,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/backend/80/da39a3ee5e"), @@ -310,8 +310,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/8080/da39a3ee5e"), @@ -371,16 +371,16 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/8080/da39a3ee5e"), }, ), ), - envoy.RouteConfiguration("https/www.example.com", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("https/www.example.com", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/8080/da39a3ee5e"), @@ -438,8 +438,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Redirect{ @@ -452,8 +452,8 @@ func TestRouteVisit(t *testing.T) { }, ), ), - envoy.RouteConfiguration("https/www.example.com", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("https/www.example.com", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/backend/8080/da39a3ee5e"), @@ -516,9 +516,9 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http"), - envoy.RouteConfiguration("https/www.example.com", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("https/www.example.com", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/8080/da39a3ee5e"), @@ -581,8 +581,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Redirect{ @@ -595,8 +595,8 @@ func TestRouteVisit(t *testing.T) { }, ), ), - envoy.RouteConfiguration("https/www.example.com", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("https/www.example.com", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/8080/da39a3ee5e"), @@ -654,8 +654,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/ws1"), Action: websocketroute("default/kuard/8080/da39a3ee5e"), @@ -697,8 +697,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/8080/da39a3ee5e"), @@ -736,8 +736,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routetimeout("default/kuard/8080/da39a3ee5e", 0), @@ -775,8 +775,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routetimeout("default/kuard/8080/da39a3ee5e", 90*time.Second), @@ -825,8 +825,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("my-very-very-long-service-host-name.subdomain.boring-dept.my.company", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("my-very-very-long-service-host-name.subdomain.boring-dept.my.company", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/80/da39a3ee5e"), @@ -864,8 +864,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeretry("default/kuard/8080/da39a3ee5e", "5xx,gateway-error", 0, 0), @@ -904,8 +904,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeretry("default/kuard/8080/da39a3ee5e", "5xx,gateway-error", 7, 0), @@ -945,8 +945,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeretry("default/kuard/8080/da39a3ee5e", "5xx,gateway-error", 7, 0), @@ -985,8 +985,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeretry("default/kuard/8080/da39a3ee5e", "5xx,gateway-error", 0, 150*time.Millisecond), @@ -1025,8 +1025,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeretry("default/kuard/8080/da39a3ee5e", "5xx,gateway-error", 0, 150*time.Millisecond), @@ -1089,8 +1089,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -1165,8 +1165,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -1242,8 +1242,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -1296,7 +1296,7 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http"), // should be blank, no fqdn defined. + v2.RouteConfiguration("ingress_http"), // should be blank, no fqdn defined. ), }, "httpproxy with pathPrefix": { @@ -1352,8 +1352,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -1428,8 +1428,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withMirrorPolicy(routecluster("default/backend/80/da39a3ee5e"), "default/backendtwo/80/da39a3ee5e"), @@ -1502,8 +1502,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Redirect{ @@ -1516,8 +1516,8 @@ func TestRouteVisit(t *testing.T) { }, ), ), - envoy.RouteConfiguration("https/www.example.com", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("https/www.example.com", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -1627,8 +1627,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/blog/info"), Action: routecluster("teama/backend/80/da39a3ee5e"), @@ -1695,8 +1695,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/", dag.HeaderMatchCondition{ Name: "x-header", @@ -1753,8 +1753,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/", dag.HeaderMatchCondition{ Name: "x-header", @@ -1812,8 +1812,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/", dag.HeaderMatchCondition{ Name: "x-header", @@ -1871,8 +1871,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/", dag.HeaderMatchCondition{ Name: "x-header", @@ -1930,8 +1930,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/", dag.HeaderMatchCondition{ Name: "x-header", @@ -1997,8 +1997,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -2110,8 +2110,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Redirect{ @@ -2124,8 +2124,8 @@ func TestRouteVisit(t *testing.T) { }, ), ), - envoy.RouteConfiguration("https/www.example.com", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("https/www.example.com", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -2143,8 +2143,8 @@ func TestRouteVisit(t *testing.T) { }, }, )), - envoy.RouteConfiguration(ENVOY_FALLBACK_ROUTECONFIG, - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration(ENVOY_FALLBACK_ROUTECONFIG, + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -2268,8 +2268,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Redirect{ @@ -2281,7 +2281,7 @@ func TestRouteVisit(t *testing.T) { }, }, ), - envoy.VirtualHost("www.example.com", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Redirect{ @@ -2294,8 +2294,8 @@ func TestRouteVisit(t *testing.T) { }, ), ), - envoy.RouteConfiguration("https/projectcontour.io", - envoy.VirtualHost("projectcontour.io", + v2.RouteConfiguration("https/projectcontour.io", + v2.VirtualHost("projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -2313,8 +2313,8 @@ func TestRouteVisit(t *testing.T) { }, }, )), - envoy.RouteConfiguration("https/www.example.com", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("https/www.example.com", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -2332,8 +2332,8 @@ func TestRouteVisit(t *testing.T) { }, }, )), - envoy.RouteConfiguration(ENVOY_FALLBACK_ROUTECONFIG, - envoy.VirtualHost("projectcontour.io", + v2.RouteConfiguration(ENVOY_FALLBACK_ROUTECONFIG, + v2.VirtualHost("projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -2457,8 +2457,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Redirect{ @@ -2470,7 +2470,7 @@ func TestRouteVisit(t *testing.T) { }, }, ), - envoy.VirtualHost("www.example.com", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Redirect{ @@ -2483,8 +2483,8 @@ func TestRouteVisit(t *testing.T) { }, ), ), - envoy.RouteConfiguration("https/projectcontour.io", - envoy.VirtualHost("projectcontour.io", + v2.RouteConfiguration("https/projectcontour.io", + v2.VirtualHost("projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -2502,8 +2502,8 @@ func TestRouteVisit(t *testing.T) { }, }, )), - envoy.RouteConfiguration("https/www.example.com", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("https/www.example.com", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -2521,8 +2521,8 @@ func TestRouteVisit(t *testing.T) { }, }, )), - envoy.RouteConfiguration(ENVOY_FALLBACK_ROUTECONFIG, - envoy.VirtualHost("projectcontour.io", + v2.RouteConfiguration(ENVOY_FALLBACK_ROUTECONFIG, + v2.VirtualHost("projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -2539,7 +2539,7 @@ func TestRouteVisit(t *testing.T) { }, }, }, - ), envoy.VirtualHost("www.example.com", + ), v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -2635,7 +2635,7 @@ func TestRouteVisit(t *testing.T) { }, }, }, - want: routeConfigurations(envoy.RouteConfiguration("ingress_http")), + want: routeConfigurations(v2.RouteConfiguration("ingress_http")), }, "httpproxy with fallback certificate - no fqdn enabled": { fallbackCertificate: &types.NamespacedName{ @@ -2714,8 +2714,8 @@ func TestRouteVisit(t *testing.T) { }, }, want: routeConfigurations( - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Redirect{ @@ -2728,8 +2728,8 @@ func TestRouteVisit(t *testing.T) { }, ), ), - envoy.RouteConfiguration("https/www.example.com", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("https/www.example.com", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Route{ @@ -2972,7 +2972,7 @@ func routeretry(cluster string, retryOn string, numRetries uint32, perTryTimeout } func routeRegex(regex string, headers ...dag.HeaderMatchCondition) *envoy_api_v2_route.RouteMatch { - return envoy.RouteMatch(&dag.Route{ + return v2.RouteMatch(&dag.Route{ PathMatchCondition: &dag.RegexMatchCondition{ Regex: regex, }, @@ -2981,7 +2981,7 @@ func routeRegex(regex string, headers ...dag.HeaderMatchCondition) *envoy_api_v2 } func routePrefix(prefix string, headers ...dag.HeaderMatchCondition) *envoy_api_v2_route.RouteMatch { - return envoy.RouteMatch(&dag.Route{ + return v2.RouteMatch(&dag.Route{ PathMatchCondition: &dag.PrefixMatchCondition{ Prefix: prefix, }, @@ -3000,8 +3000,8 @@ func weightedCluster(name string, weight uint32) *envoy_api_v2_route.WeightedClu } } -func routeConfigurations(rcs ...*v2.RouteConfiguration) map[string]*v2.RouteConfiguration { - m := make(map[string]*v2.RouteConfiguration) +func routeConfigurations(rcs ...*envoy_api_v2.RouteConfiguration) map[string]*envoy_api_v2.RouteConfiguration { + m := make(map[string]*envoy_api_v2.RouteConfiguration) for _, rc := range rcs { m[rc.Name] = rc } diff --git a/internal/contour/secret.go b/internal/contour/secret.go index 8d12a6b6711..305354e4890 100644 --- a/internal/contour/secret.go +++ b/internal/contour/secret.go @@ -22,6 +22,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/projectcontour/contour/internal/dag" "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/protobuf" "github.com/projectcontour/contour/internal/sorter" ) @@ -93,7 +94,7 @@ func visitSecrets(root dag.Vertex) map[string]*envoy_api_v2_auth.Secret { func (v *secretVisitor) addSecret(s *dag.Secret) { name := envoy.Secretname(s) if _, ok := v.secrets[name]; !ok { - envoySecret := envoy.Secret(s) + envoySecret := v2.Secret(s) v.secrets[envoySecret.Name] = envoySecret } } diff --git a/internal/contour/visitor_test.go b/internal/contour/visitor_test.go index 71afddee751..d141c76d431 100644 --- a/internal/contour/visitor_test.go +++ b/internal/contour/visitor_test.go @@ -21,7 +21,7 @@ import ( envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" envoy_api_v2_listener "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/protobuf" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -65,9 +65,9 @@ func TestVisitClusters(t *testing.T) { &envoy_api_v2.Cluster{ Name: "default/example/443/da39a3ee5e", AltStatName: "default_example_443", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/example", }, }, @@ -130,18 +130,18 @@ func TestVisitListeners(t *testing.T) { want: listenermap( &envoy_api_v2.Listener{ Name: ENVOY_HTTPS_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"tcpproxy.example.com"}, }, TransportSocket: transportSocket("secret", envoy_api_v2_auth.TlsParameters_TLSv1_1), - Filters: envoy.Filters(envoy.TCPProxy(ENVOY_HTTPS_LISTENER, p1, envoy.FileAccessLogEnvoy(DEFAULT_HTTPS_ACCESS_LOG))), + Filters: v2.Filters(v2.TCPProxy(ENVOY_HTTPS_LISTENER, p1, v2.FileAccessLogEnvoy(DEFAULT_HTTPS_ACCESS_LOG))), }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, ), }, diff --git a/internal/envoy/accesslog.go b/internal/envoy/accesslog.go index aff1616d757..06e36643267 100644 --- a/internal/envoy/accesslog.go +++ b/internal/envoy/accesslog.go @@ -13,14 +13,6 @@ package envoy -import ( - accesslogv2 "github.com/envoyproxy/go-control-plane/envoy/config/accesslog/v2" - accesslog "github.com/envoyproxy/go-control-plane/envoy/config/filter/accesslog/v2" - "github.com/envoyproxy/go-control-plane/pkg/wellknown" - _struct "github.com/golang/protobuf/ptypes/struct" - "github.com/projectcontour/contour/internal/protobuf" -) - //JSONFields is the canonical translation table for JSON fields to Envoy log template formats, //used for specifying fields for Envoy to log when JSON logging is enabled. //Only fields specified in this map may be used for JSON logging. @@ -74,55 +66,3 @@ var DefaultFields = []string{ "user_agent", "x_forwarded_for", } - -// FileAccessLogEnvoy returns a new file based access log filter -// that will output Envoy's default access logs. -func FileAccessLogEnvoy(path string) []*accesslog.AccessLog { - return []*accesslog.AccessLog{{ - Name: wellknown.FileAccessLog, - ConfigType: &accesslog.AccessLog_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&accesslogv2.FileAccessLog{ - Path: path, - // AccessLogFormat left blank to defer to Envoy's default log format. - }), - }, - }} -} - -// FileAccessLogJSON returns a new file based access log filter -// that will log in JSON format -func FileAccessLogJSON(path string, keys []string) []*accesslog.AccessLog { - - jsonformat := &_struct.Struct{ - Fields: make(map[string]*_struct.Value), - } - - for _, k := range keys { - // This will silently ignore invalid headers. - // TODO(youngnick): this should tell users if a header is not valid - // https://github.com/projectcontour/contour/issues/1507 - if template, ok := JSONFields[k]; ok { - jsonformat.Fields[k] = sv(template) - } - } - - return []*accesslog.AccessLog{{ - Name: wellknown.FileAccessLog, - ConfigType: &accesslog.AccessLog_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&accesslogv2.FileAccessLog{ - Path: path, - AccessLogFormat: &accesslogv2.FileAccessLog_JsonFormat{ - JsonFormat: jsonformat, - }, - }), - }, - }} -} - -func sv(s string) *_struct.Value { - return &_struct.Value{ - Kind: &_struct.Value_StringValue{ - StringValue: s, - }, - } -} diff --git a/internal/envoy/auth.go b/internal/envoy/auth.go index 50097bc231a..e36ba51e163 100644 --- a/internal/envoy/auth.go +++ b/internal/envoy/auth.go @@ -13,16 +13,8 @@ package envoy -import ( - envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" - envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" - matcher "github.com/envoyproxy/go-control-plane/envoy/type/matcher" - "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/protobuf" -) - var ( - // This is the list of default ciphers used by contour 1.9.1. A handful are + // Ciphers contains the list of default ciphers used by Contour. A handful are // commented out, as they're arguably less secure. They're also unnecessary // - most of the clients that might need to use the commented ciphers are // unable to connect without TLS 1.0, which contour never enables. @@ -31,7 +23,7 @@ var ( // // The commented ciphers are left in place to simplify updating this list for future // versions of envoy. - ciphers = []string{ + Ciphers = []string{ "[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]", "[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]", "ECDHE-ECDSA-AES128-SHA", @@ -46,81 +38,3 @@ var ( //"AES256-SHA", } ) - -// UpstreamTLSContext creates an envoy_api_v2_auth.UpstreamTlsContext. By default -// UpstreamTLSContext returns a HTTP/1.1 TLS enabled context. A list of -// additional ALPN protocols can be provided. -func UpstreamTLSContext(peerValidationContext *dag.PeerValidationContext, sni string, alpnProtocols ...string) *envoy_api_v2_auth.UpstreamTlsContext { - context := &envoy_api_v2_auth.UpstreamTlsContext{ - CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ - AlpnProtocols: alpnProtocols, - }, - Sni: sni, - } - - if peerValidationContext.GetCACertificate() != nil && len(peerValidationContext.GetSubjectName()) > 0 { - // We have to explicitly assign the value from validationContext - // to context.CommonTlsContext.ValidationContextType because the - // latter is an interface. Returning nil from validationContext - // directly into this field boxes the nil into the unexported - // type of this grpc OneOf field which causes proto marshaling - // to explode later on. - vc := validationContext(peerValidationContext.GetCACertificate(), peerValidationContext.GetSubjectName()) - if vc != nil { - context.CommonTlsContext.ValidationContextType = vc - } - } - - return context -} - -func validationContext(ca []byte, subjectName string) *envoy_api_v2_auth.CommonTlsContext_ValidationContext { - vc := &envoy_api_v2_auth.CommonTlsContext_ValidationContext{ - ValidationContext: &envoy_api_v2_auth.CertificateValidationContext{ - TrustedCa: &envoy_api_v2_core.DataSource{ - // TODO(dfc) update this for SDS - Specifier: &envoy_api_v2_core.DataSource_InlineBytes{ - InlineBytes: ca, - }, - }, - }, - } - - if len(subjectName) > 0 { - vc.ValidationContext.MatchSubjectAltNames = []*matcher.StringMatcher{{ - MatchPattern: &matcher.StringMatcher_Exact{ - Exact: subjectName, - }}, - } - } - - return vc -} - -// DownstreamTLSContext creates a new DownstreamTlsContext. -func DownstreamTLSContext(serverSecret *dag.Secret, tlsMinProtoVersion envoy_api_v2_auth.TlsParameters_TlsProtocol, peerValidationContext *dag.PeerValidationContext, alpnProtos ...string) *envoy_api_v2_auth.DownstreamTlsContext { - context := &envoy_api_v2_auth.DownstreamTlsContext{ - CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ - TlsParams: &envoy_api_v2_auth.TlsParameters{ - TlsMinimumProtocolVersion: tlsMinProtoVersion, - TlsMaximumProtocolVersion: envoy_api_v2_auth.TlsParameters_TLSv1_3, - CipherSuites: ciphers, - }, - TlsCertificateSdsSecretConfigs: []*envoy_api_v2_auth.SdsSecretConfig{{ - Name: Secretname(serverSecret), - SdsConfig: ConfigSource("contour"), - }}, - AlpnProtocols: alpnProtos, - }, - } - - if peerValidationContext.GetCACertificate() != nil { - vc := validationContext(peerValidationContext.GetCACertificate(), "") - if vc != nil { - context.CommonTlsContext.ValidationContextType = vc - context.RequireClientCertificate = protobuf.Bool(true) - } - } - - return context -} diff --git a/internal/envoy/bootstrap.go b/internal/envoy/bootstrap.go index 8eb336efa33..d83df173864 100644 --- a/internal/envoy/bootstrap.go +++ b/internal/envoy/bootstrap.go @@ -10,323 +10,29 @@ // 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 envoy contains APIs for translating between Contour // objects and Envoy configuration APIs and types. + package envoy import ( - "fmt" "os" - "path" - "strconv" - "strings" - "time" - api "github.com/envoyproxy/go-control-plane/envoy/api/v2" - envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" - clusterv2 "github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster" - envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" - envoy_api_bootstrap "github.com/envoyproxy/go-control-plane/envoy/config/bootstrap/v2" - matcher "github.com/envoyproxy/go-control-plane/envoy/type/matcher" "github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/proto" - "github.com/golang/protobuf/ptypes/any" - "github.com/projectcontour/contour/internal/protobuf" ) -// sdsResourcesSubdirectory stores the subdirectory name where SDS path resources are stored to. -const sdsResourcesSubdirectory = "sds" +// SdsResourcesSubdirectory stores the subdirectory name where SDS path resources are stored to. +const SdsResourcesSubdirectory = "sds" -// sdsTLSCertificateFile stores the path to the SDS resource with Envoy's +// SdsTLSCertificateFile stores the path to the SDS resource with Envoy's // client certificate and key for XDS gRPC connection. -const sdsTLSCertificateFile = "xds-tls-certicate.json" +const SdsTLSCertificateFile = "xds-tls-certicate.json" // sdsValidationContextFile stores the path to the SDS resource with // CA certificates for Envoy to use for the XDS gRPC connection. -const sdsValidationContextFile = "xds-validation-context.json" - -// WriteBootstrap writes bootstrap configuration to files. -func WriteBootstrap(c *BootstrapConfig) error { - // Create Envoy bootstrap config and associated resource files. - steps, err := bootstrap(c) - if err != nil { - return err - } - - if c.ResourcesDir != "" { - if err := os.MkdirAll(path.Join(c.ResourcesDir, "sds"), 0750); err != nil { - return err - } - } - - // Write all configuration files out to filesystem. - for _, step := range steps { - if err := writeConfig(step(c)); err != nil { - return err - } - } - - return nil -} - -type bootstrapf func(*BootstrapConfig) (string, proto.Message) - -// bootstrap creates a new v2 bootstrap configuration and associated resource files. -func bootstrap(c *BootstrapConfig) ([]bootstrapf, error) { - steps := []bootstrapf{} - - if c.GrpcClientCert == "" && c.GrpcClientKey == "" && c.GrpcCABundle == "" { - steps = append(steps, - func(*BootstrapConfig) (string, proto.Message) { - return c.Path, bootstrapConfig(c) - }) - - return steps, nil - } - - for _, f := range []string{c.GrpcClientCert, c.GrpcClientKey, c.GrpcCABundle} { - // If any of of the TLS options is not empty, they all must be not empty. - if f == "" { - return nil, fmt.Errorf( - "you must supply all TLS parameters - %q, %q, %q, or none of them", - "--envoy-cafile", "--envoy-cert-file", "--envoy-key-file") - } - - if !c.SkipFilePathCheck { - // If the TLS secrets aren't set up properly, - // some files may not be present. In this case, - // envoy will reject the bootstrap configuration, - // but there is no way to detect and fix that. If - // we check and fail here, that is visible in the - // Pod lifecycle and therefore fixable. - fi, err := os.Stat(f) - if err != nil { - return nil, err - } - if fi.Size() == 0 { - return nil, fmt.Errorf("%q is empty", f) - } - } - } - - if c.ResourcesDir == "" { - // For backwards compatibility, the old behavior - // is to use direct certificate and key file paths in - // bootstrap config. Envoy does not support rotation - // of xDS certificate files in this case. - - steps = append(steps, - func(*BootstrapConfig) (string, proto.Message) { - b := bootstrapConfig(c) - b.StaticResources.Clusters[0].TransportSocket = UpstreamTLSTransportSocket( - upstreamFileTLSContext(c)) - return c.Path, b - }) - - return steps, nil - } - - // xDS certificate rotation is supported by Envoy by using SDS path based resource files. - // These files are JSON representation of the SDS protobuf messages that normally get sent over the xDS connection, - // but for xDS connection itself, bootstrapping is done by storing the SDS resources in a local filesystem. - // Envoy will monitor and reload the resource files and the certificate and key files referred from the SDS resources. - // - // Two files are written to ResourcesDir: - // - SDS resource for xDS client certificate and key for authenticating Envoy towards Contour. - // - SDS resource for trusted CA certificate for validating Contour server certificate. - sdsTLSCertificatePath := path.Join(c.ResourcesDir, sdsResourcesSubdirectory, sdsTLSCertificateFile) - sdsValidationContextPath := path.Join(c.ResourcesDir, sdsResourcesSubdirectory, sdsValidationContextFile) - - steps = append(steps, - func(*BootstrapConfig) (string, proto.Message) { - return sdsTLSCertificatePath, tlsCertificateSdsSecretConfig(c) - }, - func(*BootstrapConfig) (string, proto.Message) { - return sdsValidationContextPath, validationContextSdsSecretConfig(c) - }, - func(*BootstrapConfig) (string, proto.Message) { - b := bootstrapConfig(c) - b.StaticResources.Clusters[0].TransportSocket = UpstreamTLSTransportSocket( - upstreamSdsTLSContext(sdsTLSCertificatePath, sdsValidationContextPath)) - return c.Path, b - }, - ) - - return steps, nil -} - -func bootstrapConfig(c *BootstrapConfig) *envoy_api_bootstrap.Bootstrap { - return &envoy_api_bootstrap.Bootstrap{ - DynamicResources: &envoy_api_bootstrap.Bootstrap_DynamicResources{ - LdsConfig: ConfigSource("contour"), - CdsConfig: ConfigSource("contour"), - }, - StaticResources: &envoy_api_bootstrap.Bootstrap_StaticResources{ - Clusters: []*api.Cluster{{ - Name: "contour", - AltStatName: strings.Join([]string{c.Namespace, "contour", strconv.Itoa(c.xdsGRPCPort())}, "_"), - ConnectTimeout: protobuf.Duration(5 * time.Second), - ClusterDiscoveryType: ClusterDiscoveryType(api.Cluster_STRICT_DNS), - LbPolicy: api.Cluster_ROUND_ROBIN, - LoadAssignment: &api.ClusterLoadAssignment{ - ClusterName: "contour", - Endpoints: Endpoints( - SocketAddress(c.xdsAddress(), c.xdsGRPCPort()), - ), - }, - UpstreamConnectionOptions: &api.UpstreamConnectionOptions{ - TcpKeepalive: &envoy_api_v2_core.TcpKeepalive{ - KeepaliveProbes: protobuf.UInt32(3), - KeepaliveTime: protobuf.UInt32(30), - KeepaliveInterval: protobuf.UInt32(5), - }, - }, - Http2ProtocolOptions: new(envoy_api_v2_core.Http2ProtocolOptions), // enables http2 - CircuitBreakers: &clusterv2.CircuitBreakers{ - Thresholds: []*clusterv2.CircuitBreakers_Thresholds{{ - Priority: envoy_api_v2_core.RoutingPriority_HIGH, - MaxConnections: protobuf.UInt32(100000), - MaxPendingRequests: protobuf.UInt32(100000), - MaxRequests: protobuf.UInt32(60000000), - MaxRetries: protobuf.UInt32(50), - }, { - Priority: envoy_api_v2_core.RoutingPriority_DEFAULT, - MaxConnections: protobuf.UInt32(100000), - MaxPendingRequests: protobuf.UInt32(100000), - MaxRequests: protobuf.UInt32(60000000), - MaxRetries: protobuf.UInt32(50), - }}, - }, - }, { - Name: "service-stats", - AltStatName: strings.Join([]string{c.Namespace, "service-stats", strconv.Itoa(c.adminPort())}, "_"), - ConnectTimeout: protobuf.Duration(250 * time.Millisecond), - ClusterDiscoveryType: ClusterDiscoveryType(api.Cluster_LOGICAL_DNS), - LbPolicy: api.Cluster_ROUND_ROBIN, - LoadAssignment: &api.ClusterLoadAssignment{ - ClusterName: "service-stats", - Endpoints: Endpoints( - SocketAddress(c.adminAddress(), c.adminPort()), - ), - }, - }}, - }, - Admin: &envoy_api_bootstrap.Admin{ - AccessLogPath: c.adminAccessLogPath(), - Address: SocketAddress(c.adminAddress(), c.adminPort()), - }, - } -} - -func upstreamFileTLSContext(c *BootstrapConfig) *envoy_api_v2_auth.UpstreamTlsContext { - context := &envoy_api_v2_auth.UpstreamTlsContext{ - CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ - TlsCertificates: []*envoy_api_v2_auth.TlsCertificate{{ - CertificateChain: &envoy_api_v2_core.DataSource{ - Specifier: &envoy_api_v2_core.DataSource_Filename{ - Filename: c.GrpcClientCert, - }, - }, - PrivateKey: &envoy_api_v2_core.DataSource{ - Specifier: &envoy_api_v2_core.DataSource_Filename{ - Filename: c.GrpcClientKey, - }, - }, - }}, - ValidationContextType: &envoy_api_v2_auth.CommonTlsContext_ValidationContext{ - ValidationContext: &envoy_api_v2_auth.CertificateValidationContext{ - TrustedCa: &envoy_api_v2_core.DataSource{ - Specifier: &envoy_api_v2_core.DataSource_Filename{ - Filename: c.GrpcCABundle, - }, - }, - // TODO(youngnick): Does there need to be a flag wired down to here? - MatchSubjectAltNames: []*matcher.StringMatcher{{ - MatchPattern: &matcher.StringMatcher_Exact{ - Exact: "contour", - }}, - }, - }, - }, - }, - } - return context -} - -func upstreamSdsTLSContext(certificateSdsFile, validationSdsFile string) *envoy_api_v2_auth.UpstreamTlsContext { - context := &envoy_api_v2_auth.UpstreamTlsContext{ - CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ - TlsCertificateSdsSecretConfigs: []*envoy_api_v2_auth.SdsSecretConfig{{ - SdsConfig: &envoy_api_v2_core.ConfigSource{ - ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_Path{ - Path: certificateSdsFile, - }, - }, - }}, - ValidationContextType: &envoy_api_v2_auth.CommonTlsContext_ValidationContextSdsSecretConfig{ - ValidationContextSdsSecretConfig: &envoy_api_v2_auth.SdsSecretConfig{ - SdsConfig: &envoy_api_v2_core.ConfigSource{ - ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_Path{ - Path: validationSdsFile, - }, - }, - }, - }, - }, - } - return context -} - -// tlsCertificateSdsSecretConfig creates DiscoveryResponse with file based SDS resource -// including paths to TLS certificates and key -func tlsCertificateSdsSecretConfig(c *BootstrapConfig) *api.DiscoveryResponse { - secret := &envoy_api_v2_auth.Secret{ - Type: &envoy_api_v2_auth.Secret_TlsCertificate{ - TlsCertificate: &envoy_api_v2_auth.TlsCertificate{ - CertificateChain: &envoy_api_v2_core.DataSource{ - Specifier: &envoy_api_v2_core.DataSource_Filename{ - Filename: c.GrpcClientCert, - }, - }, - PrivateKey: &envoy_api_v2_core.DataSource{ - Specifier: &envoy_api_v2_core.DataSource_Filename{ - Filename: c.GrpcClientKey, - }, - }, - }, - }, - } - - return &api.DiscoveryResponse{ - Resources: []*any.Any{protobuf.MustMarshalAny(secret)}, - } -} - -// validationContextSdsSecretConfig creates DiscoveryResponse with file based SDS resource -// including path to CA certificate bundle -func validationContextSdsSecretConfig(c *BootstrapConfig) *api.DiscoveryResponse { - secret := &envoy_api_v2_auth.Secret{ - Type: &envoy_api_v2_auth.Secret_ValidationContext{ - ValidationContext: &envoy_api_v2_auth.CertificateValidationContext{ - TrustedCa: &envoy_api_v2_core.DataSource{ - Specifier: &envoy_api_v2_core.DataSource_Filename{ - Filename: c.GrpcCABundle, - }, - }, - MatchSubjectAltNames: []*matcher.StringMatcher{{ - MatchPattern: &matcher.StringMatcher_Exact{ - Exact: "contour", - }}, - }, - }, - }, - } - - return &api.DiscoveryResponse{ - Resources: []*any.Any{protobuf.MustMarshalAny(secret)}, - } -} +const SdsValidationContextFile = "xds-validation-context.json" // BootstrapConfig holds configuration values for a v2.Bootstrap. type BootstrapConfig struct { @@ -376,11 +82,13 @@ type BootstrapConfig struct { SkipFilePathCheck bool } -func (c *BootstrapConfig) xdsAddress() string { return stringOrDefault(c.XDSAddress, "127.0.0.1") } -func (c *BootstrapConfig) xdsGRPCPort() int { return intOrDefault(c.XDSGRPCPort, 8001) } -func (c *BootstrapConfig) adminAddress() string { return stringOrDefault(c.AdminAddress, "127.0.0.1") } -func (c *BootstrapConfig) adminPort() int { return intOrDefault(c.AdminPort, 9001) } -func (c *BootstrapConfig) adminAccessLogPath() string { +func (c *BootstrapConfig) GetXdsAddress() string { return stringOrDefault(c.XDSAddress, "127.0.0.1") } +func (c *BootstrapConfig) GetXdsGRPCPort() int { return intOrDefault(c.XDSGRPCPort, 8001) } +func (c *BootstrapConfig) GetAdminAddress() string { + return stringOrDefault(c.AdminAddress, "127.0.0.1") +} +func (c *BootstrapConfig) GetAdminPort() int { return intOrDefault(c.AdminPort, 9001) } +func (c *BootstrapConfig) GetAdminAccessLogPath() string { return stringOrDefault(c.AdminAccessLogPath, "/dev/null") } @@ -398,7 +106,7 @@ func intOrDefault(i, def int) int { return i } -func writeConfig(filename string, config proto.Message) (err error) { +func WriteConfig(filename string, config proto.Message) (err error) { var out *os.File if filename == "-" { diff --git a/internal/envoy/cluster.go b/internal/envoy/cluster.go index e568d577dac..2a0d998f8e1 100644 --- a/internal/envoy/cluster.go +++ b/internal/envoy/cluster.go @@ -19,182 +19,10 @@ import ( "fmt" "strconv" "strings" - "time" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" - envoy_cluster "github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster" - envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" - envoy_type "github.com/envoyproxy/go-control-plane/envoy/type" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/protobuf" - "github.com/projectcontour/contour/internal/xds" - "k8s.io/apimachinery/pkg/types" ) -func clusterDefaults() *v2.Cluster { - return &v2.Cluster{ - ConnectTimeout: protobuf.Duration(250 * time.Millisecond), - CommonLbConfig: ClusterCommonLBConfig(), - LbPolicy: lbPolicy(""), - } -} - -// Cluster creates new v2.Cluster from dag.Cluster. -func Cluster(c *dag.Cluster) *v2.Cluster { - service := c.Upstream - cluster := clusterDefaults() - - cluster.Name = Clustername(c) - cluster.AltStatName = altStatName(service) - cluster.LbPolicy = lbPolicy(c.LoadBalancerPolicy) - cluster.HealthChecks = edshealthcheck(c) - - switch len(service.ExternalName) { - case 0: - // external name not set, cluster will be discovered via EDS - cluster.ClusterDiscoveryType = ClusterDiscoveryType(v2.Cluster_EDS) - cluster.EdsClusterConfig = edsconfig("contour", service) - default: - // external name set, use hard coded DNS name - cluster.ClusterDiscoveryType = ClusterDiscoveryType(v2.Cluster_STRICT_DNS) - cluster.LoadAssignment = StaticClusterLoadAssignment(service) - } - - // Drain connections immediately if using healthchecks and the endpoint is known to be removed - if c.HTTPHealthCheckPolicy != nil || c.TCPHealthCheckPolicy != nil { - cluster.DrainConnectionsOnHostRemoval = true - } - - if anyPositive(service.MaxConnections, service.MaxPendingRequests, service.MaxRequests, service.MaxRetries) { - cluster.CircuitBreakers = &envoy_cluster.CircuitBreakers{ - Thresholds: []*envoy_cluster.CircuitBreakers_Thresholds{{ - MaxConnections: protobuf.UInt32OrNil(service.MaxConnections), - MaxPendingRequests: protobuf.UInt32OrNil(service.MaxPendingRequests), - MaxRequests: protobuf.UInt32OrNil(service.MaxRequests), - MaxRetries: protobuf.UInt32OrNil(service.MaxRetries), - }}, - } - } - - switch c.Protocol { - case "tls": - cluster.TransportSocket = UpstreamTLSTransportSocket( - UpstreamTLSContext( - c.UpstreamValidation, - c.SNI, - ), - ) - case "h2": - cluster.Http2ProtocolOptions = &envoy_api_v2_core.Http2ProtocolOptions{} - cluster.TransportSocket = UpstreamTLSTransportSocket( - UpstreamTLSContext( - c.UpstreamValidation, - c.SNI, - "h2", - ), - ) - case "h2c": - cluster.Http2ProtocolOptions = &envoy_api_v2_core.Http2ProtocolOptions{} - } - - return cluster -} - -// ExtensionCluster builds a v2.Cluster struct for the given extension service. -func ExtensionCluster(ext *dag.ExtensionCluster) *v2.Cluster { - cluster := clusterDefaults() - - // The Envoy cluster name has already been set. - cluster.Name = ext.Name - - // The AltStatName was added to make a more readable alternative - // to the cluster name for metrics (see #827). For extension - // services, we can have multiple ports, so it doesn't make - // sense to build this the same way we build it for HTTPProxy - // service clusters. However, we know the namespaced name for - // the ExtensionCluster is globally unique, so we can use that - // to produce a stable, readable name. - cluster.AltStatName = strings.ReplaceAll(cluster.Name, "/", "_") - - cluster.LbPolicy = lbPolicy(ext.LoadBalancerPolicy) - - // Cluster will be discovered via EDS. - cluster.ClusterDiscoveryType = ClusterDiscoveryType(v2.Cluster_EDS) - cluster.EdsClusterConfig = &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource("contour"), - ServiceName: ext.Upstream.ClusterName, - } - - // TODO(jpeach): Externalname service support in https://github.com/projectcontour/contour/issues/2875 - - switch ext.Protocol { - case "h2": - cluster.Http2ProtocolOptions = &envoy_api_v2_core.Http2ProtocolOptions{} - cluster.TransportSocket = UpstreamTLSTransportSocket( - UpstreamTLSContext( - ext.UpstreamValidation, - ext.SNI, - "h2", - ), - ) - case "h2c": - cluster.Http2ProtocolOptions = &envoy_api_v2_core.Http2ProtocolOptions{} - } - - return cluster -} - -// StaticClusterLoadAssignment creates a *v2.ClusterLoadAssignment pointing to the external DNS address of the service -func StaticClusterLoadAssignment(service *dag.Service) *v2.ClusterLoadAssignment { - addr := SocketAddress(service.ExternalName, int(service.Weighted.ServicePort.Port)) - return &v2.ClusterLoadAssignment{ - Endpoints: Endpoints(addr), - ClusterName: xds.ClusterLoadAssignmentName( - types.NamespacedName{Name: service.Weighted.ServiceName, Namespace: service.Weighted.ServiceNamespace}, - service.Weighted.ServicePort.Name, - ), - } -} - -func edsconfig(cluster string, service *dag.Service) *v2.Cluster_EdsClusterConfig { - return &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource(cluster), - ServiceName: xds.ClusterLoadAssignmentName( - types.NamespacedName{Name: service.Weighted.ServiceName, Namespace: service.Weighted.ServiceNamespace}, - service.Weighted.ServicePort.Name, - ), - } -} - -func lbPolicy(strategy string) v2.Cluster_LbPolicy { - switch strategy { - case "WeightedLeastRequest": - return v2.Cluster_LEAST_REQUEST - case "Random": - return v2.Cluster_RANDOM - case "Cookie": - return v2.Cluster_RING_HASH - default: - return v2.Cluster_ROUND_ROBIN - } -} - -func edshealthcheck(c *dag.Cluster) []*envoy_api_v2_core.HealthCheck { - if c.HTTPHealthCheckPolicy == nil && c.TCPHealthCheckPolicy == nil { - return nil - } - - if c.HTTPHealthCheckPolicy != nil { - return []*envoy_api_v2_core.HealthCheck{ - httpHealthCheck(c), - } - } - - return []*envoy_api_v2_core.HealthCheck{ - tcpHealthCheck(c), - } -} - // Clustername returns the name of the CDS cluster for this service. func Clustername(cluster *dag.Cluster) string { service := cluster.Upstream @@ -224,23 +52,23 @@ func Clustername(cluster *dag.Cluster) string { ns := service.Weighted.ServiceNamespace name := service.Weighted.ServiceName - return hashname(60, ns, name, strconv.Itoa(int(service.Weighted.ServicePort.Port)), fmt.Sprintf("%x", hash[:5])) + return Hashname(60, ns, name, strconv.Itoa(int(service.Weighted.ServicePort.Port)), fmt.Sprintf("%x", hash[:5])) } -// altStatName generates an alternative stat name for the service +// AltStatName generates an alternative stat name for the service // using format ns_name_port -func altStatName(service *dag.Service) string { +func AltStatName(service *dag.Service) string { parts := []string{service.Weighted.ServiceNamespace, service.Weighted.ServiceName, strconv.Itoa(int(service.Weighted.ServicePort.Port))} return strings.Join(parts, "_") } -// hashname takes a lenth l and a varargs of strings s and returns a string whose length +// Hashname takes a length l and a varargs of strings s and returns a string whose length // which does not exceed l. Internally s is joined with strings.Join(s, "/"). If the // combined length exceeds l then hashname truncates each element in s, starting from the // end using a hash derived from the contents of s (not the current element). This process // continues until the length of s does not exceed l, or all elements have been truncated. // In which case, the entire string is replaced with a hash not exceeding the length of l. -func hashname(l int, s ...string) string { +func Hashname(l int, s ...string) string { const shorthash = 6 // the length of the shorthash r := strings.Join(s, "/") @@ -282,8 +110,8 @@ func min(a, b int) int { return a } -// anyPositive indicates if any of the values provided are greater than zero. -func anyPositive(first uint32, rest ...uint32) bool { +// AnyPositive indicates if any of the values provided are greater than zero. +func AnyPositive(first uint32, rest ...uint32) bool { if first > 0 { return true } @@ -294,35 +122,3 @@ func anyPositive(first uint32, rest ...uint32) bool { } return false } - -// ClusterCommonLBConfig creates a *v2.Cluster_CommonLbConfig with HealthyPanicThreshold disabled. -func ClusterCommonLBConfig() *v2.Cluster_CommonLbConfig { - return &v2.Cluster_CommonLbConfig{ - HealthyPanicThreshold: &envoy_type.Percent{ // Disable HealthyPanicThreshold - Value: 0, - }, - } -} - -// ConfigSource returns a *envoy_api_v2_core.ConfigSource for cluster. -func ConfigSource(cluster string) *envoy_api_v2_core.ConfigSource { - return &envoy_api_v2_core.ConfigSource{ - ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ - ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ - ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, - GrpcServices: []*envoy_api_v2_core.GrpcService{{ - TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ - ClusterName: cluster, - }, - }, - }}, - }, - }, - } -} - -// ClusterDiscoveryType returns the type of a ClusterDiscovery as a Cluster_type. -func ClusterDiscoveryType(t v2.Cluster_DiscoveryType) *v2.Cluster_Type { - return &v2.Cluster_Type{Type: t} -} diff --git a/internal/envoy/cluster_test.go b/internal/envoy/cluster_test.go index 632b2249464..a2a98aa3b6a 100644 --- a/internal/envoy/cluster_test.go +++ b/internal/envoy/cluster_test.go @@ -1,584 +1,11 @@ -// 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 envoy import ( "testing" - "time" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" - envoy_cluster "github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster" - envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" - envoy_type "github.com/envoyproxy/go-control-plane/envoy/type" - "github.com/golang/protobuf/proto" - "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/protobuf" - "github.com/projectcontour/contour/internal/xds" "github.com/stretchr/testify/assert" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/intstr" ) -func TestCluster(t *testing.T) { - s1 := &v1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: "kuard", - Namespace: "default", - }, - Spec: v1.ServiceSpec{ - Ports: []v1.ServicePort{{ - Name: "http", - Protocol: "TCP", - Port: 443, - TargetPort: intstr.FromInt(8080), - }}, - }, - } - - s2 := &v1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: "kuard", - Namespace: "default", - }, - Spec: v1.ServiceSpec{ - ExternalName: "foo.io", - Ports: []v1.ServicePort{{ - Name: "http", - Protocol: "TCP", - Port: 443, - TargetPort: intstr.FromInt(8080), - }}, - }, - } - - svcExternal := &v1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: "kuard", - Namespace: "default", - }, - Spec: v1.ServiceSpec{ - ExternalName: "projectcontour.local", - Ports: []v1.ServicePort{{ - Name: "http", - Protocol: "TCP", - Port: 443, - TargetPort: intstr.FromInt(8080), - }}, - Type: v1.ServiceTypeExternalName, - }, - } - - secret := &dag.Secret{ - Object: &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "secret", - Namespace: "default", - }, - Type: v1.SecretTypeTLS, - Data: map[string][]byte{dag.CACertificateKey: []byte("cacert")}, - }, - } - - tests := map[string]struct { - cluster *dag.Cluster - want *v2.Cluster - }{ - "simple service": { - cluster: &dag.Cluster{ - Upstream: service(s1), - }, - want: &v2.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource("contour"), - ServiceName: "default/kuard/http", - }, - }, - }, - "h2c upstream": { - cluster: &dag.Cluster{ - Upstream: service(s1, "h2c"), - Protocol: "h2c", - }, - want: &v2.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource("contour"), - ServiceName: "default/kuard/http", - }, - Http2ProtocolOptions: &envoy_api_v2_core.Http2ProtocolOptions{}, - }, - }, - "h2 upstream": { - cluster: &dag.Cluster{ - Upstream: service(s1, "h2"), - Protocol: "h2", - }, - want: &v2.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource("contour"), - ServiceName: "default/kuard/http", - }, - TransportSocket: UpstreamTLSTransportSocket( - UpstreamTLSContext(nil, "", "h2"), - ), - Http2ProtocolOptions: &envoy_api_v2_core.Http2ProtocolOptions{}, - }, - }, - "externalName service": { - cluster: &dag.Cluster{ - Upstream: service(s2), - }, - want: &v2.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_STRICT_DNS), - LoadAssignment: StaticClusterLoadAssignment(service(s2)), - }, - }, - "tls upstream": { - cluster: &dag.Cluster{ - Upstream: service(s1, "tls"), - Protocol: "tls", - }, - want: &v2.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource("contour"), - ServiceName: "default/kuard/http", - }, - TransportSocket: UpstreamTLSTransportSocket( - UpstreamTLSContext(nil, ""), - ), - }, - }, - "tls upstream - external name": { - cluster: &dag.Cluster{ - Upstream: service(svcExternal, "tls"), - Protocol: "tls", - SNI: "projectcontour.local", - }, - want: &v2.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_STRICT_DNS), - LoadAssignment: StaticClusterLoadAssignment(service(svcExternal, "tls")), - TransportSocket: UpstreamTLSTransportSocket( - UpstreamTLSContext(nil, "projectcontour.local"), - ), - }, - }, - "verify tls upstream with san": { - cluster: &dag.Cluster{ - Upstream: service(s1, "tls"), - Protocol: "tls", - UpstreamValidation: &dag.PeerValidationContext{ - CACertificate: secret, - SubjectName: "foo.bar.io", - }, - }, - want: &v2.Cluster{ - Name: "default/kuard/443/3ac4e90987", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource("contour"), - ServiceName: "default/kuard/http", - }, - TransportSocket: UpstreamTLSTransportSocket( - UpstreamTLSContext( - &dag.PeerValidationContext{ - CACertificate: secret, - SubjectName: "foo.bar.io", - }, - ""), - ), - }, - }, - "projectcontour.io/max-connections": { - cluster: &dag.Cluster{ - Upstream: &dag.Service{ - MaxConnections: 9000, - Weighted: dag.WeightedService{ - Weight: 1, - ServiceName: s1.Name, - ServiceNamespace: s1.Namespace, - ServicePort: s1.Spec.Ports[0], - }, - }, - }, - want: &v2.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource("contour"), - ServiceName: "default/kuard/http", - }, - CircuitBreakers: &envoy_cluster.CircuitBreakers{ - Thresholds: []*envoy_cluster.CircuitBreakers_Thresholds{{ - MaxConnections: protobuf.UInt32(9000), - }}, - }, - }, - }, - "projectcontour.io/max-pending-requests": { - cluster: &dag.Cluster{ - Upstream: &dag.Service{ - MaxPendingRequests: 4096, - Weighted: dag.WeightedService{ - Weight: 1, - ServiceName: s1.Name, - ServiceNamespace: s1.Namespace, - ServicePort: s1.Spec.Ports[0], - }, - }, - }, - want: &v2.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource("contour"), - ServiceName: "default/kuard/http", - }, - CircuitBreakers: &envoy_cluster.CircuitBreakers{ - Thresholds: []*envoy_cluster.CircuitBreakers_Thresholds{{ - MaxPendingRequests: protobuf.UInt32(4096), - }}, - }, - }, - }, - "projectcontour.io/max-requests": { - cluster: &dag.Cluster{ - Upstream: &dag.Service{ - MaxRequests: 404, - Weighted: dag.WeightedService{ - Weight: 1, - ServiceName: s1.Name, - ServiceNamespace: s1.Namespace, - ServicePort: s1.Spec.Ports[0], - }, - }, - }, - want: &v2.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource("contour"), - ServiceName: "default/kuard/http", - }, - CircuitBreakers: &envoy_cluster.CircuitBreakers{ - Thresholds: []*envoy_cluster.CircuitBreakers_Thresholds{{ - MaxRequests: protobuf.UInt32(404), - }}, - }, - }, - }, - "projectcontour.io/max-retries": { - cluster: &dag.Cluster{ - Upstream: &dag.Service{ - MaxRetries: 7, - Weighted: dag.WeightedService{ - Weight: 1, - ServiceName: s1.Name, - ServiceNamespace: s1.Namespace, - ServicePort: s1.Spec.Ports[0], - }, - }, - }, - want: &v2.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource("contour"), - ServiceName: "default/kuard/http", - }, - CircuitBreakers: &envoy_cluster.CircuitBreakers{ - Thresholds: []*envoy_cluster.CircuitBreakers_Thresholds{{ - MaxRetries: protobuf.UInt32(7), - }}, - }, - }, - }, - "cluster with random load balancer policy": { - cluster: &dag.Cluster{ - Upstream: service(s1), - LoadBalancerPolicy: "Random", - }, - want: &v2.Cluster{ - Name: "default/kuard/443/58d888c08a", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource("contour"), - ServiceName: "default/kuard/http", - }, - LbPolicy: v2.Cluster_RANDOM, - }, - }, - "cluster with cookie policy": { - cluster: &dag.Cluster{ - Upstream: service(s1), - LoadBalancerPolicy: "Cookie", - }, - want: &v2.Cluster{ - Name: "default/kuard/443/e4f81994fe", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource("contour"), - ServiceName: "default/kuard/http", - }, - LbPolicy: v2.Cluster_RING_HASH, - }, - }, - - "tcp service": { - cluster: &dag.Cluster{ - Upstream: service(s1), - }, - want: &v2.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource("contour"), - ServiceName: "default/kuard/http", - }, - }, - }, - "tcp service with healthcheck": { - cluster: &dag.Cluster{ - Upstream: service(s1), - TCPHealthCheckPolicy: &dag.TCPHealthCheckPolicy{ - Timeout: 2, - Interval: 10, - UnhealthyThreshold: 3, - HealthyThreshold: 2, - }, - }, - want: &v2.Cluster{ - Name: "default/kuard/443/da39a3ee5e", - AltStatName: "default_kuard_443", - ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: ConfigSource("contour"), - ServiceName: "default/kuard/http", - }, - DrainConnectionsOnHostRemoval: true, - HealthChecks: []*envoy_api_v2_core.HealthCheck{{ - Timeout: durationOrDefault(2, hcTimeout), - Interval: durationOrDefault(10, hcInterval), - UnhealthyThreshold: protobuf.UInt32OrDefault(3, hcUnhealthyThreshold), - HealthyThreshold: protobuf.UInt32OrDefault(2, hcHealthyThreshold), - HealthChecker: &envoy_api_v2_core.HealthCheck_TcpHealthCheck_{ - TcpHealthCheck: &envoy_api_v2_core.HealthCheck_TcpHealthCheck{}, - }, - }}, - }, - }, - } - - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - got := Cluster(tc.cluster) - want := clusterDefaults() - - proto.Merge(want, tc.want) - - protobuf.ExpectEqual(t, want, got) - }) - } -} - -func TestClusterLoadAssignmentName(t *testing.T) { - assert.Equal(t, xds.ClusterLoadAssignmentName(types.NamespacedName{Namespace: "ns", Name: "svc"}, "port"), "ns/svc/port") - assert.Equal(t, xds.ClusterLoadAssignmentName(types.NamespacedName{Namespace: "ns", Name: "svc"}, ""), "ns/svc") - assert.Equal(t, xds.ClusterLoadAssignmentName(types.NamespacedName{}, ""), "/") -} - -func TestClustername(t *testing.T) { - tests := map[string]struct { - cluster *dag.Cluster - want string - }{ - "simple": { - cluster: &dag.Cluster{ - Upstream: &dag.Service{ - Weighted: dag.WeightedService{ - Weight: 1, - ServiceName: "backend", - ServiceNamespace: "default", - ServicePort: v1.ServicePort{ - Name: "http", - Protocol: "TCP", - Port: 80, - TargetPort: intstr.FromInt(6502), - }, - }, - }, - }, - want: "default/backend/80/da39a3ee5e", - }, - "far too long": { - cluster: &dag.Cluster{ - Upstream: &dag.Service{ - Weighted: dag.WeightedService{ - Weight: 1, - ServiceName: "must-be-in-want-of-a-wife", - ServiceNamespace: "it-is-a-truth-universally-acknowledged-that-a-single-man-in-possession-of-a-good-fortune", - ServicePort: v1.ServicePort{ - Name: "http", - Protocol: "TCP", - Port: 9999, - TargetPort: intstr.FromString("http-alt"), - }, - }, - }, - }, - want: "it-is-a--dea8b0/must-be--dea8b0/9999/da39a3ee5e", - }, - "various healthcheck params": { - cluster: &dag.Cluster{ - Upstream: &dag.Service{ - Weighted: dag.WeightedService{ - Weight: 1, - ServiceName: "backend", - ServiceNamespace: "default", - ServicePort: v1.ServicePort{ - Name: "http", - Protocol: "TCP", - Port: 80, - TargetPort: intstr.FromInt(6502), - }, - }, - }, - LoadBalancerPolicy: "Random", - HTTPHealthCheckPolicy: &dag.HTTPHealthCheckPolicy{ - Path: "/healthz", - Interval: 5 * time.Second, - Timeout: 30 * time.Second, - UnhealthyThreshold: 3, - HealthyThreshold: 1, - }, - }, - want: "default/backend/80/5c26077e1d", - }, - "upstream tls validation with subject alt name": { - cluster: &dag.Cluster{ - Upstream: &dag.Service{ - Weighted: dag.WeightedService{ - Weight: 1, - ServiceName: "backend", - ServiceNamespace: "default", - ServicePort: v1.ServicePort{ - Name: "http", - Protocol: "TCP", - Port: 80, - TargetPort: intstr.FromInt(6502), - }, - }, - }, - LoadBalancerPolicy: "Random", - UpstreamValidation: &dag.PeerValidationContext{ - CACertificate: &dag.Secret{ - Object: &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "secret", - Namespace: "default", - }, - Data: map[string][]byte{ - dag.CACertificateKey: []byte("somethingsecret"), - }, - }, - }, - SubjectName: "foo.com", - }, - }, - want: "default/backend/80/6bf46b7b3a", - }, - } - - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - got := Clustername(tc.cluster) - assert.Equal(t, tc.want, got) - }) - } -} - -func TestLBPolicy(t *testing.T) { - tests := map[string]v2.Cluster_LbPolicy{ - "WeightedLeastRequest": v2.Cluster_LEAST_REQUEST, - "Random": v2.Cluster_RANDOM, - "RoundRobin": v2.Cluster_ROUND_ROBIN, - "": v2.Cluster_ROUND_ROBIN, - "unknown": v2.Cluster_ROUND_ROBIN, - "Cookie": v2.Cluster_RING_HASH, - - // RingHash and Maglev were removed as options in 0.13. - // See #1150 - "RingHash": v2.Cluster_ROUND_ROBIN, - "Maglev": v2.Cluster_ROUND_ROBIN, - } - - for policy, want := range tests { - t.Run(policy, func(t *testing.T) { - got := lbPolicy(policy) - assert.Equal(t, want, got) - }) - } -} - -func TestHashname(t *testing.T) { - tests := []struct { - name string - l int - s []string - want string - }{ - {name: "empty s", l: 99, s: nil, want: ""}, - {name: "single element", l: 99, s: []string{"alpha"}, want: "alpha"}, - {name: "long single element, hashed", l: 12, s: []string{"gammagammagamma"}, want: "0d350ea5c204"}, - {name: "single element, truncated", l: 4, s: []string{"alpha"}, want: "8ed3"}, - {name: "two elements, truncated", l: 19, s: []string{"gammagamma", "betabeta"}, want: "ga-edf159/betabeta"}, - {name: "three elements", l: 99, s: []string{"alpha", "beta", "gamma"}, want: "alpha/beta/gamma"}, - {name: "issue/25", l: 60, s: []string{"default", "my-service-name", "my-very-very-long-service-host-name.my.domainname"}, want: "default/my-service-name/my-very-very--c4d2d4"}, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - got := hashname(tc.l, append([]string{}, tc.s...)...) - assert.Equal(t, tc.want, got) - }) - } -} - func TestTruncate(t *testing.T) { tests := []struct { name string @@ -606,36 +33,33 @@ func TestTruncate(t *testing.T) { } func TestAnyPositive(t *testing.T) { - assert.Equal(t, false, anyPositive(0)) - assert.Equal(t, true, anyPositive(1)) - assert.Equal(t, false, anyPositive(0, 0)) - assert.Equal(t, true, anyPositive(1, 0)) - assert.Equal(t, true, anyPositive(0, 1)) + assert.Equal(t, false, AnyPositive(0)) + assert.Equal(t, true, AnyPositive(1)) + assert.Equal(t, false, AnyPositive(0, 0)) + assert.Equal(t, true, AnyPositive(1, 0)) + assert.Equal(t, true, AnyPositive(0, 1)) } -func TestClusterCommonLBConfig(t *testing.T) { - got := ClusterCommonLBConfig() - want := &v2.Cluster_CommonLbConfig{ - HealthyPanicThreshold: &envoy_type.Percent{ // Disable HealthyPanicThreshold - Value: 0, - }, +func TestHashname(t *testing.T) { + tests := []struct { + name string + l int + s []string + want string + }{ + {name: "empty s", l: 99, s: nil, want: ""}, + {name: "single element", l: 99, s: []string{"alpha"}, want: "alpha"}, + {name: "long single element, hashed", l: 12, s: []string{"gammagammagamma"}, want: "0d350ea5c204"}, + {name: "single element, truncated", l: 4, s: []string{"alpha"}, want: "8ed3"}, + {name: "two elements, truncated", l: 19, s: []string{"gammagamma", "betabeta"}, want: "ga-edf159/betabeta"}, + {name: "three elements", l: 99, s: []string{"alpha", "beta", "gamma"}, want: "alpha/beta/gamma"}, + {name: "issue/25", l: 60, s: []string{"default", "my-service-name", "my-very-very-long-service-host-name.my.domainname"}, want: "default/my-service-name/my-very-very--c4d2d4"}, } - assert.Equal(t, want, got) -} -func service(s *v1.Service, protocols ...string) *dag.Service { - protocol := "" - if len(protocols) > 0 { - protocol = protocols[0] - } - return &dag.Service{ - Weighted: dag.WeightedService{ - Weight: 1, - ServiceName: s.Name, - ServiceNamespace: s.Namespace, - ServicePort: s.Spec.Ports[0], - }, - ExternalName: s.Spec.ExternalName, - Protocol: protocol, + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + got := Hashname(tc.l, append([]string{}, tc.s...)...) + assert.Equal(t, tc.want, got) + }) } } diff --git a/internal/envoy/healthcheck.go b/internal/envoy/healthcheck.go index 302fd6882b4..9bac42ae126 100644 --- a/internal/envoy/healthcheck.go +++ b/internal/envoy/healthcheck.go @@ -13,66 +13,13 @@ package envoy -import ( - "time" - - envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" - "github.com/golang/protobuf/ptypes/duration" - "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/protobuf" -) +import "time" const ( // Default healthcheck / lb algorithm values - hcTimeout = 2 * time.Second - hcInterval = 10 * time.Second - hcUnhealthyThreshold = 3 - hcHealthyThreshold = 2 - hcHost = "contour-envoy-healthcheck" + HCTimeout = 2 * time.Second + HCInterval = 10 * time.Second + HCUnhealthyThreshold = 3 + HCHealthyThreshold = 2 + HCHost = "contour-envoy-healthcheck" ) - -// httpHealthCheck returns a *envoy_api_v2_core.HealthCheck value for HTTP Routes -func httpHealthCheck(cluster *dag.Cluster) *envoy_api_v2_core.HealthCheck { - hc := cluster.HTTPHealthCheckPolicy - host := hcHost - if hc.Host != "" { - host = hc.Host - } - - // TODO(dfc) why do we need to specify our own default, what is the default - // that envoy applies if these fields are left nil? - return &envoy_api_v2_core.HealthCheck{ - Timeout: durationOrDefault(hc.Timeout, hcTimeout), - Interval: durationOrDefault(hc.Interval, hcInterval), - UnhealthyThreshold: protobuf.UInt32OrDefault(hc.UnhealthyThreshold, hcUnhealthyThreshold), - HealthyThreshold: protobuf.UInt32OrDefault(hc.HealthyThreshold, hcHealthyThreshold), - HealthChecker: &envoy_api_v2_core.HealthCheck_HttpHealthCheck_{ - HttpHealthCheck: &envoy_api_v2_core.HealthCheck_HttpHealthCheck{ - Path: hc.Path, - Host: host, - }, - }, - } -} - -// tcpHealthCheck returns a *envoy_api_v2_core.HealthCheck value for TCPProxies -func tcpHealthCheck(cluster *dag.Cluster) *envoy_api_v2_core.HealthCheck { - hc := cluster.TCPHealthCheckPolicy - - return &envoy_api_v2_core.HealthCheck{ - Timeout: durationOrDefault(hc.Timeout, hcTimeout), - Interval: durationOrDefault(hc.Interval, hcInterval), - UnhealthyThreshold: protobuf.UInt32OrDefault(hc.UnhealthyThreshold, hcUnhealthyThreshold), - HealthyThreshold: protobuf.UInt32OrDefault(hc.HealthyThreshold, hcHealthyThreshold), - HealthChecker: &envoy_api_v2_core.HealthCheck_TcpHealthCheck_{ - TcpHealthCheck: &envoy_api_v2_core.HealthCheck_TcpHealthCheck{}, - }, - } -} - -func durationOrDefault(d, def time.Duration) *duration.Duration { - if d != 0 { - return protobuf.Duration(d) - } - return protobuf.Duration(def) -} diff --git a/internal/envoy/listener.go b/internal/envoy/listener.go index 57645f92932..9297683bc66 100644 --- a/internal/envoy/listener.go +++ b/internal/envoy/listener.go @@ -14,27 +14,9 @@ package envoy import ( - "fmt" "log" - "sort" - "strings" - "time" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" - envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" - envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" - envoy_api_v2_listener "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener" - accesslog "github.com/envoyproxy/go-control-plane/envoy/config/filter/accesslog/v2" - envoy_config_filter_http_ext_authz_v2 "github.com/envoyproxy/go-control-plane/envoy/config/filter/http/ext_authz/v2" - lua "github.com/envoyproxy/go-control-plane/envoy/config/filter/http/lua/v2" http "github.com/envoyproxy/go-control-plane/envoy/config/filter/network/http_connection_manager/v2" - tcp "github.com/envoyproxy/go-control-plane/envoy/config/filter/network/tcp_proxy/v2" - envoy_type "github.com/envoyproxy/go-control-plane/envoy/type" - "github.com/envoyproxy/go-control-plane/pkg/wellknown" - "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/protobuf" - "github.com/projectcontour/contour/internal/sorter" - "github.com/projectcontour/contour/internal/timeout" ) type HTTPVersionType = http.HttpConnectionManager_CodecType @@ -46,35 +28,6 @@ const ( HTTPVersion3 HTTPVersionType = http.HttpConnectionManager_HTTP3 ) -// TLSInspector returns a new TLS inspector listener filter. -func TLSInspector() *envoy_api_v2_listener.ListenerFilter { - return &envoy_api_v2_listener.ListenerFilter{ - Name: wellknown.TlsInspector, - } -} - -// ProxyProtocol returns a new Proxy Protocol listener filter. -func ProxyProtocol() *envoy_api_v2_listener.ListenerFilter { - return &envoy_api_v2_listener.ListenerFilter{ - Name: wellknown.ProxyProtocol, - } -} - -// CodecForVersions determines a single Envoy HTTP codec constant -// that support all the given HTTP protocol versions. -func CodecForVersions(versions ...HTTPVersionType) HTTPVersionType { - switch len(versions) { - case 1: - return versions[0] - case 0: - // Default is to autodetect. - return HTTPVersionAuto - default: - // If more than one version is allowed, autodetect and let ALPN sort it out. - return HTTPVersionAuto - } -} - // ProtoNamesForVersions returns the slice of ALPN protocol names for the give HTTP versions. func ProtoNamesForVersions(versions ...HTTPVersionType) []string { protocols := map[HTTPVersionType]string{ @@ -110,466 +63,17 @@ func ProtoNamesForVersions(versions ...HTTPVersionType) []string { return alpn } -// Listener returns a new v2.Listener for the supplied address, port, and filters. -func Listener(name, address string, port int, lf []*envoy_api_v2_listener.ListenerFilter, filters ...*envoy_api_v2_listener.Filter) *v2.Listener { - l := &v2.Listener{ - Name: name, - Address: SocketAddress(address, port), - ListenerFilters: lf, - SocketOptions: TCPKeepaliveSocketOptions(), - } - if len(filters) > 0 { - l.FilterChains = append( - l.FilterChains, - &envoy_api_v2_listener.FilterChain{ - Filters: filters, - }, - ) - } - return l -} - -type httpConnectionManagerBuilder struct { - routeConfigName string - metricsPrefix string - accessLoggers []*accesslog.AccessLog - requestTimeout timeout.Setting - connectionIdleTimeout timeout.Setting - streamIdleTimeout timeout.Setting - maxConnectionDuration timeout.Setting - connectionShutdownGracePeriod timeout.Setting - filters []*http.HttpFilter - codec HTTPVersionType // Note the zero value is AUTO, which is the default we want. -} - -// RouteConfigName sets the name of the RDS element that contains -// the routing table for this manager. -func (b *httpConnectionManagerBuilder) RouteConfigName(name string) *httpConnectionManagerBuilder { - b.routeConfigName = name - return b -} - -// MetricsPrefix sets the prefix used for emitting metrics from the -// connection manager. Note that this prefix is externally visible in -// monitoring tools, so it is subject to compatibility concerns. -// -// See https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/stats#config-http-conn-man-stats -func (b *httpConnectionManagerBuilder) MetricsPrefix(prefix string) *httpConnectionManagerBuilder { - b.metricsPrefix = prefix - return b -} - -// Codec sets the HTTP codec for the manager. The default is AUTO. -func (b *httpConnectionManagerBuilder) Codec(codecType HTTPVersionType) *httpConnectionManagerBuilder { - b.codec = codecType - return b -} - -// AccessLoggers sets the access logging configuration. -func (b *httpConnectionManagerBuilder) AccessLoggers(loggers []*accesslog.AccessLog) *httpConnectionManagerBuilder { - b.accessLoggers = loggers - return b -} - -// RequestTimeout sets the active request timeout on the connection manager. -func (b *httpConnectionManagerBuilder) RequestTimeout(timeout timeout.Setting) *httpConnectionManagerBuilder { - b.requestTimeout = timeout - return b -} - -// ConnectionIdleTimeout sets the idle timeout on the connection manager. -func (b *httpConnectionManagerBuilder) ConnectionIdleTimeout(timeout timeout.Setting) *httpConnectionManagerBuilder { - b.connectionIdleTimeout = timeout - return b -} - -// StreamIdleTimeout sets the stream idle timeout on the connection manager. -func (b *httpConnectionManagerBuilder) StreamIdleTimeout(timeout timeout.Setting) *httpConnectionManagerBuilder { - b.streamIdleTimeout = timeout - return b -} - -// MaxConnectionDuration sets the max connection duration on the connection manager. -func (b *httpConnectionManagerBuilder) MaxConnectionDuration(timeout timeout.Setting) *httpConnectionManagerBuilder { - b.maxConnectionDuration = timeout - return b -} - -// ConnectionShutdownGracePeriod sets the drain timeout on the connection manager. -func (b *httpConnectionManagerBuilder) ConnectionShutdownGracePeriod(timeout timeout.Setting) *httpConnectionManagerBuilder { - b.connectionShutdownGracePeriod = timeout - return b -} - -func (b *httpConnectionManagerBuilder) DefaultFilters() *httpConnectionManagerBuilder { - b.filters = append(b.filters, - &http.HttpFilter{ - Name: wellknown.Gzip, - }, - &http.HttpFilter{ - Name: wellknown.GRPCWeb, - }, - &http.HttpFilter{ - Name: wellknown.Router, - }, - ) - - return b -} - -// AddFilter appends f to the list of filters for this HTTPConnectionManager. f -// may by nil, in which case it is ignored. -func (b *httpConnectionManagerBuilder) AddFilter(f *http.HttpFilter) *httpConnectionManagerBuilder { - if f == nil { - return b - } - - if len(b.filters) > 0 { - lastIndex := len(b.filters) - 1 - // If the router filter is last, keep it at the end - // of the filter chain when we add the new filter. - if b.filters[lastIndex].Name == wellknown.Router { - b.filters = append(b.filters[:lastIndex], f, b.filters[lastIndex]) - return b - } - } - - b.filters = append(b.filters, f) - - return b -} - -// Validate runs builtin validation rules against the current builder state. -func (b *httpConnectionManagerBuilder) Validate() error { - filterNames := map[string]struct{}{} - - for _, f := range b.filters { - filterNames[f.Name] = struct{}{} - } - - // If there's no router filter, requests won't be forwarded. - if _, ok := filterNames[wellknown.Router]; !ok { - return fmt.Errorf("missing required filter %q", wellknown.Router) - } - - return nil -} - -// Get returns a new http.HttpConnectionManager filter, constructed -// from the builder settings. -// -// See https://www.envoyproxy.io/docs/envoy/latest/api-v2/config/filter/network/http_connection_manager/v2/http_connection_manager.proto.html -func (b *httpConnectionManagerBuilder) Get() *envoy_api_v2_listener.Filter { - // For now, failing validation is a programmer error that - // the caller can't reasonably recover from. A caller that can - // handle this should validate manually. - if err := b.Validate(); err != nil { - panic(err.Error()) - } - - cm := &http.HttpConnectionManager{ - CodecType: b.codec, - RouteSpecifier: &http.HttpConnectionManager_Rds{ - Rds: &http.Rds{ - RouteConfigName: b.routeConfigName, - ConfigSource: ConfigSource("contour"), - }, - }, - HttpFilters: b.filters, - CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{ - IdleTimeout: envoyTimeout(b.connectionIdleTimeout), - }, - HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ - // Enable support for HTTP/1.0 requests that carry - // a Host: header. See #537. - AcceptHttp_10: true, - }, - UseRemoteAddress: protobuf.Bool(true), - NormalizePath: protobuf.Bool(true), - - // issue #1487 pass through X-Request-Id if provided. - PreserveExternalRequestId: true, - MergeSlashes: true, - - RequestTimeout: envoyTimeout(b.requestTimeout), - StreamIdleTimeout: envoyTimeout(b.streamIdleTimeout), - DrainTimeout: envoyTimeout(b.connectionShutdownGracePeriod), - } - - // Max connection duration is infinite/disabled by default in Envoy, so if the timeout setting - // indicates to either disable or use default, don't pass a value at all. Note that unlike other - // Envoy timeouts, explicitly passing a 0 here *would not* disable the timeout; it needs to be - // omitted entirely. - if !b.maxConnectionDuration.IsDisabled() && !b.maxConnectionDuration.UseDefault() { - cm.CommonHttpProtocolOptions.MaxConnectionDuration = protobuf.Duration(b.maxConnectionDuration.Duration()) - } - - if len(b.accessLoggers) > 0 { - cm.AccessLog = b.accessLoggers - } - - // If there's no explicit metrics prefix, default it to the - // route config name. - if b.metricsPrefix != "" { - cm.StatPrefix = b.metricsPrefix - } else { - cm.StatPrefix = b.routeConfigName - } - - return &envoy_api_v2_listener.Filter{ - Name: wellknown.HTTPConnectionManager, - ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(cm), - }, - } -} - -// HTTPConnectionManager creates a new HTTP Connection Manager filter -// for the supplied route, access log, and client request timeout. -func HTTPConnectionManager(routename string, accesslogger []*accesslog.AccessLog, requestTimeout time.Duration) *envoy_api_v2_listener.Filter { - return HTTPConnectionManagerBuilder(). - RouteConfigName(routename). - MetricsPrefix(routename). - AccessLoggers(accesslogger). - RequestTimeout(timeout.DurationSetting(requestTimeout)). - DefaultFilters(). - Get() -} - -func HTTPConnectionManagerBuilder() *httpConnectionManagerBuilder { - return &httpConnectionManagerBuilder{} -} - -// TCPProxy creates a new TCPProxy filter. -func TCPProxy(statPrefix string, proxy *dag.TCPProxy, accesslogger []*accesslog.AccessLog) *envoy_api_v2_listener.Filter { - // Set the idle timeout in seconds for connections through a TCP Proxy type filter. - // The value of two and a half hours for reasons documented at - // https://github.com/projectcontour/contour/issues/1074 - // Set to 9001 because now it's OVER NINE THOUSAND. - idleTimeout := protobuf.Duration(9001 * time.Second) - - switch len(proxy.Clusters) { +// CodecForVersions determines a single Envoy HTTP codec constant +// that support all the given HTTP protocol versions. +func CodecForVersions(versions ...HTTPVersionType) HTTPVersionType { + switch len(versions) { case 1: - return &envoy_api_v2_listener.Filter{ - Name: wellknown.TCPProxy, - ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&tcp.TcpProxy{ - StatPrefix: statPrefix, - ClusterSpecifier: &tcp.TcpProxy_Cluster{ - Cluster: Clustername(proxy.Clusters[0]), - }, - AccessLog: accesslogger, - IdleTimeout: idleTimeout, - }), - }, - } + return versions[0] + case 0: + // Default is to autodetect. + return HTTPVersionAuto default: - var clusters []*tcp.TcpProxy_WeightedCluster_ClusterWeight - for _, c := range proxy.Clusters { - weight := c.Weight - if weight == 0 { - weight = 1 - } - clusters = append(clusters, &tcp.TcpProxy_WeightedCluster_ClusterWeight{ - Name: Clustername(c), - Weight: weight, - }) - } - sort.Stable(sorter.For(clusters)) - return &envoy_api_v2_listener.Filter{ - Name: wellknown.TCPProxy, - ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&tcp.TcpProxy{ - StatPrefix: statPrefix, - ClusterSpecifier: &tcp.TcpProxy_WeightedClusters{ - WeightedClusters: &tcp.TcpProxy_WeightedCluster{ - Clusters: clusters, - }, - }, - AccessLog: accesslogger, - IdleTimeout: idleTimeout, - }), - }, - } - } -} - -// SocketAddress creates a new TCP envoy_api_v2_core.Address. -func SocketAddress(address string, port int) *envoy_api_v2_core.Address { - if address == "::" { - return &envoy_api_v2_core.Address{ - Address: &envoy_api_v2_core.Address_SocketAddress{ - SocketAddress: &envoy_api_v2_core.SocketAddress{ - Protocol: envoy_api_v2_core.SocketAddress_TCP, - Address: address, - Ipv4Compat: true, - PortSpecifier: &envoy_api_v2_core.SocketAddress_PortValue{ - PortValue: uint32(port), - }, - }, - }, - } - } - return &envoy_api_v2_core.Address{ - Address: &envoy_api_v2_core.Address_SocketAddress{ - SocketAddress: &envoy_api_v2_core.SocketAddress{ - Protocol: envoy_api_v2_core.SocketAddress_TCP, - Address: address, - PortSpecifier: &envoy_api_v2_core.SocketAddress_PortValue{ - PortValue: uint32(port), - }, - }, - }, - } -} - -// Filters returns a []*envoy_api_v2_listener.Filter for the supplied filters. -func Filters(filters ...*envoy_api_v2_listener.Filter) []*envoy_api_v2_listener.Filter { - if len(filters) == 0 { - return nil - } - return filters -} - -// FilterChain retruns a *envoy_api_v2_listener.FilterChain for the supplied filters. -func FilterChain(filters ...*envoy_api_v2_listener.Filter) *envoy_api_v2_listener.FilterChain { - return &envoy_api_v2_listener.FilterChain{ - Filters: filters, - } -} - -// FilterChains returns a []*envoy_api_v2_listener.FilterChain for the supplied filters. -func FilterChains(filters ...*envoy_api_v2_listener.Filter) []*envoy_api_v2_listener.FilterChain { - if len(filters) == 0 { - return nil - } - return []*envoy_api_v2_listener.FilterChain{ - FilterChain(filters...), - } -} - -func FilterMisdirectedRequests(fqdn string) *http.HttpFilter { - // When Envoy matches on the virtual host domain, we configure - // it to match any port specifier (see envoy.VirtualHost), - // so the Host header (authority) may contain a port that - // should be ignored. This means that if we don't have a match, - // we should try again after stripping the port specifier. - - code := ` -function envoy_on_request(request_handle) - local headers = request_handle:headers() - local host = string.lower(headers:get(":authority")) - local target = "%s" - - if host ~= target then - s, e = string.find(host, ":", 1, true) - if s ~= nil then - host = string.sub(host, 1, s - 1) - end - - if host ~= target then - request_handle:respond( - {[":status"] = "421"}, - string.format("misdirected request to %%q", headers:get(":authority")) - ) - end - end -end - ` - - return &http.HttpFilter{ - Name: "envoy.filters.http.lua", - ConfigType: &http.HttpFilter_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&lua.Lua{ - InlineCode: fmt.Sprintf(code, strings.ToLower(fqdn)), - }), - }, - } -} - -// FilterExternalAuthz returns an `ext_authz` filter configured with the -// requested parameters. -func FilterExternalAuthz(authzClusterName string, failOpen bool, timeout timeout.Setting) *http.HttpFilter { - authConfig := envoy_config_filter_http_ext_authz_v2.ExtAuthz{ - Services: &envoy_config_filter_http_ext_authz_v2.ExtAuthz_GrpcService{ - GrpcService: &envoy_api_v2_core.GrpcService{ - TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ - ClusterName: authzClusterName, - }, - }, - Timeout: envoyTimeout(timeout), - // We don't need to configure metadata here, since we allow - // operators to specify authorization context parameters at - // the virtual host and route. - InitialMetadata: []*envoy_api_v2_core.HeaderValue{}, - }, - }, - // Pretty sure we always want this. Why have an - // external auth service if it is not going to affect - // routing decisions? - ClearRouteCache: true, - FailureModeAllow: failOpen, - StatusOnError: &envoy_type.HttpStatus{ - Code: envoy_type.StatusCode_Forbidden, - }, - MetadataContextNamespaces: []string{}, - IncludePeerCertificate: true, - } - - // TODO(jpeach): When we move to the Envoy v3 API, propagate the - // `transport_api_version` from ExtensionServiceSpec ProtocolVersion. - - return &http.HttpFilter{ - Name: "envoy.filters.http.ext_authz", - ConfigType: &http.HttpFilter_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&authConfig), - }, - } -} - -// FilterChainTLS returns a TLS enabled envoy_api_v2_listener.FilterChain. -func FilterChainTLS(domain string, downstream *envoy_api_v2_auth.DownstreamTlsContext, filters []*envoy_api_v2_listener.Filter) *envoy_api_v2_listener.FilterChain { - fc := &envoy_api_v2_listener.FilterChain{ - Filters: filters, - FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ - ServerNames: []string{domain}, - }, - } - // Attach TLS data to this listener if provided. - if downstream != nil { - fc.TransportSocket = DownstreamTLSTransportSocket(downstream) - - } - return fc -} - -// FilterChainTLSFallback returns a TLS enabled envoy_api_v2_listener.FilterChain conifgured for FallbackCertificate. -func FilterChainTLSFallback(downstream *envoy_api_v2_auth.DownstreamTlsContext, filters []*envoy_api_v2_listener.Filter) *envoy_api_v2_listener.FilterChain { - fc := &envoy_api_v2_listener.FilterChain{ - Name: "fallback-certificate", - Filters: filters, - FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ - TransportProtocol: "tls", - }, - } - // Attach TLS data to this listener if provided. - if downstream != nil { - fc.TransportSocket = DownstreamTLSTransportSocket(downstream) - } - return fc -} - -// ListenerFilters returns a []*envoy_api_v2_listener.ListenerFilter for the supplied listener filters. -func ListenerFilters(filters ...*envoy_api_v2_listener.ListenerFilter) []*envoy_api_v2_listener.ListenerFilter { - return filters -} - -func ContainsFallbackFilterChain(filterchains []*envoy_api_v2_listener.FilterChain) bool { - for _, fc := range filterchains { - if fc.Name == "fallback-certificate" { - return true - } + // If more than one version is allowed, autodetect and let ALPN sort it out. + return HTTPVersionAuto } - return false } diff --git a/internal/envoy/listener_test.go b/internal/envoy/listener_test.go index 4e010364369..741a0e76ba6 100644 --- a/internal/envoy/listener_test.go +++ b/internal/envoy/listener_test.go @@ -1,784 +1,11 @@ -// 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 envoy import ( "testing" - "time" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" - envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" - envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" - envoy_api_v2_listener "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener" - envoy_api_v2_accesslog "github.com/envoyproxy/go-control-plane/envoy/config/filter/accesslog/v2" - http "github.com/envoyproxy/go-control-plane/envoy/config/filter/network/http_connection_manager/v2" - envoy_config_v2_tcpproxy "github.com/envoyproxy/go-control-plane/envoy/config/filter/network/tcp_proxy/v2" - "github.com/envoyproxy/go-control-plane/pkg/wellknown" - "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/protobuf" - "github.com/projectcontour/contour/internal/timeout" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" ) -func TestListener(t *testing.T) { - tests := map[string]struct { - name, address string - port int - lf []*envoy_api_v2_listener.ListenerFilter - f []*envoy_api_v2_listener.Filter - want *v2.Listener - }{ - "insecure listener": { - name: "http", - address: "0.0.0.0", - port: 9000, - f: []*envoy_api_v2_listener.Filter{ - HTTPConnectionManager("http", FileAccessLogEnvoy("/dev/null"), 0), - }, - want: &v2.Listener{ - Name: "http", - Address: SocketAddress("0.0.0.0", 9000), - FilterChains: FilterChains( - HTTPConnectionManager("http", FileAccessLogEnvoy("/dev/null"), 0), - ), - SocketOptions: TCPKeepaliveSocketOptions(), - }, - }, - "insecure listener w/ proxy": { - name: "http-proxy", - address: "0.0.0.0", - port: 9000, - lf: []*envoy_api_v2_listener.ListenerFilter{ - ProxyProtocol(), - }, - f: []*envoy_api_v2_listener.Filter{ - HTTPConnectionManager("http-proxy", FileAccessLogEnvoy("/dev/null"), 0), - }, - want: &v2.Listener{ - Name: "http-proxy", - Address: SocketAddress("0.0.0.0", 9000), - ListenerFilters: ListenerFilters( - ProxyProtocol(), - ), - FilterChains: FilterChains( - HTTPConnectionManager("http-proxy", FileAccessLogEnvoy("/dev/null"), 0), - ), - SocketOptions: TCPKeepaliveSocketOptions(), - }, - }, - "secure listener": { - name: "https", - address: "0.0.0.0", - port: 9000, - lf: ListenerFilters( - TLSInspector(), - ), - want: &v2.Listener{ - Name: "https", - Address: SocketAddress("0.0.0.0", 9000), - ListenerFilters: ListenerFilters( - TLSInspector(), - ), - SocketOptions: TCPKeepaliveSocketOptions(), - }, - }, - "secure listener w/ proxy": { - name: "https-proxy", - address: "0.0.0.0", - port: 9000, - lf: ListenerFilters( - ProxyProtocol(), - TLSInspector(), - ), - want: &v2.Listener{ - Name: "https-proxy", - Address: SocketAddress("0.0.0.0", 9000), - ListenerFilters: ListenerFilters( - ProxyProtocol(), - TLSInspector(), - ), - SocketOptions: TCPKeepaliveSocketOptions(), - }, - }, - } - - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - got := Listener(tc.name, tc.address, tc.port, tc.lf, tc.f...) - protobuf.ExpectEqual(t, tc.want, got) - }) - } -} - -func TestSocketAddress(t *testing.T) { - const ( - addr = "foo.example.com" - port = 8123 - ) - - got := SocketAddress(addr, port) - want := &envoy_api_v2_core.Address{ - Address: &envoy_api_v2_core.Address_SocketAddress{ - SocketAddress: &envoy_api_v2_core.SocketAddress{ - Protocol: envoy_api_v2_core.SocketAddress_TCP, - Address: addr, - PortSpecifier: &envoy_api_v2_core.SocketAddress_PortValue{ - PortValue: port, - }, - }, - }, - } - require.Equal(t, want, got) - - got = SocketAddress("::", port) - want = &envoy_api_v2_core.Address{ - Address: &envoy_api_v2_core.Address_SocketAddress{ - SocketAddress: &envoy_api_v2_core.SocketAddress{ - Protocol: envoy_api_v2_core.SocketAddress_TCP, - Address: "::", - Ipv4Compat: true, // Set only for ipv6-any "::" - PortSpecifier: &envoy_api_v2_core.SocketAddress_PortValue{ - PortValue: port, - }, - }, - }, - } - assert.Equal(t, want, got) -} - -func TestDownstreamTLSContext(t *testing.T) { - const subjectName = "client-subject-name" - ca := []byte("client-ca-cert") - - serverSecret := &dag.Secret{ - Object: &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "tls-cert", - Namespace: "default", - }, - Data: map[string][]byte{ - v1.TLSCertKey: []byte("cert"), - v1.TLSPrivateKeyKey: []byte("key"), - }, - }, - } - - tlsParams := &envoy_api_v2_auth.TlsParameters{ - TlsMinimumProtocolVersion: envoy_api_v2_auth.TlsParameters_TLSv1_1, - TlsMaximumProtocolVersion: envoy_api_v2_auth.TlsParameters_TLSv1_3, - CipherSuites: []string{ - "[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]", - "[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]", - "ECDHE-ECDSA-AES128-SHA", - "ECDHE-RSA-AES128-SHA", - "ECDHE-ECDSA-AES256-GCM-SHA384", - "ECDHE-RSA-AES256-GCM-SHA384", - "ECDHE-ECDSA-AES256-SHA", - "ECDHE-RSA-AES256-SHA", - }, - } - - tlsCertificateSdsSecretConfigs := []*envoy_api_v2_auth.SdsSecretConfig{{ - Name: Secretname(serverSecret), - SdsConfig: &envoy_api_v2_core.ConfigSource{ - ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ - ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ - ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, - GrpcServices: []*envoy_api_v2_core.GrpcService{{ - TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ - ClusterName: "contour", - }, - }, - }}, - }, - }, - }, - }} - - alpnProtocols := []string{"h2", "http/1.1"} - validationContext := &envoy_api_v2_auth.CommonTlsContext_ValidationContext{ - ValidationContext: &envoy_api_v2_auth.CertificateValidationContext{ - TrustedCa: &envoy_api_v2_core.DataSource{ - Specifier: &envoy_api_v2_core.DataSource_InlineBytes{ - InlineBytes: ca, - }, - }, - }, - } - - peerValidationContext := &dag.PeerValidationContext{ - CACertificate: &dag.Secret{ - Object: &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "secret", - Namespace: "default", - }, - Data: map[string][]byte{ - dag.CACertificateKey: ca, - }, - }, - }, - } - - // Negative test case: downstream validation should not contain subjectname. - peerValidationContextWithSubjectName := &dag.PeerValidationContext{ - CACertificate: &dag.Secret{ - Object: &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "secret", - Namespace: "default", - }, - Data: map[string][]byte{ - dag.CACertificateKey: ca, - }, - }, - }, - SubjectName: subjectName, - } - - tests := map[string]struct { - got *envoy_api_v2_auth.DownstreamTlsContext - want *envoy_api_v2_auth.DownstreamTlsContext - }{ - "TLS context without client authentication": { - DownstreamTLSContext(serverSecret, envoy_api_v2_auth.TlsParameters_TLSv1_1, nil, "h2", "http/1.1"), - &envoy_api_v2_auth.DownstreamTlsContext{ - CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ - TlsParams: tlsParams, - TlsCertificateSdsSecretConfigs: tlsCertificateSdsSecretConfigs, - AlpnProtocols: alpnProtocols, - }, - }, - }, - "TLS context with client authentication": { - DownstreamTLSContext(serverSecret, envoy_api_v2_auth.TlsParameters_TLSv1_1, peerValidationContext, "h2", "http/1.1"), - &envoy_api_v2_auth.DownstreamTlsContext{ - CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ - TlsParams: tlsParams, - TlsCertificateSdsSecretConfigs: tlsCertificateSdsSecretConfigs, - AlpnProtocols: alpnProtocols, - ValidationContextType: validationContext, - }, - RequireClientCertificate: protobuf.Bool(true), - }, - }, - "Downstream validation shall not support subjectName validation": { - DownstreamTLSContext(serverSecret, envoy_api_v2_auth.TlsParameters_TLSv1_1, peerValidationContextWithSubjectName, "h2", "http/1.1"), - &envoy_api_v2_auth.DownstreamTlsContext{ - CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ - TlsParams: tlsParams, - TlsCertificateSdsSecretConfigs: tlsCertificateSdsSecretConfigs, - AlpnProtocols: alpnProtocols, - ValidationContextType: validationContext, - }, - RequireClientCertificate: protobuf.Bool(true), - }, - }, - } - - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - protobuf.ExpectEqual(t, tc.want, tc.got) - }) - } -} - -func TestHTTPConnectionManager(t *testing.T) { - tests := map[string]struct { - routename string - accesslogger []*envoy_api_v2_accesslog.AccessLog - requestTimeout timeout.Setting - connectionIdleTimeout timeout.Setting - streamIdleTimeout timeout.Setting - maxConnectionDuration timeout.Setting - connectionShutdownGracePeriod timeout.Setting - want *envoy_api_v2_listener.Filter - }{ - "default": { - routename: "default/kuard", - accesslogger: FileAccessLogEnvoy("/dev/stdout"), - want: &envoy_api_v2_listener.Filter{ - Name: wellknown.HTTPConnectionManager, - ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&http.HttpConnectionManager{ - StatPrefix: "default/kuard", - RouteSpecifier: &http.HttpConnectionManager_Rds{ - Rds: &http.Rds{ - RouteConfigName: "default/kuard", - ConfigSource: &envoy_api_v2_core.ConfigSource{ - ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ - ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ - ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, - GrpcServices: []*envoy_api_v2_core.GrpcService{{ - TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ - ClusterName: "contour", - }, - }, - }}, - }, - }, - }, - }, - }, - HttpFilters: []*http.HttpFilter{{ - Name: wellknown.Gzip, - }, { - Name: wellknown.GRPCWeb, - }, { - Name: wellknown.Router, - }}, - HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ - // Enable support for HTTP/1.0 requests that carry - // a Host: header. See #537. - AcceptHttp_10: true, - }, - CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{}, - AccessLog: FileAccessLogEnvoy("/dev/stdout"), - UseRemoteAddress: protobuf.Bool(true), - NormalizePath: protobuf.Bool(true), - PreserveExternalRequestId: true, - MergeSlashes: true, - }), - }, - }, - }, - "request timeout of 10s": { - routename: "default/kuard", - accesslogger: FileAccessLogEnvoy("/dev/stdout"), - requestTimeout: timeout.DurationSetting(10 * time.Second), - want: &envoy_api_v2_listener.Filter{ - Name: wellknown.HTTPConnectionManager, - ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&http.HttpConnectionManager{ - StatPrefix: "default/kuard", - RouteSpecifier: &http.HttpConnectionManager_Rds{ - Rds: &http.Rds{ - RouteConfigName: "default/kuard", - ConfigSource: &envoy_api_v2_core.ConfigSource{ - ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ - ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ - ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, - GrpcServices: []*envoy_api_v2_core.GrpcService{{ - TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ - ClusterName: "contour", - }, - }, - }}, - }, - }, - }, - }, - }, - HttpFilters: []*http.HttpFilter{{ - Name: wellknown.Gzip, - }, { - Name: wellknown.GRPCWeb, - }, { - Name: wellknown.Router, - }}, - HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ - // Enable support for HTTP/1.0 requests that carry - // a Host: header. See #537. - AcceptHttp_10: true, - }, - CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{}, - AccessLog: FileAccessLogEnvoy("/dev/stdout"), - UseRemoteAddress: protobuf.Bool(true), - NormalizePath: protobuf.Bool(true), - RequestTimeout: protobuf.Duration(10 * time.Second), - PreserveExternalRequestId: true, - MergeSlashes: true, - }), - }, - }, - }, - "connection idle timeout of 90s": { - routename: "default/kuard", - accesslogger: FileAccessLogEnvoy("/dev/stdout"), - connectionIdleTimeout: timeout.DurationSetting(90 * time.Second), - want: &envoy_api_v2_listener.Filter{ - Name: wellknown.HTTPConnectionManager, - ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&http.HttpConnectionManager{ - StatPrefix: "default/kuard", - RouteSpecifier: &http.HttpConnectionManager_Rds{ - Rds: &http.Rds{ - RouteConfigName: "default/kuard", - ConfigSource: &envoy_api_v2_core.ConfigSource{ - ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ - ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ - ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, - GrpcServices: []*envoy_api_v2_core.GrpcService{{ - TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ - ClusterName: "contour", - }, - }, - }}, - }, - }, - }, - }, - }, - HttpFilters: []*http.HttpFilter{{ - Name: wellknown.Gzip, - }, { - Name: wellknown.GRPCWeb, - }, { - Name: wellknown.Router, - }}, - HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ - // Enable support for HTTP/1.0 requests that carry - // a Host: header. See #537. - AcceptHttp_10: true, - }, - CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{ - IdleTimeout: protobuf.Duration(90 * time.Second), - }, - AccessLog: FileAccessLogEnvoy("/dev/stdout"), - UseRemoteAddress: protobuf.Bool(true), - NormalizePath: protobuf.Bool(true), - PreserveExternalRequestId: true, - MergeSlashes: true, - }), - }, - }, - }, - "stream idle timeout of 90s": { - routename: "default/kuard", - accesslogger: FileAccessLogEnvoy("/dev/stdout"), - streamIdleTimeout: timeout.DurationSetting(90 * time.Second), - want: &envoy_api_v2_listener.Filter{ - Name: wellknown.HTTPConnectionManager, - ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&http.HttpConnectionManager{ - StatPrefix: "default/kuard", - RouteSpecifier: &http.HttpConnectionManager_Rds{ - Rds: &http.Rds{ - RouteConfigName: "default/kuard", - ConfigSource: &envoy_api_v2_core.ConfigSource{ - ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ - ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ - ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, - GrpcServices: []*envoy_api_v2_core.GrpcService{{ - TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ - ClusterName: "contour", - }, - }, - }}, - }, - }, - }, - }, - }, - HttpFilters: []*http.HttpFilter{{ - Name: wellknown.Gzip, - }, { - Name: wellknown.GRPCWeb, - }, { - Name: wellknown.Router, - }}, - HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ - // Enable support for HTTP/1.0 requests that carry - // a Host: header. See #537. - AcceptHttp_10: true, - }, - CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{}, - AccessLog: FileAccessLogEnvoy("/dev/stdout"), - UseRemoteAddress: protobuf.Bool(true), - NormalizePath: protobuf.Bool(true), - PreserveExternalRequestId: true, - MergeSlashes: true, - StreamIdleTimeout: protobuf.Duration(90 * time.Second), - }), - }, - }, - }, - "max connection duration of 90s": { - routename: "default/kuard", - accesslogger: FileAccessLogEnvoy("/dev/stdout"), - maxConnectionDuration: timeout.DurationSetting(90 * time.Second), - want: &envoy_api_v2_listener.Filter{ - Name: wellknown.HTTPConnectionManager, - ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&http.HttpConnectionManager{ - StatPrefix: "default/kuard", - RouteSpecifier: &http.HttpConnectionManager_Rds{ - Rds: &http.Rds{ - RouteConfigName: "default/kuard", - ConfigSource: &envoy_api_v2_core.ConfigSource{ - ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ - ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ - ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, - GrpcServices: []*envoy_api_v2_core.GrpcService{{ - TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ - ClusterName: "contour", - }, - }, - }}, - }, - }, - }, - }, - }, - HttpFilters: []*http.HttpFilter{{ - Name: wellknown.Gzip, - }, { - Name: wellknown.GRPCWeb, - }, { - Name: wellknown.Router, - }}, - HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ - // Enable support for HTTP/1.0 requests that carry - // a Host: header. See #537. - AcceptHttp_10: true, - }, - CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{ - MaxConnectionDuration: protobuf.Duration(90 * time.Second), - }, - AccessLog: FileAccessLogEnvoy("/dev/stdout"), - UseRemoteAddress: protobuf.Bool(true), - NormalizePath: protobuf.Bool(true), - PreserveExternalRequestId: true, - MergeSlashes: true, - }), - }, - }, - }, - "when max connection duration is disabled, it's omitted": { - routename: "default/kuard", - accesslogger: FileAccessLogEnvoy("/dev/stdout"), - maxConnectionDuration: timeout.DisabledSetting(), - want: &envoy_api_v2_listener.Filter{ - Name: wellknown.HTTPConnectionManager, - ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&http.HttpConnectionManager{ - StatPrefix: "default/kuard", - RouteSpecifier: &http.HttpConnectionManager_Rds{ - Rds: &http.Rds{ - RouteConfigName: "default/kuard", - ConfigSource: &envoy_api_v2_core.ConfigSource{ - ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ - ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ - ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, - GrpcServices: []*envoy_api_v2_core.GrpcService{{ - TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ - ClusterName: "contour", - }, - }, - }}, - }, - }, - }, - }, - }, - HttpFilters: []*http.HttpFilter{{ - Name: wellknown.Gzip, - }, { - Name: wellknown.GRPCWeb, - }, { - Name: wellknown.Router, - }}, - HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ - // Enable support for HTTP/1.0 requests that carry - // a Host: header. See #537. - AcceptHttp_10: true, - }, - CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{}, - AccessLog: FileAccessLogEnvoy("/dev/stdout"), - UseRemoteAddress: protobuf.Bool(true), - NormalizePath: protobuf.Bool(true), - PreserveExternalRequestId: true, - MergeSlashes: true, - }), - }, - }, - }, - "drain timeout of 90s": { - routename: "default/kuard", - accesslogger: FileAccessLogEnvoy("/dev/stdout"), - connectionShutdownGracePeriod: timeout.DurationSetting(90 * time.Second), - want: &envoy_api_v2_listener.Filter{ - Name: wellknown.HTTPConnectionManager, - ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&http.HttpConnectionManager{ - StatPrefix: "default/kuard", - RouteSpecifier: &http.HttpConnectionManager_Rds{ - Rds: &http.Rds{ - RouteConfigName: "default/kuard", - ConfigSource: &envoy_api_v2_core.ConfigSource{ - ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ - ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ - ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, - GrpcServices: []*envoy_api_v2_core.GrpcService{{ - TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ - ClusterName: "contour", - }, - }, - }}, - }, - }, - }, - }, - }, - HttpFilters: []*http.HttpFilter{{ - Name: wellknown.Gzip, - }, { - Name: wellknown.GRPCWeb, - }, { - Name: wellknown.Router, - }}, - HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ - // Enable support for HTTP/1.0 requests that carry - // a Host: header. See #537. - AcceptHttp_10: true, - }, - CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{}, - AccessLog: FileAccessLogEnvoy("/dev/stdout"), - UseRemoteAddress: protobuf.Bool(true), - NormalizePath: protobuf.Bool(true), - PreserveExternalRequestId: true, - MergeSlashes: true, - DrainTimeout: protobuf.Duration(90 * time.Second), - }), - }, - }, - }, - } - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - got := HTTPConnectionManagerBuilder(). - RouteConfigName(tc.routename). - MetricsPrefix(tc.routename). - AccessLoggers(tc.accesslogger). - RequestTimeout(tc.requestTimeout). - ConnectionIdleTimeout(tc.connectionIdleTimeout). - StreamIdleTimeout(tc.streamIdleTimeout). - MaxConnectionDuration(tc.maxConnectionDuration). - ConnectionShutdownGracePeriod(tc.connectionShutdownGracePeriod). - DefaultFilters(). - Get() - - protobuf.ExpectEqual(t, tc.want, got) - }) - } -} - -func TestTCPProxy(t *testing.T) { - const ( - statPrefix = "ingress_https" - accessLogPath = "/dev/stdout" - ) - - c1 := &dag.Cluster{ - Upstream: &dag.Service{ - Weighted: dag.WeightedService{ - Weight: 1, - ServiceName: "example", - ServiceNamespace: "default", - ServicePort: v1.ServicePort{ - Protocol: "TCP", - Port: 443, - TargetPort: intstr.FromInt(8443), - }, - }, - }, - } - c2 := &dag.Cluster{ - Upstream: &dag.Service{ - Weighted: dag.WeightedService{ - ServiceName: "example2", - ServiceNamespace: "default", - ServicePort: v1.ServicePort{ - Protocol: "TCP", - Port: 443, - TargetPort: intstr.FromInt(8443), - }, - }, - }, - Weight: 20, - } - - tests := map[string]struct { - proxy *dag.TCPProxy - want *envoy_api_v2_listener.Filter - }{ - "single cluster": { - proxy: &dag.TCPProxy{ - Clusters: []*dag.Cluster{c1}, - }, - want: &envoy_api_v2_listener.Filter{ - Name: wellknown.TCPProxy, - ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&envoy_config_v2_tcpproxy.TcpProxy{ - StatPrefix: statPrefix, - ClusterSpecifier: &envoy_config_v2_tcpproxy.TcpProxy_Cluster{ - Cluster: Clustername(c1), - }, - AccessLog: FileAccessLogEnvoy(accessLogPath), - IdleTimeout: protobuf.Duration(9001 * time.Second), - }), - }, - }, - }, - "multiple cluster": { - proxy: &dag.TCPProxy{ - Clusters: []*dag.Cluster{c2, c1}, - }, - want: &envoy_api_v2_listener.Filter{ - Name: wellknown.TCPProxy, - ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(&envoy_config_v2_tcpproxy.TcpProxy{ - StatPrefix: statPrefix, - ClusterSpecifier: &envoy_config_v2_tcpproxy.TcpProxy_WeightedClusters{ - WeightedClusters: &envoy_config_v2_tcpproxy.TcpProxy_WeightedCluster{ - Clusters: []*envoy_config_v2_tcpproxy.TcpProxy_WeightedCluster_ClusterWeight{{ - Name: Clustername(c1), - Weight: 1, - }, { - Name: Clustername(c2), - Weight: 20, - }}, - }, - }, - AccessLog: FileAccessLogEnvoy(accessLogPath), - IdleTimeout: protobuf.Duration(9001 * time.Second), - }), - }, - }, - }, - } - - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - got := TCPProxy(statPrefix, tc.proxy, FileAccessLogEnvoy(accessLogPath)) - protobuf.ExpectEqual(t, tc.want, got) - }) - } -} - func TestCodecForVersions(t *testing.T) { assert.Equal(t, CodecForVersions(HTTPVersionAuto), HTTPVersionAuto) assert.Equal(t, CodecForVersions(HTTPVersion1, HTTPVersion2), HTTPVersionAuto) @@ -794,19 +21,3 @@ func TestProtoNamesForVersions(t *testing.T) { assert.Equal(t, ProtoNamesForVersions(HTTPVersion3), []string(nil)) assert.Equal(t, ProtoNamesForVersions(HTTPVersion1, HTTPVersion2), []string{"h2", "http/1.1"}) } - -// TestBuilderValidation tests that validation checks that -// DefaultFilters adds the required HTTP connection manager filters. -func TestBuilderValidation(t *testing.T) { - if err := HTTPConnectionManagerBuilder().Validate(); err == nil { - t.Errorf("ConnectionManager with no filters passed validation") - } - - if err := HTTPConnectionManagerBuilder().AddFilter(&http.HttpFilter{Name: "foo"}).Validate(); err == nil { - t.Errorf("ConnectionManager with no filters passed validation") - } - - if err := HTTPConnectionManagerBuilder().DefaultFilters().Validate(); err != nil { - t.Errorf("ConnectionManager with default filters failed validation: %s", err) - } -} diff --git a/internal/envoy/route.go b/internal/envoy/route.go index d1577043290..73eaa9022f2 100644 --- a/internal/envoy/route.go +++ b/internal/envoy/route.go @@ -14,157 +14,26 @@ package envoy import ( - "fmt" - "regexp" - "sort" - - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" - envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" - envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" - envoy_config_filter_http_ext_authz_v2 "github.com/envoyproxy/go-control-plane/envoy/config/filter/http/ext_authz/v2" - "github.com/golang/protobuf/ptypes/any" "github.com/golang/protobuf/ptypes/duration" - wrappers "github.com/golang/protobuf/ptypes/wrappers" "github.com/projectcontour/contour/internal/dag" "github.com/projectcontour/contour/internal/protobuf" - "github.com/projectcontour/contour/internal/sorter" "github.com/projectcontour/contour/internal/timeout" ) -// RouteAuthzDisabled returns a per-route config to disable authorization. -func RouteAuthzDisabled() *any.Any { - return protobuf.MustMarshalAny( - &envoy_config_filter_http_ext_authz_v2.ExtAuthzPerRoute{ - Override: &envoy_config_filter_http_ext_authz_v2.ExtAuthzPerRoute_Disabled{ - Disabled: true, - }, - }, - ) -} - -// RouteAuthzContext returns a per-route config to pass the given -// context entries in the check request. -func RouteAuthzContext(settings map[string]string) *any.Any { - return protobuf.MustMarshalAny( - &envoy_config_filter_http_ext_authz_v2.ExtAuthzPerRoute{ - Override: &envoy_config_filter_http_ext_authz_v2.ExtAuthzPerRoute_CheckSettings{ - CheckSettings: &envoy_config_filter_http_ext_authz_v2.CheckSettings{ - ContextExtensions: settings, - }, - }, - }, - ) -} - -// RouteMatch creates a *envoy_api_v2_route.RouteMatch for the supplied *dag.Route. -func RouteMatch(route *dag.Route) *envoy_api_v2_route.RouteMatch { - switch c := route.PathMatchCondition.(type) { - case *dag.RegexMatchCondition: - return &envoy_api_v2_route.RouteMatch{ - PathSpecifier: &envoy_api_v2_route.RouteMatch_SafeRegex{ - SafeRegex: SafeRegexMatch(c.Regex), - }, - Headers: headerMatcher(route.HeaderMatchConditions), - } - case *dag.PrefixMatchCondition: - return &envoy_api_v2_route.RouteMatch{ - PathSpecifier: &envoy_api_v2_route.RouteMatch_Prefix{ - Prefix: c.Prefix, - }, - Headers: headerMatcher(route.HeaderMatchConditions), - } - default: - return &envoy_api_v2_route.RouteMatch{ - Headers: headerMatcher(route.HeaderMatchConditions), - } - } -} - -// RouteRoute creates a *envoy_api_v2_route.Route_Route for the services supplied. -// If len(services) is greater than one, the route's action will be a -// weighted cluster. -func RouteRoute(r *dag.Route) *envoy_api_v2_route.Route_Route { - ra := envoy_api_v2_route.RouteAction{ - RetryPolicy: retryPolicy(r), - Timeout: envoyTimeout(r.TimeoutPolicy.ResponseTimeout), - IdleTimeout: envoyTimeout(r.TimeoutPolicy.IdleTimeout), - PrefixRewrite: r.PrefixRewrite, - HashPolicy: hashPolicy(r), - RequestMirrorPolicies: mirrorPolicy(r), - } - - // Check for host header policy and set if found - if val := hostReplaceHeader(r.RequestHeadersPolicy); val != "" { - ra.HostRewriteSpecifier = &envoy_api_v2_route.RouteAction_HostRewrite{ - HostRewrite: val, - } - } - - if r.Websocket { - ra.UpgradeConfigs = append(ra.UpgradeConfigs, - &envoy_api_v2_route.RouteAction_UpgradeConfig{ - UpgradeType: "websocket", - }, - ) - } - - if singleSimpleCluster(r.Clusters) { - ra.ClusterSpecifier = &envoy_api_v2_route.RouteAction_Cluster{ - Cluster: Clustername(r.Clusters[0]), - } - } else { - ra.ClusterSpecifier = &envoy_api_v2_route.RouteAction_WeightedClusters{ - WeightedClusters: weightedClusters(r.Clusters), - } - } - return &envoy_api_v2_route.Route_Route{ - Route: &ra, - } -} - -// hashPolicy returns a slice of hash policies iff at least one of the route's -// clusters supplied uses the `Cookie` load balancing strategy. -func hashPolicy(r *dag.Route) []*envoy_api_v2_route.RouteAction_HashPolicy { - for _, c := range r.Clusters { - if c.LoadBalancerPolicy == "Cookie" { - return []*envoy_api_v2_route.RouteAction_HashPolicy{{ - PolicySpecifier: &envoy_api_v2_route.RouteAction_HashPolicy_Cookie_{ - Cookie: &envoy_api_v2_route.RouteAction_HashPolicy_Cookie{ - Name: "X-Contour-Session-Affinity", - Ttl: protobuf.Duration(0), - Path: "/", - }, - }, - }} - } - } - return nil -} - -func mirrorPolicy(r *dag.Route) []*envoy_api_v2_route.RouteAction_RequestMirrorPolicy { - if r.MirrorPolicy == nil { - return nil - } - - return []*envoy_api_v2_route.RouteAction_RequestMirrorPolicy{{ - Cluster: Clustername(r.MirrorPolicy.Cluster), - }} -} - -func hostReplaceHeader(hp *dag.HeadersPolicy) string { +func HostReplaceHeader(hp *dag.HeadersPolicy) string { if hp == nil { return "" } return hp.HostRewrite } -// envoyTimeout converts a timeout.Setting to a protobuf.Duration +// Timeout converts a timeout.Setting to a protobuf.Duration // that's appropriate for Envoy. In general (though there are // exceptions), Envoy uses the following semantics: // - not passing a value means "use Envoy default" // - explicitly passing a 0 means "disable this timeout" // - passing a positive value uses that value -func envoyTimeout(d timeout.Setting) *duration.Duration { +func Timeout(d timeout.Setting) *duration.Duration { switch { case d.UseDefault(): // Don't pass a value to Envoy. @@ -178,63 +47,9 @@ func envoyTimeout(d timeout.Setting) *duration.Duration { } } -func retryPolicy(r *dag.Route) *envoy_api_v2_route.RetryPolicy { - if r.RetryPolicy == nil { - return nil - } - if r.RetryPolicy.RetryOn == "" { - return nil - } - - rp := &envoy_api_v2_route.RetryPolicy{ - RetryOn: r.RetryPolicy.RetryOn, - RetriableStatusCodes: r.RetryPolicy.RetriableStatusCodes, - } - if r.RetryPolicy.NumRetries > 0 { - rp.NumRetries = protobuf.UInt32(r.RetryPolicy.NumRetries) - } - rp.PerTryTimeout = envoyTimeout(r.RetryPolicy.PerTryTimeout) - - return rp -} - -// UpgradeHTTPS returns a route Action that redirects the request to HTTPS. -func UpgradeHTTPS() *envoy_api_v2_route.Route_Redirect { - return &envoy_api_v2_route.Route_Redirect{ - Redirect: &envoy_api_v2_route.RedirectAction{ - SchemeRewriteSpecifier: &envoy_api_v2_route.RedirectAction_HttpsRedirect{ - HttpsRedirect: true, - }, - }, - } -} - -// HeaderValueList creates a list of Envoy HeaderValueOptions from the provided map. -func HeaderValueList(hvm map[string]string, app bool) []*envoy_api_v2_core.HeaderValueOption { - var hvs []*envoy_api_v2_core.HeaderValueOption - - for key, value := range hvm { - hvs = append(hvs, &envoy_api_v2_core.HeaderValueOption{ - Header: &envoy_api_v2_core.HeaderValue{ - Key: key, - Value: value, - }, - Append: &wrappers.BoolValue{ - Value: app, - }, - }) - } - - sort.Slice(hvs, func(i, j int) bool { - return hvs[i].Header.Key < hvs[j].Header.Key - }) - - return hvs -} - -// singleSimpleCluster determines whether we can use a RouteAction_Cluster +// SingleSimpleCluster determines whether we can use a RouteAction_Cluster // or must use a RouteAction_WeighedCluster to encode additional routing data. -func singleSimpleCluster(clusters []*dag.Cluster) bool { +func SingleSimpleCluster(clusters []*dag.Cluster) bool { // If there are multiple clusters, than we cannot simply dispatch // to it by name. if len(clusters) != 1 { @@ -260,112 +75,3 @@ func singleSimpleCluster(clusters []*dag.Cluster) bool { return true } - -// weightedClusters returns a route.WeightedCluster for multiple services. -func weightedClusters(clusters []*dag.Cluster) *envoy_api_v2_route.WeightedCluster { - var wc envoy_api_v2_route.WeightedCluster - var total uint32 - for _, cluster := range clusters { - total += cluster.Weight - - c := &envoy_api_v2_route.WeightedCluster_ClusterWeight{ - Name: Clustername(cluster), - Weight: protobuf.UInt32(cluster.Weight), - } - if cluster.RequestHeadersPolicy != nil { - c.RequestHeadersToAdd = HeaderValueList(cluster.RequestHeadersPolicy.Set, false) - c.RequestHeadersToRemove = cluster.RequestHeadersPolicy.Remove - } - if cluster.ResponseHeadersPolicy != nil { - c.ResponseHeadersToAdd = HeaderValueList(cluster.ResponseHeadersPolicy.Set, false) - c.ResponseHeadersToRemove = cluster.ResponseHeadersPolicy.Remove - } - wc.Clusters = append(wc.Clusters, c) - } - // Check if no weights were defined, if not default to even distribution - if total == 0 { - for _, c := range wc.Clusters { - c.Weight.Value = 1 - } - total = uint32(len(clusters)) - } - wc.TotalWeight = protobuf.UInt32(total) - - sort.Stable(sorter.For(wc.Clusters)) - return &wc -} - -// VirtualHost creates a new route.VirtualHost. -func VirtualHost(hostname string, routes ...*envoy_api_v2_route.Route) *envoy_api_v2_route.VirtualHost { - domains := []string{hostname} - if hostname != "*" { - // NOTE(jpeach) see also envoy.FilterMisdirectedRequests(). - domains = append(domains, hostname+":*") - } - - return &envoy_api_v2_route.VirtualHost{ - Name: hashname(60, hostname), - Domains: domains, - Routes: routes, - } -} - -// RouteConfiguration returns a *v2.RouteConfiguration. -func RouteConfiguration(name string, virtualhosts ...*envoy_api_v2_route.VirtualHost) *v2.RouteConfiguration { - return &v2.RouteConfiguration{ - Name: name, - VirtualHosts: virtualhosts, - RequestHeadersToAdd: Headers( - AppendHeader("x-request-start", "t=%START_TIME(%s.%3f)%"), - ), - } -} - -func Headers(first *envoy_api_v2_core.HeaderValueOption, rest ...*envoy_api_v2_core.HeaderValueOption) []*envoy_api_v2_core.HeaderValueOption { - return append([]*envoy_api_v2_core.HeaderValueOption{first}, rest...) -} - -func AppendHeader(key, value string) *envoy_api_v2_core.HeaderValueOption { - return &envoy_api_v2_core.HeaderValueOption{ - Header: &envoy_api_v2_core.HeaderValue{ - Key: key, - Value: value, - }, - Append: protobuf.Bool(true), - } -} - -func headerMatcher(headers []dag.HeaderMatchCondition) []*envoy_api_v2_route.HeaderMatcher { - var envoyHeaders []*envoy_api_v2_route.HeaderMatcher - - for _, h := range headers { - header := &envoy_api_v2_route.HeaderMatcher{ - Name: h.Name, - InvertMatch: h.Invert, - } - - switch h.MatchType { - case "exact": - header.HeaderMatchSpecifier = &envoy_api_v2_route.HeaderMatcher_ExactMatch{ExactMatch: h.Value} - case "contains": - header.HeaderMatchSpecifier = containsMatch(h.Value) - case "present": - header.HeaderMatchSpecifier = &envoy_api_v2_route.HeaderMatcher_PresentMatch{PresentMatch: true} - } - envoyHeaders = append(envoyHeaders, header) - } - return envoyHeaders -} - -// containsMatch returns a HeaderMatchSpecifier which will match the -// supplied substring -func containsMatch(s string) *envoy_api_v2_route.HeaderMatcher_SafeRegexMatch { - // convert the substring s into a regular expression that matches s. - // note that Envoy expects the expression to match the entire string, not just the substring - // formed from s. see [projectcontour/contour/#1751 & envoyproxy/envoy#8283] - regex := fmt.Sprintf(".*%s.*", regexp.QuoteMeta(s)) - - return &envoy_api_v2_route.HeaderMatcher_SafeRegexMatch{ - SafeRegexMatch: SafeRegexMatch(regex), - } -} diff --git a/internal/envoy/secret.go b/internal/envoy/secret.go index 6d3397063c1..625f2d0606c 100644 --- a/internal/envoy/secret.go +++ b/internal/envoy/secret.go @@ -1,24 +1,9 @@ -// 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 envoy import ( "crypto/sha1" // nolint:gosec "fmt" - envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" - envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" "github.com/projectcontour/contour/internal/dag" ) @@ -28,26 +13,5 @@ func Secretname(s *dag.Secret) string { hash := sha1.Sum(s.Cert()) // nolint:gosec ns := s.Namespace() name := s.Name() - return hashname(60, ns, name, fmt.Sprintf("%x", hash[:5])) -} - -// Secret creates new envoy_api_v2_auth.Secret from secret. -func Secret(s *dag.Secret) *envoy_api_v2_auth.Secret { - return &envoy_api_v2_auth.Secret{ - Name: Secretname(s), - Type: &envoy_api_v2_auth.Secret_TlsCertificate{ - TlsCertificate: &envoy_api_v2_auth.TlsCertificate{ - PrivateKey: &envoy_api_v2_core.DataSource{ - Specifier: &envoy_api_v2_core.DataSource_InlineBytes{ - InlineBytes: s.PrivateKey(), - }, - }, - CertificateChain: &envoy_api_v2_core.DataSource{ - Specifier: &envoy_api_v2_core.DataSource_InlineBytes{ - InlineBytes: s.Cert(), - }, - }, - }, - }, - } + return Hashname(60, ns, name, fmt.Sprintf("%x", hash[:5])) } diff --git a/internal/envoy/tcp_keepalive.go b/internal/envoy/tcp_keepalive.go index e4230f265a7..1dd38a5819f 100644 --- a/internal/envoy/tcp_keepalive.go +++ b/internal/envoy/tcp_keepalive.go @@ -12,11 +12,7 @@ package envoy -import ( - "syscall" - - envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" -) +import "syscall" // We only support Envoy on Linux so always configure Linux TCP keep-alive // socket options regardless of the platform that Contour is running on. @@ -34,47 +30,3 @@ const ( // is defined here for consistency. IPPROTO_TCP = syscall.IPPROTO_TCP ) - -func TCPKeepaliveSocketOptions() []*envoy_api_v2_core.SocketOption { - - // Note: TCP_KEEPIDLE + (TCP_KEEPINTVL * TCP_KEEPCNT) must be greater than - // the grpc.KeepaliveParams time + timeout (currently 60 + 20 = 80 seconds) - // otherwise TestGRPC/StreamClusters fails. - return []*envoy_api_v2_core.SocketOption{ - // Enable TCP keep-alive. - { - Description: "Enable TCP keep-alive", - Level: SOL_SOCKET, - Name: SO_KEEPALIVE, - Value: &envoy_api_v2_core.SocketOption_IntValue{IntValue: 1}, - State: envoy_api_v2_core.SocketOption_STATE_LISTENING, - }, - // The time (in seconds) the connection needs to remain idle - // before TCP starts sending keepalive probes. - { - Description: "TCP keep-alive initial idle time", - Level: IPPROTO_TCP, - Name: TCP_KEEPIDLE, - Value: &envoy_api_v2_core.SocketOption_IntValue{IntValue: 45}, - State: envoy_api_v2_core.SocketOption_STATE_LISTENING, - }, - // The time (in seconds) between individual keepalive probes. - { - Description: "TCP keep-alive time between probes", - Level: IPPROTO_TCP, - Name: TCP_KEEPINTVL, - Value: &envoy_api_v2_core.SocketOption_IntValue{IntValue: 5}, - State: envoy_api_v2_core.SocketOption_STATE_LISTENING, - }, - // The maximum number of TCP keep-alive probes to send before - // giving up and killing the connection if no response is - // obtained from the other end. - { - Description: "TCP keep-alive probe count", - Level: IPPROTO_TCP, - Name: TCP_KEEPCNT, - Value: &envoy_api_v2_core.SocketOption_IntValue{IntValue: 9}, - State: envoy_api_v2_core.SocketOption_STATE_LISTENING, - }, - } -} diff --git a/internal/envoy/v2/accesslog.go b/internal/envoy/v2/accesslog.go new file mode 100644 index 00000000000..d1793f35e49 --- /dev/null +++ b/internal/envoy/v2/accesslog.go @@ -0,0 +1,75 @@ +// 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 v2 + +import ( + accesslogv2 "github.com/envoyproxy/go-control-plane/envoy/config/accesslog/v2" + accesslog "github.com/envoyproxy/go-control-plane/envoy/config/filter/accesslog/v2" + "github.com/envoyproxy/go-control-plane/pkg/wellknown" + _struct "github.com/golang/protobuf/ptypes/struct" + "github.com/projectcontour/contour/internal/envoy" + "github.com/projectcontour/contour/internal/protobuf" +) + +// FileAccessLogEnvoy returns a new file based access log filter +// that will output Envoy's default access logs. +func FileAccessLogEnvoy(path string) []*accesslog.AccessLog { + return []*accesslog.AccessLog{{ + Name: wellknown.FileAccessLog, + ConfigType: &accesslog.AccessLog_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&accesslogv2.FileAccessLog{ + Path: path, + // AccessLogFormat left blank to defer to Envoy's default log format. + }), + }, + }} +} + +// FileAccessLogJSON returns a new file based access log filter +// that will log in JSON format +func FileAccessLogJSON(path string, keys []string) []*accesslog.AccessLog { + + jsonformat := &_struct.Struct{ + Fields: make(map[string]*_struct.Value), + } + + for _, k := range keys { + // This will silently ignore invalid headers. + // TODO(youngnick): this should tell users if a header is not valid + // https://github.com/projectcontour/contour/issues/1507 + if template, ok := envoy.JSONFields[k]; ok { + jsonformat.Fields[k] = sv(template) + } + } + + return []*accesslog.AccessLog{{ + Name: wellknown.FileAccessLog, + ConfigType: &accesslog.AccessLog_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&accesslogv2.FileAccessLog{ + Path: path, + AccessLogFormat: &accesslogv2.FileAccessLog_JsonFormat{ + JsonFormat: jsonformat, + }, + }), + }, + }} +} + +func sv(s string) *_struct.Value { + return &_struct.Value{ + Kind: &_struct.Value_StringValue{ + StringValue: s, + }, + } +} diff --git a/internal/envoy/accesslog_test.go b/internal/envoy/v2/accesslog_test.go similarity index 94% rename from internal/envoy/accesslog_test.go rename to internal/envoy/v2/accesslog_test.go index 144f9096be1..3d883054575 100644 --- a/internal/envoy/accesslog_test.go +++ b/internal/envoy/v2/accesslog_test.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package envoy +package v2 import ( "testing" @@ -20,6 +20,7 @@ import ( envoy_accesslog "github.com/envoyproxy/go-control-plane/envoy/config/filter/accesslog/v2" "github.com/envoyproxy/go-control-plane/pkg/wellknown" _struct "github.com/golang/protobuf/ptypes/struct" + "github.com/projectcontour/contour/internal/envoy" "github.com/projectcontour/contour/internal/protobuf" ) @@ -89,8 +90,8 @@ func TestJSONFileAccessLog(t *testing.T) { AccessLogFormat: &accesslog_v2.FileAccessLog_JsonFormat{ JsonFormat: &_struct.Struct{ Fields: map[string]*_struct.Value{ - "@timestamp": sv(JSONFields["@timestamp"]), - "method": sv(JSONFields["method"]), + "@timestamp": sv(envoy.JSONFields["@timestamp"]), + "method": sv(envoy.JSONFields["method"]), }, }, }, diff --git a/internal/envoy/v2/auth.go b/internal/envoy/v2/auth.go new file mode 100644 index 00000000000..914534d3bb5 --- /dev/null +++ b/internal/envoy/v2/auth.go @@ -0,0 +1,101 @@ +// 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 v2 + +import ( + envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" + envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" + matcher "github.com/envoyproxy/go-control-plane/envoy/type/matcher" + "github.com/projectcontour/contour/internal/dag" + "github.com/projectcontour/contour/internal/envoy" + "github.com/projectcontour/contour/internal/protobuf" +) + +// UpstreamTLSContext creates an envoy_api_v2_auth.UpstreamTlsContext. By default +// UpstreamTLSContext returns a HTTP/1.1 TLS enabled context. A list of +// additional ALPN protocols can be provided. +func UpstreamTLSContext(peerValidationContext *dag.PeerValidationContext, sni string, alpnProtocols ...string) *envoy_api_v2_auth.UpstreamTlsContext { + context := &envoy_api_v2_auth.UpstreamTlsContext{ + CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ + AlpnProtocols: alpnProtocols, + }, + Sni: sni, + } + + if peerValidationContext.GetCACertificate() != nil && len(peerValidationContext.GetSubjectName()) > 0 { + // We have to explicitly assign the value from validationContext + // to context.CommonTlsContext.ValidationContextType because the + // latter is an interface. Returning nil from validationContext + // directly into this field boxes the nil into the unexported + // type of this grpc OneOf field which causes proto marshaling + // to explode later on. + vc := validationContext(peerValidationContext.GetCACertificate(), peerValidationContext.GetSubjectName()) + if vc != nil { + context.CommonTlsContext.ValidationContextType = vc + } + } + + return context +} + +func validationContext(ca []byte, subjectName string) *envoy_api_v2_auth.CommonTlsContext_ValidationContext { + vc := &envoy_api_v2_auth.CommonTlsContext_ValidationContext{ + ValidationContext: &envoy_api_v2_auth.CertificateValidationContext{ + TrustedCa: &envoy_api_v2_core.DataSource{ + // TODO(dfc) update this for SDS + Specifier: &envoy_api_v2_core.DataSource_InlineBytes{ + InlineBytes: ca, + }, + }, + }, + } + + if len(subjectName) > 0 { + vc.ValidationContext.MatchSubjectAltNames = []*matcher.StringMatcher{{ + MatchPattern: &matcher.StringMatcher_Exact{ + Exact: subjectName, + }}, + } + } + + return vc +} + +// DownstreamTLSContext creates a new DownstreamTlsContext. +func DownstreamTLSContext(serverSecret *dag.Secret, tlsMinProtoVersion envoy_api_v2_auth.TlsParameters_TlsProtocol, peerValidationContext *dag.PeerValidationContext, alpnProtos ...string) *envoy_api_v2_auth.DownstreamTlsContext { + context := &envoy_api_v2_auth.DownstreamTlsContext{ + CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ + TlsParams: &envoy_api_v2_auth.TlsParameters{ + TlsMinimumProtocolVersion: tlsMinProtoVersion, + TlsMaximumProtocolVersion: envoy_api_v2_auth.TlsParameters_TLSv1_3, + CipherSuites: envoy.Ciphers, + }, + TlsCertificateSdsSecretConfigs: []*envoy_api_v2_auth.SdsSecretConfig{{ + Name: envoy.Secretname(serverSecret), + SdsConfig: ConfigSource("contour"), + }}, + AlpnProtocols: alpnProtos, + }, + } + + if peerValidationContext.GetCACertificate() != nil { + vc := validationContext(peerValidationContext.GetCACertificate(), "") + if vc != nil { + context.CommonTlsContext.ValidationContextType = vc + context.RequireClientCertificate = protobuf.Bool(true) + } + } + + return context +} diff --git a/internal/envoy/auth_test.go b/internal/envoy/v2/auth_test.go similarity index 99% rename from internal/envoy/auth_test.go rename to internal/envoy/v2/auth_test.go index 467feefcad4..eca2d43c3e1 100644 --- a/internal/envoy/auth_test.go +++ b/internal/envoy/v2/auth_test.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package envoy +package v2 import ( "testing" diff --git a/internal/envoy/v2/bootstrap.go b/internal/envoy/v2/bootstrap.go new file mode 100644 index 00000000000..d2fba26cfe0 --- /dev/null +++ b/internal/envoy/v2/bootstrap.go @@ -0,0 +1,319 @@ +// 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 envoy contains APIs for translating between Contour +// objects and Envoy configuration APIs and types. + +package v2 + +import ( + "fmt" + "os" + "path" + "strconv" + "strings" + "time" + + api "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" + clusterv2 "github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster" + envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" + envoy_api_bootstrap "github.com/envoyproxy/go-control-plane/envoy/config/bootstrap/v2" + matcher "github.com/envoyproxy/go-control-plane/envoy/type/matcher" + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/ptypes/any" + "github.com/projectcontour/contour/internal/envoy" + "github.com/projectcontour/contour/internal/protobuf" +) + +// WriteBootstrap writes bootstrap configuration to files. +func WriteBootstrap(c *envoy.BootstrapConfig) error { + // Create Envoy bootstrap config and associated resource files. + steps, err := bootstrap(c) + if err != nil { + return err + } + + if c.ResourcesDir != "" { + if err := os.MkdirAll(path.Join(c.ResourcesDir, "sds"), 0750); err != nil { + return err + } + } + + // Write all configuration files out to filesystem. + for _, step := range steps { + if err := envoy.WriteConfig(step(c)); err != nil { + return err + } + } + + return nil +} + +type bootstrapf func(*envoy.BootstrapConfig) (string, proto.Message) + +// bootstrap creates a new v2 bootstrap configuration and associated resource files. +func bootstrap(c *envoy.BootstrapConfig) ([]bootstrapf, error) { + steps := []bootstrapf{} + + if c.GrpcClientCert == "" && c.GrpcClientKey == "" && c.GrpcCABundle == "" { + steps = append(steps, + func(*envoy.BootstrapConfig) (string, proto.Message) { + return c.Path, bootstrapConfig(c) + }) + + return steps, nil + } + + for _, f := range []string{c.GrpcClientCert, c.GrpcClientKey, c.GrpcCABundle} { + // If any of of the TLS options is not empty, they all must be not empty. + if f == "" { + return nil, fmt.Errorf( + "you must supply all TLS parameters - %q, %q, %q, or none of them", + "--envoy-cafile", "--envoy-cert-file", "--envoy-key-file") + } + + if !c.SkipFilePathCheck { + // If the TLS secrets aren't set up properly, + // some files may not be present. In this case, + // envoy will reject the bootstrap configuration, + // but there is no way to detect and fix that. If + // we check and fail here, that is visible in the + // Pod lifecycle and therefore fixable. + fi, err := os.Stat(f) + if err != nil { + return nil, err + } + if fi.Size() == 0 { + return nil, fmt.Errorf("%q is empty", f) + } + } + } + + if c.ResourcesDir == "" { + // For backwards compatibility, the old behavior + // is to use direct certificate and key file paths in + // bootstrap config. Envoy does not support rotation + // of xDS certificate files in this case. + + steps = append(steps, + func(*envoy.BootstrapConfig) (string, proto.Message) { + b := bootstrapConfig(c) + b.StaticResources.Clusters[0].TransportSocket = UpstreamTLSTransportSocket( + upstreamFileTLSContext(c)) + return c.Path, b + }) + + return steps, nil + } + + // xDS certificate rotation is supported by Envoy by using SDS path based resource files. + // These files are JSON representation of the SDS protobuf messages that normally get sent over the xDS connection, + // but for xDS connection itself, bootstrapping is done by storing the SDS resources in a local filesystem. + // Envoy will monitor and reload the resource files and the certificate and key files referred from the SDS resources. + // + // Two files are written to ResourcesDir: + // - SDS resource for xDS client certificate and key for authenticating Envoy towards Contour. + // - SDS resource for trusted CA certificate for validating Contour server certificate. + sdsTLSCertificatePath := path.Join(c.ResourcesDir, envoy.SdsResourcesSubdirectory, envoy.SdsTLSCertificateFile) + sdsValidationContextPath := path.Join(c.ResourcesDir, envoy.SdsResourcesSubdirectory, envoy.SdsValidationContextFile) + + steps = append(steps, + func(*envoy.BootstrapConfig) (string, proto.Message) { + return sdsTLSCertificatePath, tlsCertificateSdsSecretConfig(c) + }, + func(*envoy.BootstrapConfig) (string, proto.Message) { + return sdsValidationContextPath, validationContextSdsSecretConfig(c) + }, + func(*envoy.BootstrapConfig) (string, proto.Message) { + b := bootstrapConfig(c) + b.StaticResources.Clusters[0].TransportSocket = UpstreamTLSTransportSocket( + upstreamSdsTLSContext(sdsTLSCertificatePath, sdsValidationContextPath)) + return c.Path, b + }, + ) + + return steps, nil +} + +func bootstrapConfig(c *envoy.BootstrapConfig) *envoy_api_bootstrap.Bootstrap { + return &envoy_api_bootstrap.Bootstrap{ + DynamicResources: &envoy_api_bootstrap.Bootstrap_DynamicResources{ + LdsConfig: ConfigSource("contour"), + CdsConfig: ConfigSource("contour"), + }, + StaticResources: &envoy_api_bootstrap.Bootstrap_StaticResources{ + Clusters: []*api.Cluster{{ + Name: "contour", + AltStatName: strings.Join([]string{c.Namespace, "contour", strconv.Itoa(c.GetXdsGRPCPort())}, "_"), + ConnectTimeout: protobuf.Duration(5 * time.Second), + ClusterDiscoveryType: ClusterDiscoveryType(api.Cluster_STRICT_DNS), + LbPolicy: api.Cluster_ROUND_ROBIN, + LoadAssignment: &api.ClusterLoadAssignment{ + ClusterName: "contour", + Endpoints: Endpoints( + SocketAddress(c.GetXdsAddress(), c.GetXdsGRPCPort()), + ), + }, + UpstreamConnectionOptions: &api.UpstreamConnectionOptions{ + TcpKeepalive: &envoy_api_v2_core.TcpKeepalive{ + KeepaliveProbes: protobuf.UInt32(3), + KeepaliveTime: protobuf.UInt32(30), + KeepaliveInterval: protobuf.UInt32(5), + }, + }, + Http2ProtocolOptions: new(envoy_api_v2_core.Http2ProtocolOptions), // enables http2 + CircuitBreakers: &clusterv2.CircuitBreakers{ + Thresholds: []*clusterv2.CircuitBreakers_Thresholds{{ + Priority: envoy_api_v2_core.RoutingPriority_HIGH, + MaxConnections: protobuf.UInt32(100000), + MaxPendingRequests: protobuf.UInt32(100000), + MaxRequests: protobuf.UInt32(60000000), + MaxRetries: protobuf.UInt32(50), + }, { + Priority: envoy_api_v2_core.RoutingPriority_DEFAULT, + MaxConnections: protobuf.UInt32(100000), + MaxPendingRequests: protobuf.UInt32(100000), + MaxRequests: protobuf.UInt32(60000000), + MaxRetries: protobuf.UInt32(50), + }}, + }, + }, { + Name: "service-stats", + AltStatName: strings.Join([]string{c.Namespace, "service-stats", strconv.Itoa(c.GetAdminPort())}, "_"), + ConnectTimeout: protobuf.Duration(250 * time.Millisecond), + ClusterDiscoveryType: ClusterDiscoveryType(api.Cluster_LOGICAL_DNS), + LbPolicy: api.Cluster_ROUND_ROBIN, + LoadAssignment: &api.ClusterLoadAssignment{ + ClusterName: "service-stats", + Endpoints: Endpoints( + SocketAddress(c.GetAdminAddress(), c.GetAdminPort()), + ), + }, + }}, + }, + Admin: &envoy_api_bootstrap.Admin{ + AccessLogPath: c.GetAdminAccessLogPath(), + Address: SocketAddress(c.GetAdminAddress(), c.GetAdminPort()), + }, + } +} + +func upstreamFileTLSContext(c *envoy.BootstrapConfig) *envoy_api_v2_auth.UpstreamTlsContext { + context := &envoy_api_v2_auth.UpstreamTlsContext{ + CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ + TlsCertificates: []*envoy_api_v2_auth.TlsCertificate{{ + CertificateChain: &envoy_api_v2_core.DataSource{ + Specifier: &envoy_api_v2_core.DataSource_Filename{ + Filename: c.GrpcClientCert, + }, + }, + PrivateKey: &envoy_api_v2_core.DataSource{ + Specifier: &envoy_api_v2_core.DataSource_Filename{ + Filename: c.GrpcClientKey, + }, + }, + }}, + ValidationContextType: &envoy_api_v2_auth.CommonTlsContext_ValidationContext{ + ValidationContext: &envoy_api_v2_auth.CertificateValidationContext{ + TrustedCa: &envoy_api_v2_core.DataSource{ + Specifier: &envoy_api_v2_core.DataSource_Filename{ + Filename: c.GrpcCABundle, + }, + }, + // TODO(youngnick): Does there need to be a flag wired down to here? + MatchSubjectAltNames: []*matcher.StringMatcher{{ + MatchPattern: &matcher.StringMatcher_Exact{ + Exact: "contour", + }}, + }, + }, + }, + }, + } + return context +} + +func upstreamSdsTLSContext(certificateSdsFile, validationSdsFile string) *envoy_api_v2_auth.UpstreamTlsContext { + context := &envoy_api_v2_auth.UpstreamTlsContext{ + CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ + TlsCertificateSdsSecretConfigs: []*envoy_api_v2_auth.SdsSecretConfig{{ + SdsConfig: &envoy_api_v2_core.ConfigSource{ + ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_Path{ + Path: certificateSdsFile, + }, + }, + }}, + ValidationContextType: &envoy_api_v2_auth.CommonTlsContext_ValidationContextSdsSecretConfig{ + ValidationContextSdsSecretConfig: &envoy_api_v2_auth.SdsSecretConfig{ + SdsConfig: &envoy_api_v2_core.ConfigSource{ + ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_Path{ + Path: validationSdsFile, + }, + }, + }, + }, + }, + } + return context +} + +// tlsCertificateSdsSecretConfig creates DiscoveryResponse with file based SDS resource +// including paths to TLS certificates and key +func tlsCertificateSdsSecretConfig(c *envoy.BootstrapConfig) *api.DiscoveryResponse { + secret := &envoy_api_v2_auth.Secret{ + Type: &envoy_api_v2_auth.Secret_TlsCertificate{ + TlsCertificate: &envoy_api_v2_auth.TlsCertificate{ + CertificateChain: &envoy_api_v2_core.DataSource{ + Specifier: &envoy_api_v2_core.DataSource_Filename{ + Filename: c.GrpcClientCert, + }, + }, + PrivateKey: &envoy_api_v2_core.DataSource{ + Specifier: &envoy_api_v2_core.DataSource_Filename{ + Filename: c.GrpcClientKey, + }, + }, + }, + }, + } + + return &api.DiscoveryResponse{ + Resources: []*any.Any{protobuf.MustMarshalAny(secret)}, + } +} + +// validationContextSdsSecretConfig creates DiscoveryResponse with file based SDS resource +// including path to CA certificate bundle +func validationContextSdsSecretConfig(c *envoy.BootstrapConfig) *api.DiscoveryResponse { + secret := &envoy_api_v2_auth.Secret{ + Type: &envoy_api_v2_auth.Secret_ValidationContext{ + ValidationContext: &envoy_api_v2_auth.CertificateValidationContext{ + TrustedCa: &envoy_api_v2_core.DataSource{ + Specifier: &envoy_api_v2_core.DataSource_Filename{ + Filename: c.GrpcCABundle, + }, + }, + MatchSubjectAltNames: []*matcher.StringMatcher{{ + MatchPattern: &matcher.StringMatcher_Exact{ + Exact: "contour", + }}, + }, + }, + }, + } + + return &api.DiscoveryResponse{ + Resources: []*any.Any{protobuf.MustMarshalAny(secret)}, + } +} diff --git a/internal/envoy/bootstrap_test.go b/internal/envoy/v2/bootstrap_test.go similarity index 97% rename from internal/envoy/bootstrap_test.go rename to internal/envoy/v2/bootstrap_test.go index 8f82a9d3056..c700f87c5f9 100644 --- a/internal/envoy/bootstrap_test.go +++ b/internal/envoy/v2/bootstrap_test.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package envoy +package v2 import ( "path" @@ -21,20 +21,21 @@ import ( envoy_api_bootstrap "github.com/envoyproxy/go-control-plane/envoy/config/bootstrap/v2" "github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/proto" + "github.com/projectcontour/contour/internal/envoy" "github.com/projectcontour/contour/internal/protobuf" "github.com/stretchr/testify/assert" ) func TestBootstrap(t *testing.T) { tests := map[string]struct { - config BootstrapConfig + config envoy.BootstrapConfig wantedBootstrapConfig string wantedTLSCertificateConfig string wantedValidationContextConfig string wantedError bool }{ "default configuration": { - config: BootstrapConfig{ + config: envoy.BootstrapConfig{ Path: "envoy.json", Namespace: "testing-ns"}, wantedBootstrapConfig: `{ @@ -155,7 +156,7 @@ func TestBootstrap(t *testing.T) { }`, }, "--admin-address=8.8.8.8 --admin-port=9200": { - config: BootstrapConfig{ + config: envoy.BootstrapConfig{ Path: "envoy.json", AdminAddress: "8.8.8.8", AdminPort: 9200, @@ -279,7 +280,7 @@ func TestBootstrap(t *testing.T) { }`, }, "AdminAccessLogPath": { // TODO(dfc) doesn't appear to be exposed via contour bootstrap - config: BootstrapConfig{ + config: envoy.BootstrapConfig{ Path: "envoy.json", AdminAccessLogPath: "/var/log/admin.log", Namespace: "testing-ns", @@ -402,7 +403,7 @@ func TestBootstrap(t *testing.T) { }`, }, "--xds-address=8.8.8.8 --xds-port=9200": { - config: BootstrapConfig{ + config: envoy.BootstrapConfig{ Path: "envoy.json", XDSAddress: "8.8.8.8", XDSGRPCPort: 9200, @@ -526,7 +527,7 @@ func TestBootstrap(t *testing.T) { }`, }, "--stats-address=8.8.8.8 --stats-port=9200": { - config: BootstrapConfig{ + config: envoy.BootstrapConfig{ Path: "envoy.json", Namespace: "testing-ns", }, @@ -648,7 +649,7 @@ func TestBootstrap(t *testing.T) { }`, }, "--envoy-cafile=CA.cert --envoy-client-cert=client.cert --envoy-client-key=client.key": { - config: BootstrapConfig{ + config: envoy.BootstrapConfig{ Path: "envoy.json", Namespace: "testing-ns", GrpcCABundle: "CA.cert", @@ -802,7 +803,7 @@ func TestBootstrap(t *testing.T) { }`, }, "--resources-dir tmp --envoy-cafile=CA.cert --envoy-client-cert=client.cert --envoy-client-key=client.key": { - config: BootstrapConfig{ + config: envoy.BootstrapConfig{ Path: "envoy.json", Namespace: "testing-ns", ResourcesDir: "resources", @@ -981,7 +982,7 @@ func TestBootstrap(t *testing.T) { }`, }, "return error when not providing all certificate related parameters": { - config: BootstrapConfig{ + config: envoy.BootstrapConfig{ Path: "envoy.json", Namespace: "testing-ns", ResourcesDir: "resources", @@ -1002,8 +1003,8 @@ func TestBootstrap(t *testing.T) { gotConfigs[path] = config } - sdsTLSCertificatePath := path.Join(tc.config.ResourcesDir, sdsResourcesSubdirectory, sdsTLSCertificateFile) - sdsValidationContextPath := path.Join(tc.config.ResourcesDir, sdsResourcesSubdirectory, sdsValidationContextFile) + sdsTLSCertificatePath := path.Join(tc.config.ResourcesDir, envoy.SdsResourcesSubdirectory, envoy.SdsTLSCertificateFile) + sdsValidationContextPath := path.Join(tc.config.ResourcesDir, envoy.SdsResourcesSubdirectory, envoy.SdsValidationContextFile) if tc.wantedBootstrapConfig != "" { want := new(envoy_api_bootstrap.Bootstrap) diff --git a/internal/envoy/v2/cluster.go b/internal/envoy/v2/cluster.go new file mode 100644 index 00000000000..08f98af6d0a --- /dev/null +++ b/internal/envoy/v2/cluster.go @@ -0,0 +1,227 @@ +// 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 v2 + +import ( + // nolint:gosec + + "strings" + "time" + + v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_cluster "github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster" + envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" + envoy_type "github.com/envoyproxy/go-control-plane/envoy/type" + "github.com/projectcontour/contour/internal/dag" + "github.com/projectcontour/contour/internal/envoy" + "github.com/projectcontour/contour/internal/protobuf" + "github.com/projectcontour/contour/internal/xds" + "k8s.io/apimachinery/pkg/types" +) + +func clusterDefaults() *v2.Cluster { + return &v2.Cluster{ + ConnectTimeout: protobuf.Duration(250 * time.Millisecond), + CommonLbConfig: ClusterCommonLBConfig(), + LbPolicy: lbPolicy(""), + } +} + +// Cluster creates new v2.Cluster from dag.Cluster. +func Cluster(c *dag.Cluster) *v2.Cluster { + service := c.Upstream + cluster := clusterDefaults() + + cluster.Name = envoy.Clustername(c) + cluster.AltStatName = envoy.AltStatName(service) + cluster.LbPolicy = lbPolicy(c.LoadBalancerPolicy) + cluster.HealthChecks = edshealthcheck(c) + + switch len(service.ExternalName) { + case 0: + // external name not set, cluster will be discovered via EDS + cluster.ClusterDiscoveryType = ClusterDiscoveryType(v2.Cluster_EDS) + cluster.EdsClusterConfig = edsconfig("contour", service) + default: + // external name set, use hard coded DNS name + cluster.ClusterDiscoveryType = ClusterDiscoveryType(v2.Cluster_STRICT_DNS) + cluster.LoadAssignment = StaticClusterLoadAssignment(service) + } + + // Drain connections immediately if using healthchecks and the endpoint is known to be removed + if c.HTTPHealthCheckPolicy != nil || c.TCPHealthCheckPolicy != nil { + cluster.DrainConnectionsOnHostRemoval = true + } + + if envoy.AnyPositive(service.MaxConnections, service.MaxPendingRequests, service.MaxRequests, service.MaxRetries) { + cluster.CircuitBreakers = &envoy_cluster.CircuitBreakers{ + Thresholds: []*envoy_cluster.CircuitBreakers_Thresholds{{ + MaxConnections: protobuf.UInt32OrNil(service.MaxConnections), + MaxPendingRequests: protobuf.UInt32OrNil(service.MaxPendingRequests), + MaxRequests: protobuf.UInt32OrNil(service.MaxRequests), + MaxRetries: protobuf.UInt32OrNil(service.MaxRetries), + }}, + } + } + + switch c.Protocol { + case "tls": + cluster.TransportSocket = UpstreamTLSTransportSocket( + UpstreamTLSContext( + c.UpstreamValidation, + c.SNI, + ), + ) + case "h2": + cluster.Http2ProtocolOptions = &envoy_api_v2_core.Http2ProtocolOptions{} + cluster.TransportSocket = UpstreamTLSTransportSocket( + UpstreamTLSContext( + c.UpstreamValidation, + c.SNI, + "h2", + ), + ) + case "h2c": + cluster.Http2ProtocolOptions = &envoy_api_v2_core.Http2ProtocolOptions{} + } + + return cluster +} + +// ExtensionCluster builds a v2.Cluster struct for the given extension service. +func ExtensionCluster(ext *dag.ExtensionCluster) *v2.Cluster { + cluster := clusterDefaults() + + // The Envoy cluster name has already been set. + cluster.Name = ext.Name + + // The AltStatName was added to make a more readable alternative + // to the cluster name for metrics (see #827). For extension + // services, we can have multiple ports, so it doesn't make + // sense to build this the same way we build it for HTTPProxy + // service clusters. However, we know the namespaced name for + // the ExtensionCluster is globally unique, so we can use that + // to produce a stable, readable name. + cluster.AltStatName = strings.ReplaceAll(cluster.Name, "/", "_") + + cluster.LbPolicy = lbPolicy(ext.LoadBalancerPolicy) + + // Cluster will be discovered via EDS. + cluster.ClusterDiscoveryType = ClusterDiscoveryType(v2.Cluster_EDS) + cluster.EdsClusterConfig = &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: ext.Upstream.ClusterName, + } + + // TODO(jpeach): Externalname service support in https://github.com/projectcontour/contour/issues/2875 + + switch ext.Protocol { + case "h2": + cluster.Http2ProtocolOptions = &envoy_api_v2_core.Http2ProtocolOptions{} + cluster.TransportSocket = UpstreamTLSTransportSocket( + UpstreamTLSContext( + ext.UpstreamValidation, + ext.SNI, + "h2", + ), + ) + case "h2c": + cluster.Http2ProtocolOptions = &envoy_api_v2_core.Http2ProtocolOptions{} + } + + return cluster +} + +// StaticClusterLoadAssignment creates a *v2.ClusterLoadAssignment pointing to the external DNS address of the service +func StaticClusterLoadAssignment(service *dag.Service) *v2.ClusterLoadAssignment { + addr := SocketAddress(service.ExternalName, int(service.Weighted.ServicePort.Port)) + return &v2.ClusterLoadAssignment{ + Endpoints: Endpoints(addr), + ClusterName: xds.ClusterLoadAssignmentName( + types.NamespacedName{Name: service.Weighted.ServiceName, Namespace: service.Weighted.ServiceNamespace}, + service.Weighted.ServicePort.Name, + ), + } +} + +func edsconfig(cluster string, service *dag.Service) *v2.Cluster_EdsClusterConfig { + return &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource(cluster), + ServiceName: xds.ClusterLoadAssignmentName( + types.NamespacedName{Name: service.Weighted.ServiceName, Namespace: service.Weighted.ServiceNamespace}, + service.Weighted.ServicePort.Name, + ), + } +} + +func lbPolicy(strategy string) v2.Cluster_LbPolicy { + switch strategy { + case "WeightedLeastRequest": + return v2.Cluster_LEAST_REQUEST + case "Random": + return v2.Cluster_RANDOM + case "Cookie": + return v2.Cluster_RING_HASH + default: + return v2.Cluster_ROUND_ROBIN + } +} + +func edshealthcheck(c *dag.Cluster) []*envoy_api_v2_core.HealthCheck { + if c.HTTPHealthCheckPolicy == nil && c.TCPHealthCheckPolicy == nil { + return nil + } + + if c.HTTPHealthCheckPolicy != nil { + return []*envoy_api_v2_core.HealthCheck{ + httpHealthCheck(c), + } + } + + return []*envoy_api_v2_core.HealthCheck{ + tcpHealthCheck(c), + } +} + +// ClusterCommonLBConfig creates a *v2.Cluster_CommonLbConfig with HealthyPanicThreshold disabled. +func ClusterCommonLBConfig() *v2.Cluster_CommonLbConfig { + return &v2.Cluster_CommonLbConfig{ + HealthyPanicThreshold: &envoy_type.Percent{ // Disable HealthyPanicThreshold + Value: 0, + }, + } +} + +// ConfigSource returns a *envoy_api_v2_core.ConfigSource for cluster. +func ConfigSource(cluster string) *envoy_api_v2_core.ConfigSource { + return &envoy_api_v2_core.ConfigSource{ + ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ + ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ + ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, + GrpcServices: []*envoy_api_v2_core.GrpcService{{ + TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ + EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ + ClusterName: cluster, + }, + }, + }}, + }, + }, + } +} + +// ClusterDiscoveryType returns the type of a ClusterDiscovery as a Cluster_type. +func ClusterDiscoveryType(t v2.Cluster_DiscoveryType) *v2.Cluster_Type { + return &v2.Cluster_Type{Type: t} +} diff --git a/internal/envoy/v2/cluster_test.go b/internal/envoy/v2/cluster_test.go new file mode 100644 index 00000000000..c4a0c98bd15 --- /dev/null +++ b/internal/envoy/v2/cluster_test.go @@ -0,0 +1,584 @@ +// 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 v2 + +import ( + "testing" + "time" + + v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_cluster "github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster" + envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" + envoy_type "github.com/envoyproxy/go-control-plane/envoy/type" + "github.com/golang/protobuf/proto" + "github.com/projectcontour/contour/internal/dag" + "github.com/projectcontour/contour/internal/envoy" + "github.com/projectcontour/contour/internal/protobuf" + "github.com/projectcontour/contour/internal/xds" + "github.com/stretchr/testify/assert" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/intstr" +) + +func TestCluster(t *testing.T) { + s1 := &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kuard", + Namespace: "default", + }, + Spec: v1.ServiceSpec{ + Ports: []v1.ServicePort{{ + Name: "http", + Protocol: "TCP", + Port: 443, + TargetPort: intstr.FromInt(8080), + }}, + }, + } + + s2 := &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kuard", + Namespace: "default", + }, + Spec: v1.ServiceSpec{ + ExternalName: "foo.io", + Ports: []v1.ServicePort{{ + Name: "http", + Protocol: "TCP", + Port: 443, + TargetPort: intstr.FromInt(8080), + }}, + }, + } + + svcExternal := &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kuard", + Namespace: "default", + }, + Spec: v1.ServiceSpec{ + ExternalName: "projectcontour.local", + Ports: []v1.ServicePort{{ + Name: "http", + Protocol: "TCP", + Port: 443, + TargetPort: intstr.FromInt(8080), + }}, + Type: v1.ServiceTypeExternalName, + }, + } + + secret := &dag.Secret{ + Object: &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret", + Namespace: "default", + }, + Type: v1.SecretTypeTLS, + Data: map[string][]byte{dag.CACertificateKey: []byte("cacert")}, + }, + } + + tests := map[string]struct { + cluster *dag.Cluster + want *v2.Cluster + }{ + "simple service": { + cluster: &dag.Cluster{ + Upstream: service(s1), + }, + want: &v2.Cluster{ + Name: "default/kuard/443/da39a3ee5e", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), + EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: "default/kuard/http", + }, + }, + }, + "h2c upstream": { + cluster: &dag.Cluster{ + Upstream: service(s1, "h2c"), + Protocol: "h2c", + }, + want: &v2.Cluster{ + Name: "default/kuard/443/da39a3ee5e", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), + EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: "default/kuard/http", + }, + Http2ProtocolOptions: &envoy_api_v2_core.Http2ProtocolOptions{}, + }, + }, + "h2 upstream": { + cluster: &dag.Cluster{ + Upstream: service(s1, "h2"), + Protocol: "h2", + }, + want: &v2.Cluster{ + Name: "default/kuard/443/da39a3ee5e", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), + EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: "default/kuard/http", + }, + TransportSocket: UpstreamTLSTransportSocket( + UpstreamTLSContext(nil, "", "h2"), + ), + Http2ProtocolOptions: &envoy_api_v2_core.Http2ProtocolOptions{}, + }, + }, + "externalName service": { + cluster: &dag.Cluster{ + Upstream: service(s2), + }, + want: &v2.Cluster{ + Name: "default/kuard/443/da39a3ee5e", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_STRICT_DNS), + LoadAssignment: StaticClusterLoadAssignment(service(s2)), + }, + }, + "tls upstream": { + cluster: &dag.Cluster{ + Upstream: service(s1, "tls"), + Protocol: "tls", + }, + want: &v2.Cluster{ + Name: "default/kuard/443/da39a3ee5e", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), + EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: "default/kuard/http", + }, + TransportSocket: UpstreamTLSTransportSocket( + UpstreamTLSContext(nil, ""), + ), + }, + }, + "tls upstream - external name": { + cluster: &dag.Cluster{ + Upstream: service(svcExternal, "tls"), + Protocol: "tls", + SNI: "projectcontour.local", + }, + want: &v2.Cluster{ + Name: "default/kuard/443/da39a3ee5e", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_STRICT_DNS), + LoadAssignment: StaticClusterLoadAssignment(service(svcExternal, "tls")), + TransportSocket: UpstreamTLSTransportSocket( + UpstreamTLSContext(nil, "projectcontour.local"), + ), + }, + }, + "verify tls upstream with san": { + cluster: &dag.Cluster{ + Upstream: service(s1, "tls"), + Protocol: "tls", + UpstreamValidation: &dag.PeerValidationContext{ + CACertificate: secret, + SubjectName: "foo.bar.io", + }, + }, + want: &v2.Cluster{ + Name: "default/kuard/443/3ac4e90987", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), + EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: "default/kuard/http", + }, + TransportSocket: UpstreamTLSTransportSocket( + UpstreamTLSContext( + &dag.PeerValidationContext{ + CACertificate: secret, + SubjectName: "foo.bar.io", + }, + ""), + ), + }, + }, + "projectcontour.io/max-connections": { + cluster: &dag.Cluster{ + Upstream: &dag.Service{ + MaxConnections: 9000, + Weighted: dag.WeightedService{ + Weight: 1, + ServiceName: s1.Name, + ServiceNamespace: s1.Namespace, + ServicePort: s1.Spec.Ports[0], + }, + }, + }, + want: &v2.Cluster{ + Name: "default/kuard/443/da39a3ee5e", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), + EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: "default/kuard/http", + }, + CircuitBreakers: &envoy_cluster.CircuitBreakers{ + Thresholds: []*envoy_cluster.CircuitBreakers_Thresholds{{ + MaxConnections: protobuf.UInt32(9000), + }}, + }, + }, + }, + "projectcontour.io/max-pending-requests": { + cluster: &dag.Cluster{ + Upstream: &dag.Service{ + MaxPendingRequests: 4096, + Weighted: dag.WeightedService{ + Weight: 1, + ServiceName: s1.Name, + ServiceNamespace: s1.Namespace, + ServicePort: s1.Spec.Ports[0], + }, + }, + }, + want: &v2.Cluster{ + Name: "default/kuard/443/da39a3ee5e", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), + EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: "default/kuard/http", + }, + CircuitBreakers: &envoy_cluster.CircuitBreakers{ + Thresholds: []*envoy_cluster.CircuitBreakers_Thresholds{{ + MaxPendingRequests: protobuf.UInt32(4096), + }}, + }, + }, + }, + "projectcontour.io/max-requests": { + cluster: &dag.Cluster{ + Upstream: &dag.Service{ + MaxRequests: 404, + Weighted: dag.WeightedService{ + Weight: 1, + ServiceName: s1.Name, + ServiceNamespace: s1.Namespace, + ServicePort: s1.Spec.Ports[0], + }, + }, + }, + want: &v2.Cluster{ + Name: "default/kuard/443/da39a3ee5e", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), + EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: "default/kuard/http", + }, + CircuitBreakers: &envoy_cluster.CircuitBreakers{ + Thresholds: []*envoy_cluster.CircuitBreakers_Thresholds{{ + MaxRequests: protobuf.UInt32(404), + }}, + }, + }, + }, + "projectcontour.io/max-retries": { + cluster: &dag.Cluster{ + Upstream: &dag.Service{ + MaxRetries: 7, + Weighted: dag.WeightedService{ + Weight: 1, + ServiceName: s1.Name, + ServiceNamespace: s1.Namespace, + ServicePort: s1.Spec.Ports[0], + }, + }, + }, + want: &v2.Cluster{ + Name: "default/kuard/443/da39a3ee5e", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), + EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: "default/kuard/http", + }, + CircuitBreakers: &envoy_cluster.CircuitBreakers{ + Thresholds: []*envoy_cluster.CircuitBreakers_Thresholds{{ + MaxRetries: protobuf.UInt32(7), + }}, + }, + }, + }, + "cluster with random load balancer policy": { + cluster: &dag.Cluster{ + Upstream: service(s1), + LoadBalancerPolicy: "Random", + }, + want: &v2.Cluster{ + Name: "default/kuard/443/58d888c08a", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), + EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: "default/kuard/http", + }, + LbPolicy: v2.Cluster_RANDOM, + }, + }, + "cluster with cookie policy": { + cluster: &dag.Cluster{ + Upstream: service(s1), + LoadBalancerPolicy: "Cookie", + }, + want: &v2.Cluster{ + Name: "default/kuard/443/e4f81994fe", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), + EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: "default/kuard/http", + }, + LbPolicy: v2.Cluster_RING_HASH, + }, + }, + + "tcp service": { + cluster: &dag.Cluster{ + Upstream: service(s1), + }, + want: &v2.Cluster{ + Name: "default/kuard/443/da39a3ee5e", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), + EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: "default/kuard/http", + }, + }, + }, + "tcp service with healthcheck": { + cluster: &dag.Cluster{ + Upstream: service(s1), + TCPHealthCheckPolicy: &dag.TCPHealthCheckPolicy{ + Timeout: 2, + Interval: 10, + UnhealthyThreshold: 3, + HealthyThreshold: 2, + }, + }, + want: &v2.Cluster{ + Name: "default/kuard/443/da39a3ee5e", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(v2.Cluster_EDS), + EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: "default/kuard/http", + }, + DrainConnectionsOnHostRemoval: true, + HealthChecks: []*envoy_api_v2_core.HealthCheck{{ + Timeout: durationOrDefault(2, envoy.HCTimeout), + Interval: durationOrDefault(10, envoy.HCInterval), + UnhealthyThreshold: protobuf.UInt32OrDefault(3, envoy.HCUnhealthyThreshold), + HealthyThreshold: protobuf.UInt32OrDefault(2, envoy.HCHealthyThreshold), + HealthChecker: &envoy_api_v2_core.HealthCheck_TcpHealthCheck_{ + TcpHealthCheck: &envoy_api_v2_core.HealthCheck_TcpHealthCheck{}, + }, + }}, + }, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + got := Cluster(tc.cluster) + want := clusterDefaults() + + proto.Merge(want, tc.want) + + protobuf.ExpectEqual(t, want, got) + }) + } +} + +func TestClusterLoadAssignmentName(t *testing.T) { + assert.Equal(t, xds.ClusterLoadAssignmentName(types.NamespacedName{Namespace: "ns", Name: "svc"}, "port"), "ns/svc/port") + assert.Equal(t, xds.ClusterLoadAssignmentName(types.NamespacedName{Namespace: "ns", Name: "svc"}, ""), "ns/svc") + assert.Equal(t, xds.ClusterLoadAssignmentName(types.NamespacedName{}, ""), "/") +} + +func TestClustername(t *testing.T) { + tests := map[string]struct { + cluster *dag.Cluster + want string + }{ + "simple": { + cluster: &dag.Cluster{ + Upstream: &dag.Service{ + Weighted: dag.WeightedService{ + Weight: 1, + ServiceName: "backend", + ServiceNamespace: "default", + ServicePort: v1.ServicePort{ + Name: "http", + Protocol: "TCP", + Port: 80, + TargetPort: intstr.FromInt(6502), + }, + }, + }, + }, + want: "default/backend/80/da39a3ee5e", + }, + "far too long": { + cluster: &dag.Cluster{ + Upstream: &dag.Service{ + Weighted: dag.WeightedService{ + Weight: 1, + ServiceName: "must-be-in-want-of-a-wife", + ServiceNamespace: "it-is-a-truth-universally-acknowledged-that-a-single-man-in-possession-of-a-good-fortune", + ServicePort: v1.ServicePort{ + Name: "http", + Protocol: "TCP", + Port: 9999, + TargetPort: intstr.FromString("http-alt"), + }, + }, + }, + }, + want: "it-is-a--dea8b0/must-be--dea8b0/9999/da39a3ee5e", + }, + "various healthcheck params": { + cluster: &dag.Cluster{ + Upstream: &dag.Service{ + Weighted: dag.WeightedService{ + Weight: 1, + ServiceName: "backend", + ServiceNamespace: "default", + ServicePort: v1.ServicePort{ + Name: "http", + Protocol: "TCP", + Port: 80, + TargetPort: intstr.FromInt(6502), + }, + }, + }, + LoadBalancerPolicy: "Random", + HTTPHealthCheckPolicy: &dag.HTTPHealthCheckPolicy{ + Path: "/healthz", + Interval: 5 * time.Second, + Timeout: 30 * time.Second, + UnhealthyThreshold: 3, + HealthyThreshold: 1, + }, + }, + want: "default/backend/80/5c26077e1d", + }, + "upstream tls validation with subject alt name": { + cluster: &dag.Cluster{ + Upstream: &dag.Service{ + Weighted: dag.WeightedService{ + Weight: 1, + ServiceName: "backend", + ServiceNamespace: "default", + ServicePort: v1.ServicePort{ + Name: "http", + Protocol: "TCP", + Port: 80, + TargetPort: intstr.FromInt(6502), + }, + }, + }, + LoadBalancerPolicy: "Random", + UpstreamValidation: &dag.PeerValidationContext{ + CACertificate: &dag.Secret{ + Object: &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret", + Namespace: "default", + }, + Data: map[string][]byte{ + dag.CACertificateKey: []byte("somethingsecret"), + }, + }, + }, + SubjectName: "foo.com", + }, + }, + want: "default/backend/80/6bf46b7b3a", + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + got := envoy.Clustername(tc.cluster) + assert.Equal(t, tc.want, got) + }) + } +} + +func TestLBPolicy(t *testing.T) { + tests := map[string]v2.Cluster_LbPolicy{ + "WeightedLeastRequest": v2.Cluster_LEAST_REQUEST, + "Random": v2.Cluster_RANDOM, + "RoundRobin": v2.Cluster_ROUND_ROBIN, + "": v2.Cluster_ROUND_ROBIN, + "unknown": v2.Cluster_ROUND_ROBIN, + "Cookie": v2.Cluster_RING_HASH, + + // RingHash and Maglev were removed as options in 0.13. + // See #1150 + "RingHash": v2.Cluster_ROUND_ROBIN, + "Maglev": v2.Cluster_ROUND_ROBIN, + } + + for policy, want := range tests { + t.Run(policy, func(t *testing.T) { + got := lbPolicy(policy) + assert.Equal(t, want, got) + }) + } +} + +func TestClusterCommonLBConfig(t *testing.T) { + got := ClusterCommonLBConfig() + want := &v2.Cluster_CommonLbConfig{ + HealthyPanicThreshold: &envoy_type.Percent{ // Disable HealthyPanicThreshold + Value: 0, + }, + } + assert.Equal(t, want, got) +} + +func service(s *v1.Service, protocols ...string) *dag.Service { + protocol := "" + if len(protocols) > 0 { + protocol = protocols[0] + } + return &dag.Service{ + Weighted: dag.WeightedService{ + Weight: 1, + ServiceName: s.Name, + ServiceNamespace: s.Namespace, + ServicePort: s.Spec.Ports[0], + }, + ExternalName: s.Spec.ExternalName, + Protocol: protocol, + } +} diff --git a/internal/envoy/endpoint.go b/internal/envoy/v2/endpoint.go similarity index 99% rename from internal/envoy/endpoint.go rename to internal/envoy/v2/endpoint.go index a1b4906afb0..5c7783f682e 100644 --- a/internal/envoy/endpoint.go +++ b/internal/envoy/v2/endpoint.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package envoy +package v2 import ( v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" diff --git a/internal/envoy/endpoint_test.go b/internal/envoy/v2/endpoint_test.go similarity index 99% rename from internal/envoy/endpoint_test.go rename to internal/envoy/v2/endpoint_test.go index eb2b41e800f..d0a0c8a4abc 100644 --- a/internal/envoy/endpoint_test.go +++ b/internal/envoy/v2/endpoint_test.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package envoy +package v2 import ( "testing" diff --git a/internal/envoy/v2/healthcheck.go b/internal/envoy/v2/healthcheck.go new file mode 100644 index 00000000000..35e2e572c99 --- /dev/null +++ b/internal/envoy/v2/healthcheck.go @@ -0,0 +1,70 @@ +// 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 v2 + +import ( + "time" + + envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" + "github.com/golang/protobuf/ptypes/duration" + "github.com/projectcontour/contour/internal/dag" + "github.com/projectcontour/contour/internal/envoy" + "github.com/projectcontour/contour/internal/protobuf" +) + +// httpHealthCheck returns a *envoy_api_v2_core.HealthCheck value for HTTP Routes +func httpHealthCheck(cluster *dag.Cluster) *envoy_api_v2_core.HealthCheck { + hc := cluster.HTTPHealthCheckPolicy + host := envoy.HCHost + if hc.Host != "" { + host = hc.Host + } + + // TODO(dfc) why do we need to specify our own default, what is the default + // that envoy applies if these fields are left nil? + return &envoy_api_v2_core.HealthCheck{ + Timeout: durationOrDefault(hc.Timeout, envoy.HCTimeout), + Interval: durationOrDefault(hc.Interval, envoy.HCInterval), + UnhealthyThreshold: protobuf.UInt32OrDefault(hc.UnhealthyThreshold, envoy.HCUnhealthyThreshold), + HealthyThreshold: protobuf.UInt32OrDefault(hc.HealthyThreshold, envoy.HCHealthyThreshold), + HealthChecker: &envoy_api_v2_core.HealthCheck_HttpHealthCheck_{ + HttpHealthCheck: &envoy_api_v2_core.HealthCheck_HttpHealthCheck{ + Path: hc.Path, + Host: host, + }, + }, + } +} + +// tcpHealthCheck returns a *envoy_api_v2_core.HealthCheck value for TCPProxies +func tcpHealthCheck(cluster *dag.Cluster) *envoy_api_v2_core.HealthCheck { + hc := cluster.TCPHealthCheckPolicy + + return &envoy_api_v2_core.HealthCheck{ + Timeout: durationOrDefault(hc.Timeout, envoy.HCTimeout), + Interval: durationOrDefault(hc.Interval, envoy.HCInterval), + UnhealthyThreshold: protobuf.UInt32OrDefault(hc.UnhealthyThreshold, envoy.HCUnhealthyThreshold), + HealthyThreshold: protobuf.UInt32OrDefault(hc.HealthyThreshold, envoy.HCHealthyThreshold), + HealthChecker: &envoy_api_v2_core.HealthCheck_TcpHealthCheck_{ + TcpHealthCheck: &envoy_api_v2_core.HealthCheck_TcpHealthCheck{}, + }, + } +} + +func durationOrDefault(d, def time.Duration) *duration.Duration { + if d != 0 { + return protobuf.Duration(d) + } + return protobuf.Duration(def) +} diff --git a/internal/envoy/healthcheck_test.go b/internal/envoy/v2/healthcheck_test.go similarity index 91% rename from internal/envoy/healthcheck_test.go rename to internal/envoy/v2/healthcheck_test.go index 5f762f6b32c..06f650dc33f 100644 --- a/internal/envoy/healthcheck_test.go +++ b/internal/envoy/v2/healthcheck_test.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package envoy +package v2 import ( "testing" @@ -19,6 +19,7 @@ import ( envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" "github.com/projectcontour/contour/internal/dag" + "github.com/projectcontour/contour/internal/envoy" "github.com/projectcontour/contour/internal/protobuf" ) @@ -34,8 +35,8 @@ func TestHealthCheck(t *testing.T) { HTTPHealthCheckPolicy: new(dag.HTTPHealthCheckPolicy), }, want: &envoy_api_v2_core.HealthCheck{ - Timeout: protobuf.Duration(hcTimeout), - Interval: protobuf.Duration(hcInterval), + Timeout: protobuf.Duration(envoy.HCTimeout), + Interval: protobuf.Duration(envoy.HCInterval), UnhealthyThreshold: protobuf.UInt32(3), HealthyThreshold: protobuf.UInt32(2), HealthChecker: &envoy_api_v2_core.HealthCheck_HttpHealthCheck_{ @@ -53,8 +54,8 @@ func TestHealthCheck(t *testing.T) { }, }, want: &envoy_api_v2_core.HealthCheck{ - Timeout: protobuf.Duration(hcTimeout), - Interval: protobuf.Duration(hcInterval), + Timeout: protobuf.Duration(envoy.HCTimeout), + Interval: protobuf.Duration(envoy.HCInterval), UnhealthyThreshold: protobuf.UInt32(3), HealthyThreshold: protobuf.UInt32(2), HealthChecker: &envoy_api_v2_core.HealthCheck_HttpHealthCheck_{ diff --git a/internal/envoy/v2/listener.go b/internal/envoy/v2/listener.go new file mode 100644 index 00000000000..79441c7a6a2 --- /dev/null +++ b/internal/envoy/v2/listener.go @@ -0,0 +1,516 @@ +// 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 v2 + +import ( + "fmt" + "sort" + "strings" + "time" + + v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" + envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" + envoy_api_v2_listener "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener" + accesslog "github.com/envoyproxy/go-control-plane/envoy/config/filter/accesslog/v2" + envoy_config_filter_http_ext_authz_v2 "github.com/envoyproxy/go-control-plane/envoy/config/filter/http/ext_authz/v2" + lua "github.com/envoyproxy/go-control-plane/envoy/config/filter/http/lua/v2" + http "github.com/envoyproxy/go-control-plane/envoy/config/filter/network/http_connection_manager/v2" + tcp "github.com/envoyproxy/go-control-plane/envoy/config/filter/network/tcp_proxy/v2" + envoy_type "github.com/envoyproxy/go-control-plane/envoy/type" + "github.com/envoyproxy/go-control-plane/pkg/wellknown" + "github.com/projectcontour/contour/internal/dag" + "github.com/projectcontour/contour/internal/envoy" + "github.com/projectcontour/contour/internal/protobuf" + "github.com/projectcontour/contour/internal/sorter" + "github.com/projectcontour/contour/internal/timeout" +) + +// TLSInspector returns a new TLS inspector listener filter. +func TLSInspector() *envoy_api_v2_listener.ListenerFilter { + return &envoy_api_v2_listener.ListenerFilter{ + Name: wellknown.TlsInspector, + } +} + +// ProxyProtocol returns a new Proxy Protocol listener filter. +func ProxyProtocol() *envoy_api_v2_listener.ListenerFilter { + return &envoy_api_v2_listener.ListenerFilter{ + Name: wellknown.ProxyProtocol, + } +} + +// Listener returns a new v2.Listener for the supplied address, port, and filters. +func Listener(name, address string, port int, lf []*envoy_api_v2_listener.ListenerFilter, filters ...*envoy_api_v2_listener.Filter) *v2.Listener { + l := &v2.Listener{ + Name: name, + Address: SocketAddress(address, port), + ListenerFilters: lf, + SocketOptions: TCPKeepaliveSocketOptions(), + } + if len(filters) > 0 { + l.FilterChains = append( + l.FilterChains, + &envoy_api_v2_listener.FilterChain{ + Filters: filters, + }, + ) + } + return l +} + +type httpConnectionManagerBuilder struct { + routeConfigName string + metricsPrefix string + accessLoggers []*accesslog.AccessLog + requestTimeout timeout.Setting + connectionIdleTimeout timeout.Setting + streamIdleTimeout timeout.Setting + maxConnectionDuration timeout.Setting + connectionShutdownGracePeriod timeout.Setting + filters []*http.HttpFilter + codec envoy.HTTPVersionType // Note the zero value is AUTO, which is the default we want. +} + +// RouteConfigName sets the name of the RDS element that contains +// the routing table for this manager. +func (b *httpConnectionManagerBuilder) RouteConfigName(name string) *httpConnectionManagerBuilder { + b.routeConfigName = name + return b +} + +// MetricsPrefix sets the prefix used for emitting metrics from the +// connection manager. Note that this prefix is externally visible in +// monitoring tools, so it is subject to compatibility concerns. +// +// See https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/stats#config-http-conn-man-stats +func (b *httpConnectionManagerBuilder) MetricsPrefix(prefix string) *httpConnectionManagerBuilder { + b.metricsPrefix = prefix + return b +} + +// Codec sets the HTTP codec for the manager. The default is AUTO. +func (b *httpConnectionManagerBuilder) Codec(codecType envoy.HTTPVersionType) *httpConnectionManagerBuilder { + b.codec = codecType + return b +} + +// AccessLoggers sets the access logging configuration. +func (b *httpConnectionManagerBuilder) AccessLoggers(loggers []*accesslog.AccessLog) *httpConnectionManagerBuilder { + b.accessLoggers = loggers + return b +} + +// RequestTimeout sets the active request timeout on the connection manager. +func (b *httpConnectionManagerBuilder) RequestTimeout(timeout timeout.Setting) *httpConnectionManagerBuilder { + b.requestTimeout = timeout + return b +} + +// ConnectionIdleTimeout sets the idle timeout on the connection manager. +func (b *httpConnectionManagerBuilder) ConnectionIdleTimeout(timeout timeout.Setting) *httpConnectionManagerBuilder { + b.connectionIdleTimeout = timeout + return b +} + +// StreamIdleTimeout sets the stream idle timeout on the connection manager. +func (b *httpConnectionManagerBuilder) StreamIdleTimeout(timeout timeout.Setting) *httpConnectionManagerBuilder { + b.streamIdleTimeout = timeout + return b +} + +// MaxConnectionDuration sets the max connection duration on the connection manager. +func (b *httpConnectionManagerBuilder) MaxConnectionDuration(timeout timeout.Setting) *httpConnectionManagerBuilder { + b.maxConnectionDuration = timeout + return b +} + +// ConnectionShutdownGracePeriod sets the drain timeout on the connection manager. +func (b *httpConnectionManagerBuilder) ConnectionShutdownGracePeriod(timeout timeout.Setting) *httpConnectionManagerBuilder { + b.connectionShutdownGracePeriod = timeout + return b +} + +func (b *httpConnectionManagerBuilder) DefaultFilters() *httpConnectionManagerBuilder { + b.filters = append(b.filters, + &http.HttpFilter{ + Name: wellknown.Gzip, + }, + &http.HttpFilter{ + Name: wellknown.GRPCWeb, + }, + &http.HttpFilter{ + Name: wellknown.Router, + }, + ) + + return b +} + +// AddFilter appends f to the list of filters for this HTTPConnectionManager. f +// may by nil, in which case it is ignored. +func (b *httpConnectionManagerBuilder) AddFilter(f *http.HttpFilter) *httpConnectionManagerBuilder { + if f == nil { + return b + } + + if len(b.filters) > 0 { + lastIndex := len(b.filters) - 1 + // If the router filter is last, keep it at the end + // of the filter chain when we add the new filter. + if b.filters[lastIndex].Name == wellknown.Router { + b.filters = append(b.filters[:lastIndex], f, b.filters[lastIndex]) + return b + } + } + + b.filters = append(b.filters, f) + + return b +} + +// Validate runs builtin validation rules against the current builder state. +func (b *httpConnectionManagerBuilder) Validate() error { + filterNames := map[string]struct{}{} + + for _, f := range b.filters { + filterNames[f.Name] = struct{}{} + } + + // If there's no router filter, requests won't be forwarded. + if _, ok := filterNames[wellknown.Router]; !ok { + return fmt.Errorf("missing required filter %q", wellknown.Router) + } + + return nil +} + +// Get returns a new http.HttpConnectionManager filter, constructed +// from the builder settings. +// +// See https://www.envoyproxy.io/docs/envoy/latest/api-v2/config/filter/network/http_connection_manager/v2/http_connection_manager.proto.html +func (b *httpConnectionManagerBuilder) Get() *envoy_api_v2_listener.Filter { + // For now, failing validation is a programmer error that + // the caller can't reasonably recover from. A caller that can + // handle this should validate manually. + if err := b.Validate(); err != nil { + panic(err.Error()) + } + + cm := &http.HttpConnectionManager{ + CodecType: b.codec, + RouteSpecifier: &http.HttpConnectionManager_Rds{ + Rds: &http.Rds{ + RouteConfigName: b.routeConfigName, + ConfigSource: ConfigSource("contour"), + }, + }, + HttpFilters: b.filters, + CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{ + IdleTimeout: envoy.Timeout(b.connectionIdleTimeout), + }, + HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ + // Enable support for HTTP/1.0 requests that carry + // a Host: header. See #537. + AcceptHttp_10: true, + }, + UseRemoteAddress: protobuf.Bool(true), + NormalizePath: protobuf.Bool(true), + + // issue #1487 pass through X-Request-Id if provided. + PreserveExternalRequestId: true, + MergeSlashes: true, + + RequestTimeout: envoy.Timeout(b.requestTimeout), + StreamIdleTimeout: envoy.Timeout(b.streamIdleTimeout), + DrainTimeout: envoy.Timeout(b.connectionShutdownGracePeriod), + } + + // Max connection duration is infinite/disabled by default in Envoy, so if the timeout setting + // indicates to either disable or use default, don't pass a value at all. Note that unlike other + // Envoy timeouts, explicitly passing a 0 here *would not* disable the timeout; it needs to be + // omitted entirely. + if !b.maxConnectionDuration.IsDisabled() && !b.maxConnectionDuration.UseDefault() { + cm.CommonHttpProtocolOptions.MaxConnectionDuration = protobuf.Duration(b.maxConnectionDuration.Duration()) + } + + if len(b.accessLoggers) > 0 { + cm.AccessLog = b.accessLoggers + } + + // If there's no explicit metrics prefix, default it to the + // route config name. + if b.metricsPrefix != "" { + cm.StatPrefix = b.metricsPrefix + } else { + cm.StatPrefix = b.routeConfigName + } + + return &envoy_api_v2_listener.Filter{ + Name: wellknown.HTTPConnectionManager, + ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(cm), + }, + } +} + +// HTTPConnectionManager creates a new HTTP Connection Manager filter +// for the supplied route, access log, and client request timeout. +func HTTPConnectionManager(routename string, accesslogger []*accesslog.AccessLog, requestTimeout time.Duration) *envoy_api_v2_listener.Filter { + return HTTPConnectionManagerBuilder(). + RouteConfigName(routename). + MetricsPrefix(routename). + AccessLoggers(accesslogger). + RequestTimeout(timeout.DurationSetting(requestTimeout)). + DefaultFilters(). + Get() +} + +func HTTPConnectionManagerBuilder() *httpConnectionManagerBuilder { + return &httpConnectionManagerBuilder{} +} + +// TCPProxy creates a new TCPProxy filter. +func TCPProxy(statPrefix string, proxy *dag.TCPProxy, accesslogger []*accesslog.AccessLog) *envoy_api_v2_listener.Filter { + // Set the idle timeout in seconds for connections through a TCP Proxy type filter. + // The value of two and a half hours for reasons documented at + // https://github.com/projectcontour/contour/issues/1074 + // Set to 9001 because now it's OVER NINE THOUSAND. + idleTimeout := protobuf.Duration(9001 * time.Second) + + switch len(proxy.Clusters) { + case 1: + return &envoy_api_v2_listener.Filter{ + Name: wellknown.TCPProxy, + ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&tcp.TcpProxy{ + StatPrefix: statPrefix, + ClusterSpecifier: &tcp.TcpProxy_Cluster{ + Cluster: envoy.Clustername(proxy.Clusters[0]), + }, + AccessLog: accesslogger, + IdleTimeout: idleTimeout, + }), + }, + } + default: + var clusters []*tcp.TcpProxy_WeightedCluster_ClusterWeight + for _, c := range proxy.Clusters { + weight := c.Weight + if weight == 0 { + weight = 1 + } + clusters = append(clusters, &tcp.TcpProxy_WeightedCluster_ClusterWeight{ + Name: envoy.Clustername(c), + Weight: weight, + }) + } + sort.Stable(sorter.For(clusters)) + return &envoy_api_v2_listener.Filter{ + Name: wellknown.TCPProxy, + ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&tcp.TcpProxy{ + StatPrefix: statPrefix, + ClusterSpecifier: &tcp.TcpProxy_WeightedClusters{ + WeightedClusters: &tcp.TcpProxy_WeightedCluster{ + Clusters: clusters, + }, + }, + AccessLog: accesslogger, + IdleTimeout: idleTimeout, + }), + }, + } + } +} + +// SocketAddress creates a new TCP envoy_api_v2_core.Address. +func SocketAddress(address string, port int) *envoy_api_v2_core.Address { + if address == "::" { + return &envoy_api_v2_core.Address{ + Address: &envoy_api_v2_core.Address_SocketAddress{ + SocketAddress: &envoy_api_v2_core.SocketAddress{ + Protocol: envoy_api_v2_core.SocketAddress_TCP, + Address: address, + Ipv4Compat: true, + PortSpecifier: &envoy_api_v2_core.SocketAddress_PortValue{ + PortValue: uint32(port), + }, + }, + }, + } + } + return &envoy_api_v2_core.Address{ + Address: &envoy_api_v2_core.Address_SocketAddress{ + SocketAddress: &envoy_api_v2_core.SocketAddress{ + Protocol: envoy_api_v2_core.SocketAddress_TCP, + Address: address, + PortSpecifier: &envoy_api_v2_core.SocketAddress_PortValue{ + PortValue: uint32(port), + }, + }, + }, + } +} + +// Filters returns a []*envoy_api_v2_listener.Filter for the supplied filters. +func Filters(filters ...*envoy_api_v2_listener.Filter) []*envoy_api_v2_listener.Filter { + if len(filters) == 0 { + return nil + } + return filters +} + +// FilterChain retruns a *envoy_api_v2_listener.FilterChain for the supplied filters. +func FilterChain(filters ...*envoy_api_v2_listener.Filter) *envoy_api_v2_listener.FilterChain { + return &envoy_api_v2_listener.FilterChain{ + Filters: filters, + } +} + +// FilterChains returns a []*envoy_api_v2_listener.FilterChain for the supplied filters. +func FilterChains(filters ...*envoy_api_v2_listener.Filter) []*envoy_api_v2_listener.FilterChain { + if len(filters) == 0 { + return nil + } + return []*envoy_api_v2_listener.FilterChain{ + FilterChain(filters...), + } +} + +func FilterMisdirectedRequests(fqdn string) *http.HttpFilter { + // When Envoy matches on the virtual host domain, we configure + // it to match any port specifier (see envoy.VirtualHost), + // so the Host header (authority) may contain a port that + // should be ignored. This means that if we don't have a match, + // we should try again after stripping the port specifier. + + code := ` +function envoy_on_request(request_handle) + local headers = request_handle:headers() + local host = string.lower(headers:get(":authority")) + local target = "%s" + + if host ~= target then + s, e = string.find(host, ":", 1, true) + if s ~= nil then + host = string.sub(host, 1, s - 1) + end + + if host ~= target then + request_handle:respond( + {[":status"] = "421"}, + string.format("misdirected request to %%q", headers:get(":authority")) + ) + end + end +end + ` + + return &http.HttpFilter{ + Name: "envoy.filters.http.lua", + ConfigType: &http.HttpFilter_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&lua.Lua{ + InlineCode: fmt.Sprintf(code, strings.ToLower(fqdn)), + }), + }, + } +} + +// FilterExternalAuthz returns an `ext_authz` filter configured with the +// requested parameters. +func FilterExternalAuthz(authzClusterName string, failOpen bool, timeout timeout.Setting) *http.HttpFilter { + authConfig := envoy_config_filter_http_ext_authz_v2.ExtAuthz{ + Services: &envoy_config_filter_http_ext_authz_v2.ExtAuthz_GrpcService{ + GrpcService: &envoy_api_v2_core.GrpcService{ + TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ + EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ + ClusterName: authzClusterName, + }, + }, + Timeout: envoy.Timeout(timeout), + // We don't need to configure metadata here, since we allow + // operators to specify authorization context parameters at + // the virtual host and route. + InitialMetadata: []*envoy_api_v2_core.HeaderValue{}, + }, + }, + // Pretty sure we always want this. Why have an + // external auth service if it is not going to affect + // routing decisions? + ClearRouteCache: true, + FailureModeAllow: failOpen, + StatusOnError: &envoy_type.HttpStatus{ + Code: envoy_type.StatusCode_Forbidden, + }, + MetadataContextNamespaces: []string{}, + IncludePeerCertificate: true, + } + + // TODO(jpeach): When we move to the Envoy v3 API, propagate the + // `transport_api_version` from ExtensionServiceSpec ProtocolVersion. + + return &http.HttpFilter{ + Name: "envoy.filters.http.ext_authz", + ConfigType: &http.HttpFilter_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&authConfig), + }, + } +} + +// FilterChainTLS returns a TLS enabled envoy_api_v2_listener.FilterChain. +func FilterChainTLS(domain string, downstream *envoy_api_v2_auth.DownstreamTlsContext, filters []*envoy_api_v2_listener.Filter) *envoy_api_v2_listener.FilterChain { + fc := &envoy_api_v2_listener.FilterChain{ + Filters: filters, + FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ + ServerNames: []string{domain}, + }, + } + // Attach TLS data to this listener if provided. + if downstream != nil { + fc.TransportSocket = DownstreamTLSTransportSocket(downstream) + + } + return fc +} + +// FilterChainTLSFallback returns a TLS enabled envoy_api_v2_listener.FilterChain conifgured for FallbackCertificate. +func FilterChainTLSFallback(downstream *envoy_api_v2_auth.DownstreamTlsContext, filters []*envoy_api_v2_listener.Filter) *envoy_api_v2_listener.FilterChain { + fc := &envoy_api_v2_listener.FilterChain{ + Name: "fallback-certificate", + Filters: filters, + FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ + TransportProtocol: "tls", + }, + } + // Attach TLS data to this listener if provided. + if downstream != nil { + fc.TransportSocket = DownstreamTLSTransportSocket(downstream) + } + return fc +} + +// ListenerFilters returns a []*envoy_api_v2_listener.ListenerFilter for the supplied listener filters. +func ListenerFilters(filters ...*envoy_api_v2_listener.ListenerFilter) []*envoy_api_v2_listener.ListenerFilter { + return filters +} + +func ContainsFallbackFilterChain(filterchains []*envoy_api_v2_listener.FilterChain) bool { + for _, fc := range filterchains { + if fc.Name == "fallback-certificate" { + return true + } + } + return false +} diff --git a/internal/envoy/v2/listener_test.go b/internal/envoy/v2/listener_test.go new file mode 100644 index 00000000000..68f6c22b3b4 --- /dev/null +++ b/internal/envoy/v2/listener_test.go @@ -0,0 +1,797 @@ +// 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 v2 + +import ( + "testing" + "time" + + v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" + envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" + envoy_api_v2_listener "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener" + envoy_api_v2_accesslog "github.com/envoyproxy/go-control-plane/envoy/config/filter/accesslog/v2" + http "github.com/envoyproxy/go-control-plane/envoy/config/filter/network/http_connection_manager/v2" + envoy_config_v2_tcpproxy "github.com/envoyproxy/go-control-plane/envoy/config/filter/network/tcp_proxy/v2" + "github.com/envoyproxy/go-control-plane/pkg/wellknown" + "github.com/projectcontour/contour/internal/dag" + "github.com/projectcontour/contour/internal/envoy" + "github.com/projectcontour/contour/internal/protobuf" + "github.com/projectcontour/contour/internal/timeout" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +func TestListener(t *testing.T) { + tests := map[string]struct { + name, address string + port int + lf []*envoy_api_v2_listener.ListenerFilter + f []*envoy_api_v2_listener.Filter + want *v2.Listener + }{ + "insecure listener": { + name: "http", + address: "0.0.0.0", + port: 9000, + f: []*envoy_api_v2_listener.Filter{ + HTTPConnectionManager("http", FileAccessLogEnvoy("/dev/null"), 0), + }, + want: &v2.Listener{ + Name: "http", + Address: SocketAddress("0.0.0.0", 9000), + FilterChains: FilterChains( + HTTPConnectionManager("http", FileAccessLogEnvoy("/dev/null"), 0), + ), + SocketOptions: TCPKeepaliveSocketOptions(), + }, + }, + "insecure listener w/ proxy": { + name: "http-proxy", + address: "0.0.0.0", + port: 9000, + lf: []*envoy_api_v2_listener.ListenerFilter{ + ProxyProtocol(), + }, + f: []*envoy_api_v2_listener.Filter{ + HTTPConnectionManager("http-proxy", FileAccessLogEnvoy("/dev/null"), 0), + }, + want: &v2.Listener{ + Name: "http-proxy", + Address: SocketAddress("0.0.0.0", 9000), + ListenerFilters: ListenerFilters( + ProxyProtocol(), + ), + FilterChains: FilterChains( + HTTPConnectionManager("http-proxy", FileAccessLogEnvoy("/dev/null"), 0), + ), + SocketOptions: TCPKeepaliveSocketOptions(), + }, + }, + "secure listener": { + name: "https", + address: "0.0.0.0", + port: 9000, + lf: ListenerFilters( + TLSInspector(), + ), + want: &v2.Listener{ + Name: "https", + Address: SocketAddress("0.0.0.0", 9000), + ListenerFilters: ListenerFilters( + TLSInspector(), + ), + SocketOptions: TCPKeepaliveSocketOptions(), + }, + }, + "secure listener w/ proxy": { + name: "https-proxy", + address: "0.0.0.0", + port: 9000, + lf: ListenerFilters( + ProxyProtocol(), + TLSInspector(), + ), + want: &v2.Listener{ + Name: "https-proxy", + Address: SocketAddress("0.0.0.0", 9000), + ListenerFilters: ListenerFilters( + ProxyProtocol(), + TLSInspector(), + ), + SocketOptions: TCPKeepaliveSocketOptions(), + }, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + got := Listener(tc.name, tc.address, tc.port, tc.lf, tc.f...) + protobuf.ExpectEqual(t, tc.want, got) + }) + } +} + +func TestSocketAddress(t *testing.T) { + const ( + addr = "foo.example.com" + port = 8123 + ) + + got := SocketAddress(addr, port) + want := &envoy_api_v2_core.Address{ + Address: &envoy_api_v2_core.Address_SocketAddress{ + SocketAddress: &envoy_api_v2_core.SocketAddress{ + Protocol: envoy_api_v2_core.SocketAddress_TCP, + Address: addr, + PortSpecifier: &envoy_api_v2_core.SocketAddress_PortValue{ + PortValue: port, + }, + }, + }, + } + require.Equal(t, want, got) + + got = SocketAddress("::", port) + want = &envoy_api_v2_core.Address{ + Address: &envoy_api_v2_core.Address_SocketAddress{ + SocketAddress: &envoy_api_v2_core.SocketAddress{ + Protocol: envoy_api_v2_core.SocketAddress_TCP, + Address: "::", + Ipv4Compat: true, // Set only for ipv6-any "::" + PortSpecifier: &envoy_api_v2_core.SocketAddress_PortValue{ + PortValue: port, + }, + }, + }, + } + assert.Equal(t, want, got) +} + +func TestDownstreamTLSContext(t *testing.T) { + const subjectName = "client-subject-name" + ca := []byte("client-ca-cert") + + serverSecret := &dag.Secret{ + Object: &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "tls-cert", + Namespace: "default", + }, + Data: map[string][]byte{ + v1.TLSCertKey: []byte("cert"), + v1.TLSPrivateKeyKey: []byte("key"), + }, + }, + } + + tlsParams := &envoy_api_v2_auth.TlsParameters{ + TlsMinimumProtocolVersion: envoy_api_v2_auth.TlsParameters_TLSv1_1, + TlsMaximumProtocolVersion: envoy_api_v2_auth.TlsParameters_TLSv1_3, + CipherSuites: []string{ + "[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]", + "[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]", + "ECDHE-ECDSA-AES128-SHA", + "ECDHE-RSA-AES128-SHA", + "ECDHE-ECDSA-AES256-GCM-SHA384", + "ECDHE-RSA-AES256-GCM-SHA384", + "ECDHE-ECDSA-AES256-SHA", + "ECDHE-RSA-AES256-SHA", + }, + } + + tlsCertificateSdsSecretConfigs := []*envoy_api_v2_auth.SdsSecretConfig{{ + Name: envoy.Secretname(serverSecret), + SdsConfig: &envoy_api_v2_core.ConfigSource{ + ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ + ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ + ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, + GrpcServices: []*envoy_api_v2_core.GrpcService{{ + TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ + EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ + ClusterName: "contour", + }, + }, + }}, + }, + }, + }, + }} + + alpnProtocols := []string{"h2", "http/1.1"} + validationContext := &envoy_api_v2_auth.CommonTlsContext_ValidationContext{ + ValidationContext: &envoy_api_v2_auth.CertificateValidationContext{ + TrustedCa: &envoy_api_v2_core.DataSource{ + Specifier: &envoy_api_v2_core.DataSource_InlineBytes{ + InlineBytes: ca, + }, + }, + }, + } + + peerValidationContext := &dag.PeerValidationContext{ + CACertificate: &dag.Secret{ + Object: &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret", + Namespace: "default", + }, + Data: map[string][]byte{ + dag.CACertificateKey: ca, + }, + }, + }, + } + + // Negative test case: downstream validation should not contain subjectname. + peerValidationContextWithSubjectName := &dag.PeerValidationContext{ + CACertificate: &dag.Secret{ + Object: &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret", + Namespace: "default", + }, + Data: map[string][]byte{ + dag.CACertificateKey: ca, + }, + }, + }, + SubjectName: subjectName, + } + + tests := map[string]struct { + got *envoy_api_v2_auth.DownstreamTlsContext + want *envoy_api_v2_auth.DownstreamTlsContext + }{ + "TLS context without client authentication": { + DownstreamTLSContext(serverSecret, envoy_api_v2_auth.TlsParameters_TLSv1_1, nil, "h2", "http/1.1"), + &envoy_api_v2_auth.DownstreamTlsContext{ + CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ + TlsParams: tlsParams, + TlsCertificateSdsSecretConfigs: tlsCertificateSdsSecretConfigs, + AlpnProtocols: alpnProtocols, + }, + }, + }, + "TLS context with client authentication": { + DownstreamTLSContext(serverSecret, envoy_api_v2_auth.TlsParameters_TLSv1_1, peerValidationContext, "h2", "http/1.1"), + &envoy_api_v2_auth.DownstreamTlsContext{ + CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ + TlsParams: tlsParams, + TlsCertificateSdsSecretConfigs: tlsCertificateSdsSecretConfigs, + AlpnProtocols: alpnProtocols, + ValidationContextType: validationContext, + }, + RequireClientCertificate: protobuf.Bool(true), + }, + }, + "Downstream validation shall not support subjectName validation": { + DownstreamTLSContext(serverSecret, envoy_api_v2_auth.TlsParameters_TLSv1_1, peerValidationContextWithSubjectName, "h2", "http/1.1"), + &envoy_api_v2_auth.DownstreamTlsContext{ + CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ + TlsParams: tlsParams, + TlsCertificateSdsSecretConfigs: tlsCertificateSdsSecretConfigs, + AlpnProtocols: alpnProtocols, + ValidationContextType: validationContext, + }, + RequireClientCertificate: protobuf.Bool(true), + }, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + protobuf.ExpectEqual(t, tc.want, tc.got) + }) + } +} + +func TestHTTPConnectionManager(t *testing.T) { + tests := map[string]struct { + routename string + accesslogger []*envoy_api_v2_accesslog.AccessLog + requestTimeout timeout.Setting + connectionIdleTimeout timeout.Setting + streamIdleTimeout timeout.Setting + maxConnectionDuration timeout.Setting + connectionShutdownGracePeriod timeout.Setting + want *envoy_api_v2_listener.Filter + }{ + "default": { + routename: "default/kuard", + accesslogger: FileAccessLogEnvoy("/dev/stdout"), + want: &envoy_api_v2_listener.Filter{ + Name: wellknown.HTTPConnectionManager, + ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&http.HttpConnectionManager{ + StatPrefix: "default/kuard", + RouteSpecifier: &http.HttpConnectionManager_Rds{ + Rds: &http.Rds{ + RouteConfigName: "default/kuard", + ConfigSource: &envoy_api_v2_core.ConfigSource{ + ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ + ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ + ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, + GrpcServices: []*envoy_api_v2_core.GrpcService{{ + TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ + EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ + ClusterName: "contour", + }, + }, + }}, + }, + }, + }, + }, + }, + HttpFilters: []*http.HttpFilter{{ + Name: wellknown.Gzip, + }, { + Name: wellknown.GRPCWeb, + }, { + Name: wellknown.Router, + }}, + HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ + // Enable support for HTTP/1.0 requests that carry + // a Host: header. See #537. + AcceptHttp_10: true, + }, + CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{}, + AccessLog: FileAccessLogEnvoy("/dev/stdout"), + UseRemoteAddress: protobuf.Bool(true), + NormalizePath: protobuf.Bool(true), + PreserveExternalRequestId: true, + MergeSlashes: true, + }), + }, + }, + }, + "request timeout of 10s": { + routename: "default/kuard", + accesslogger: FileAccessLogEnvoy("/dev/stdout"), + requestTimeout: timeout.DurationSetting(10 * time.Second), + want: &envoy_api_v2_listener.Filter{ + Name: wellknown.HTTPConnectionManager, + ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&http.HttpConnectionManager{ + StatPrefix: "default/kuard", + RouteSpecifier: &http.HttpConnectionManager_Rds{ + Rds: &http.Rds{ + RouteConfigName: "default/kuard", + ConfigSource: &envoy_api_v2_core.ConfigSource{ + ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ + ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ + ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, + GrpcServices: []*envoy_api_v2_core.GrpcService{{ + TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ + EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ + ClusterName: "contour", + }, + }, + }}, + }, + }, + }, + }, + }, + HttpFilters: []*http.HttpFilter{{ + Name: wellknown.Gzip, + }, { + Name: wellknown.GRPCWeb, + }, { + Name: wellknown.Router, + }}, + HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ + // Enable support for HTTP/1.0 requests that carry + // a Host: header. See #537. + AcceptHttp_10: true, + }, + CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{}, + AccessLog: FileAccessLogEnvoy("/dev/stdout"), + UseRemoteAddress: protobuf.Bool(true), + NormalizePath: protobuf.Bool(true), + RequestTimeout: protobuf.Duration(10 * time.Second), + PreserveExternalRequestId: true, + MergeSlashes: true, + }), + }, + }, + }, + "connection idle timeout of 90s": { + routename: "default/kuard", + accesslogger: FileAccessLogEnvoy("/dev/stdout"), + connectionIdleTimeout: timeout.DurationSetting(90 * time.Second), + want: &envoy_api_v2_listener.Filter{ + Name: wellknown.HTTPConnectionManager, + ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&http.HttpConnectionManager{ + StatPrefix: "default/kuard", + RouteSpecifier: &http.HttpConnectionManager_Rds{ + Rds: &http.Rds{ + RouteConfigName: "default/kuard", + ConfigSource: &envoy_api_v2_core.ConfigSource{ + ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ + ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ + ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, + GrpcServices: []*envoy_api_v2_core.GrpcService{{ + TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ + EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ + ClusterName: "contour", + }, + }, + }}, + }, + }, + }, + }, + }, + HttpFilters: []*http.HttpFilter{{ + Name: wellknown.Gzip, + }, { + Name: wellknown.GRPCWeb, + }, { + Name: wellknown.Router, + }}, + HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ + // Enable support for HTTP/1.0 requests that carry + // a Host: header. See #537. + AcceptHttp_10: true, + }, + CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{ + IdleTimeout: protobuf.Duration(90 * time.Second), + }, + AccessLog: FileAccessLogEnvoy("/dev/stdout"), + UseRemoteAddress: protobuf.Bool(true), + NormalizePath: protobuf.Bool(true), + PreserveExternalRequestId: true, + MergeSlashes: true, + }), + }, + }, + }, + "stream idle timeout of 90s": { + routename: "default/kuard", + accesslogger: FileAccessLogEnvoy("/dev/stdout"), + streamIdleTimeout: timeout.DurationSetting(90 * time.Second), + want: &envoy_api_v2_listener.Filter{ + Name: wellknown.HTTPConnectionManager, + ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&http.HttpConnectionManager{ + StatPrefix: "default/kuard", + RouteSpecifier: &http.HttpConnectionManager_Rds{ + Rds: &http.Rds{ + RouteConfigName: "default/kuard", + ConfigSource: &envoy_api_v2_core.ConfigSource{ + ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ + ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ + ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, + GrpcServices: []*envoy_api_v2_core.GrpcService{{ + TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ + EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ + ClusterName: "contour", + }, + }, + }}, + }, + }, + }, + }, + }, + HttpFilters: []*http.HttpFilter{{ + Name: wellknown.Gzip, + }, { + Name: wellknown.GRPCWeb, + }, { + Name: wellknown.Router, + }}, + HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ + // Enable support for HTTP/1.0 requests that carry + // a Host: header. See #537. + AcceptHttp_10: true, + }, + CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{}, + AccessLog: FileAccessLogEnvoy("/dev/stdout"), + UseRemoteAddress: protobuf.Bool(true), + NormalizePath: protobuf.Bool(true), + PreserveExternalRequestId: true, + MergeSlashes: true, + StreamIdleTimeout: protobuf.Duration(90 * time.Second), + }), + }, + }, + }, + "max connection duration of 90s": { + routename: "default/kuard", + accesslogger: FileAccessLogEnvoy("/dev/stdout"), + maxConnectionDuration: timeout.DurationSetting(90 * time.Second), + want: &envoy_api_v2_listener.Filter{ + Name: wellknown.HTTPConnectionManager, + ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&http.HttpConnectionManager{ + StatPrefix: "default/kuard", + RouteSpecifier: &http.HttpConnectionManager_Rds{ + Rds: &http.Rds{ + RouteConfigName: "default/kuard", + ConfigSource: &envoy_api_v2_core.ConfigSource{ + ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ + ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ + ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, + GrpcServices: []*envoy_api_v2_core.GrpcService{{ + TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ + EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ + ClusterName: "contour", + }, + }, + }}, + }, + }, + }, + }, + }, + HttpFilters: []*http.HttpFilter{{ + Name: wellknown.Gzip, + }, { + Name: wellknown.GRPCWeb, + }, { + Name: wellknown.Router, + }}, + HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ + // Enable support for HTTP/1.0 requests that carry + // a Host: header. See #537. + AcceptHttp_10: true, + }, + CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{ + MaxConnectionDuration: protobuf.Duration(90 * time.Second), + }, + AccessLog: FileAccessLogEnvoy("/dev/stdout"), + UseRemoteAddress: protobuf.Bool(true), + NormalizePath: protobuf.Bool(true), + PreserveExternalRequestId: true, + MergeSlashes: true, + }), + }, + }, + }, + "when max connection duration is disabled, it's omitted": { + routename: "default/kuard", + accesslogger: FileAccessLogEnvoy("/dev/stdout"), + maxConnectionDuration: timeout.DisabledSetting(), + want: &envoy_api_v2_listener.Filter{ + Name: wellknown.HTTPConnectionManager, + ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&http.HttpConnectionManager{ + StatPrefix: "default/kuard", + RouteSpecifier: &http.HttpConnectionManager_Rds{ + Rds: &http.Rds{ + RouteConfigName: "default/kuard", + ConfigSource: &envoy_api_v2_core.ConfigSource{ + ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ + ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ + ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, + GrpcServices: []*envoy_api_v2_core.GrpcService{{ + TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ + EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ + ClusterName: "contour", + }, + }, + }}, + }, + }, + }, + }, + }, + HttpFilters: []*http.HttpFilter{{ + Name: wellknown.Gzip, + }, { + Name: wellknown.GRPCWeb, + }, { + Name: wellknown.Router, + }}, + HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ + // Enable support for HTTP/1.0 requests that carry + // a Host: header. See #537. + AcceptHttp_10: true, + }, + CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{}, + AccessLog: FileAccessLogEnvoy("/dev/stdout"), + UseRemoteAddress: protobuf.Bool(true), + NormalizePath: protobuf.Bool(true), + PreserveExternalRequestId: true, + MergeSlashes: true, + }), + }, + }, + }, + "drain timeout of 90s": { + routename: "default/kuard", + accesslogger: FileAccessLogEnvoy("/dev/stdout"), + connectionShutdownGracePeriod: timeout.DurationSetting(90 * time.Second), + want: &envoy_api_v2_listener.Filter{ + Name: wellknown.HTTPConnectionManager, + ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&http.HttpConnectionManager{ + StatPrefix: "default/kuard", + RouteSpecifier: &http.HttpConnectionManager_Rds{ + Rds: &http.Rds{ + RouteConfigName: "default/kuard", + ConfigSource: &envoy_api_v2_core.ConfigSource{ + ConfigSourceSpecifier: &envoy_api_v2_core.ConfigSource_ApiConfigSource{ + ApiConfigSource: &envoy_api_v2_core.ApiConfigSource{ + ApiType: envoy_api_v2_core.ApiConfigSource_GRPC, + GrpcServices: []*envoy_api_v2_core.GrpcService{{ + TargetSpecifier: &envoy_api_v2_core.GrpcService_EnvoyGrpc_{ + EnvoyGrpc: &envoy_api_v2_core.GrpcService_EnvoyGrpc{ + ClusterName: "contour", + }, + }, + }}, + }, + }, + }, + }, + }, + HttpFilters: []*http.HttpFilter{{ + Name: wellknown.Gzip, + }, { + Name: wellknown.GRPCWeb, + }, { + Name: wellknown.Router, + }}, + HttpProtocolOptions: &envoy_api_v2_core.Http1ProtocolOptions{ + // Enable support for HTTP/1.0 requests that carry + // a Host: header. See #537. + AcceptHttp_10: true, + }, + CommonHttpProtocolOptions: &envoy_api_v2_core.HttpProtocolOptions{}, + AccessLog: FileAccessLogEnvoy("/dev/stdout"), + UseRemoteAddress: protobuf.Bool(true), + NormalizePath: protobuf.Bool(true), + PreserveExternalRequestId: true, + MergeSlashes: true, + DrainTimeout: protobuf.Duration(90 * time.Second), + }), + }, + }, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + got := HTTPConnectionManagerBuilder(). + RouteConfigName(tc.routename). + MetricsPrefix(tc.routename). + AccessLoggers(tc.accesslogger). + RequestTimeout(tc.requestTimeout). + ConnectionIdleTimeout(tc.connectionIdleTimeout). + StreamIdleTimeout(tc.streamIdleTimeout). + MaxConnectionDuration(tc.maxConnectionDuration). + ConnectionShutdownGracePeriod(tc.connectionShutdownGracePeriod). + DefaultFilters(). + Get() + + protobuf.ExpectEqual(t, tc.want, got) + }) + } +} + +func TestTCPProxy(t *testing.T) { + const ( + statPrefix = "ingress_https" + accessLogPath = "/dev/stdout" + ) + + c1 := &dag.Cluster{ + Upstream: &dag.Service{ + Weighted: dag.WeightedService{ + Weight: 1, + ServiceName: "example", + ServiceNamespace: "default", + ServicePort: v1.ServicePort{ + Protocol: "TCP", + Port: 443, + TargetPort: intstr.FromInt(8443), + }, + }, + }, + } + c2 := &dag.Cluster{ + Upstream: &dag.Service{ + Weighted: dag.WeightedService{ + ServiceName: "example2", + ServiceNamespace: "default", + ServicePort: v1.ServicePort{ + Protocol: "TCP", + Port: 443, + TargetPort: intstr.FromInt(8443), + }, + }, + }, + Weight: 20, + } + + tests := map[string]struct { + proxy *dag.TCPProxy + want *envoy_api_v2_listener.Filter + }{ + "single cluster": { + proxy: &dag.TCPProxy{ + Clusters: []*dag.Cluster{c1}, + }, + want: &envoy_api_v2_listener.Filter{ + Name: wellknown.TCPProxy, + ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&envoy_config_v2_tcpproxy.TcpProxy{ + StatPrefix: statPrefix, + ClusterSpecifier: &envoy_config_v2_tcpproxy.TcpProxy_Cluster{ + Cluster: envoy.Clustername(c1), + }, + AccessLog: FileAccessLogEnvoy(accessLogPath), + IdleTimeout: protobuf.Duration(9001 * time.Second), + }), + }, + }, + }, + "multiple cluster": { + proxy: &dag.TCPProxy{ + Clusters: []*dag.Cluster{c2, c1}, + }, + want: &envoy_api_v2_listener.Filter{ + Name: wellknown.TCPProxy, + ConfigType: &envoy_api_v2_listener.Filter_TypedConfig{ + TypedConfig: protobuf.MustMarshalAny(&envoy_config_v2_tcpproxy.TcpProxy{ + StatPrefix: statPrefix, + ClusterSpecifier: &envoy_config_v2_tcpproxy.TcpProxy_WeightedClusters{ + WeightedClusters: &envoy_config_v2_tcpproxy.TcpProxy_WeightedCluster{ + Clusters: []*envoy_config_v2_tcpproxy.TcpProxy_WeightedCluster_ClusterWeight{{ + Name: envoy.Clustername(c1), + Weight: 1, + }, { + Name: envoy.Clustername(c2), + Weight: 20, + }}, + }, + }, + AccessLog: FileAccessLogEnvoy(accessLogPath), + IdleTimeout: protobuf.Duration(9001 * time.Second), + }), + }, + }, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + got := TCPProxy(statPrefix, tc.proxy, FileAccessLogEnvoy(accessLogPath)) + protobuf.ExpectEqual(t, tc.want, got) + }) + } +} + +// TestBuilderValidation tests that validation checks that +// DefaultFilters adds the required HTTP connection manager filters. +func TestBuilderValidation(t *testing.T) { + if err := HTTPConnectionManagerBuilder().Validate(); err == nil { + t.Errorf("ConnectionManager with no filters passed validation") + } + + if err := HTTPConnectionManagerBuilder().AddFilter(&http.HttpFilter{Name: "foo"}).Validate(); err == nil { + t.Errorf("ConnectionManager with no filters passed validation") + } + + if err := HTTPConnectionManagerBuilder().DefaultFilters().Validate(); err != nil { + t.Errorf("ConnectionManager with default filters failed validation: %s", err) + } +} diff --git a/internal/envoy/v2/route.go b/internal/envoy/v2/route.go new file mode 100644 index 00000000000..13993341b59 --- /dev/null +++ b/internal/envoy/v2/route.go @@ -0,0 +1,314 @@ +// 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 v2 + +import ( + "fmt" + "regexp" + "sort" + + v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" + envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" + envoy_config_filter_http_ext_authz_v2 "github.com/envoyproxy/go-control-plane/envoy/config/filter/http/ext_authz/v2" + "github.com/golang/protobuf/ptypes/any" + wrappers "github.com/golang/protobuf/ptypes/wrappers" + "github.com/projectcontour/contour/internal/dag" + "github.com/projectcontour/contour/internal/envoy" + "github.com/projectcontour/contour/internal/protobuf" + "github.com/projectcontour/contour/internal/sorter" +) + +// RouteAuthzDisabled returns a per-route config to disable authorization. +func RouteAuthzDisabled() *any.Any { + return protobuf.MustMarshalAny( + &envoy_config_filter_http_ext_authz_v2.ExtAuthzPerRoute{ + Override: &envoy_config_filter_http_ext_authz_v2.ExtAuthzPerRoute_Disabled{ + Disabled: true, + }, + }, + ) +} + +// RouteAuthzContext returns a per-route config to pass the given +// context entries in the check request. +func RouteAuthzContext(settings map[string]string) *any.Any { + return protobuf.MustMarshalAny( + &envoy_config_filter_http_ext_authz_v2.ExtAuthzPerRoute{ + Override: &envoy_config_filter_http_ext_authz_v2.ExtAuthzPerRoute_CheckSettings{ + CheckSettings: &envoy_config_filter_http_ext_authz_v2.CheckSettings{ + ContextExtensions: settings, + }, + }, + }, + ) +} + +// RouteMatch creates a *envoy_api_v2_route.RouteMatch for the supplied *dag.Route. +func RouteMatch(route *dag.Route) *envoy_api_v2_route.RouteMatch { + switch c := route.PathMatchCondition.(type) { + case *dag.RegexMatchCondition: + return &envoy_api_v2_route.RouteMatch{ + PathSpecifier: &envoy_api_v2_route.RouteMatch_SafeRegex{ + SafeRegex: envoy.SafeRegexMatch(c.Regex), + }, + Headers: headerMatcher(route.HeaderMatchConditions), + } + case *dag.PrefixMatchCondition: + return &envoy_api_v2_route.RouteMatch{ + PathSpecifier: &envoy_api_v2_route.RouteMatch_Prefix{ + Prefix: c.Prefix, + }, + Headers: headerMatcher(route.HeaderMatchConditions), + } + default: + return &envoy_api_v2_route.RouteMatch{ + Headers: headerMatcher(route.HeaderMatchConditions), + } + } +} + +// RouteRoute creates a *envoy_api_v2_route.Route_Route for the services supplied. +// If len(services) is greater than one, the route's action will be a +// weighted cluster. +func RouteRoute(r *dag.Route) *envoy_api_v2_route.Route_Route { + ra := envoy_api_v2_route.RouteAction{ + RetryPolicy: retryPolicy(r), + Timeout: envoy.Timeout(r.TimeoutPolicy.ResponseTimeout), + IdleTimeout: envoy.Timeout(r.TimeoutPolicy.IdleTimeout), + PrefixRewrite: r.PrefixRewrite, + HashPolicy: hashPolicy(r), + RequestMirrorPolicies: mirrorPolicy(r), + } + + // Check for host header policy and set if found + if val := envoy.HostReplaceHeader(r.RequestHeadersPolicy); val != "" { + ra.HostRewriteSpecifier = &envoy_api_v2_route.RouteAction_HostRewrite{ + HostRewrite: val, + } + } + + if r.Websocket { + ra.UpgradeConfigs = append(ra.UpgradeConfigs, + &envoy_api_v2_route.RouteAction_UpgradeConfig{ + UpgradeType: "websocket", + }, + ) + } + + if envoy.SingleSimpleCluster(r.Clusters) { + ra.ClusterSpecifier = &envoy_api_v2_route.RouteAction_Cluster{ + Cluster: envoy.Clustername(r.Clusters[0]), + } + } else { + ra.ClusterSpecifier = &envoy_api_v2_route.RouteAction_WeightedClusters{ + WeightedClusters: weightedClusters(r.Clusters), + } + } + return &envoy_api_v2_route.Route_Route{ + Route: &ra, + } +} + +// hashPolicy returns a slice of hash policies iff at least one of the route's +// clusters supplied uses the `Cookie` load balancing strategy. +func hashPolicy(r *dag.Route) []*envoy_api_v2_route.RouteAction_HashPolicy { + for _, c := range r.Clusters { + if c.LoadBalancerPolicy == "Cookie" { + return []*envoy_api_v2_route.RouteAction_HashPolicy{{ + PolicySpecifier: &envoy_api_v2_route.RouteAction_HashPolicy_Cookie_{ + Cookie: &envoy_api_v2_route.RouteAction_HashPolicy_Cookie{ + Name: "X-Contour-Session-Affinity", + Ttl: protobuf.Duration(0), + Path: "/", + }, + }, + }} + } + } + return nil +} + +func mirrorPolicy(r *dag.Route) []*envoy_api_v2_route.RouteAction_RequestMirrorPolicy { + if r.MirrorPolicy == nil { + return nil + } + + return []*envoy_api_v2_route.RouteAction_RequestMirrorPolicy{{ + Cluster: envoy.Clustername(r.MirrorPolicy.Cluster), + }} +} + +func retryPolicy(r *dag.Route) *envoy_api_v2_route.RetryPolicy { + if r.RetryPolicy == nil { + return nil + } + if r.RetryPolicy.RetryOn == "" { + return nil + } + + rp := &envoy_api_v2_route.RetryPolicy{ + RetryOn: r.RetryPolicy.RetryOn, + RetriableStatusCodes: r.RetryPolicy.RetriableStatusCodes, + } + if r.RetryPolicy.NumRetries > 0 { + rp.NumRetries = protobuf.UInt32(r.RetryPolicy.NumRetries) + } + rp.PerTryTimeout = envoy.Timeout(r.RetryPolicy.PerTryTimeout) + + return rp +} + +// UpgradeHTTPS returns a route Action that redirects the request to HTTPS. +func UpgradeHTTPS() *envoy_api_v2_route.Route_Redirect { + return &envoy_api_v2_route.Route_Redirect{ + Redirect: &envoy_api_v2_route.RedirectAction{ + SchemeRewriteSpecifier: &envoy_api_v2_route.RedirectAction_HttpsRedirect{ + HttpsRedirect: true, + }, + }, + } +} + +// HeaderValueList creates a list of Envoy HeaderValueOptions from the provided map. +func HeaderValueList(hvm map[string]string, app bool) []*envoy_api_v2_core.HeaderValueOption { + var hvs []*envoy_api_v2_core.HeaderValueOption + + for key, value := range hvm { + hvs = append(hvs, &envoy_api_v2_core.HeaderValueOption{ + Header: &envoy_api_v2_core.HeaderValue{ + Key: key, + Value: value, + }, + Append: &wrappers.BoolValue{ + Value: app, + }, + }) + } + + sort.Slice(hvs, func(i, j int) bool { + return hvs[i].Header.Key < hvs[j].Header.Key + }) + + return hvs +} + +// weightedClusters returns a route.WeightedCluster for multiple services. +func weightedClusters(clusters []*dag.Cluster) *envoy_api_v2_route.WeightedCluster { + var wc envoy_api_v2_route.WeightedCluster + var total uint32 + for _, cluster := range clusters { + total += cluster.Weight + + c := &envoy_api_v2_route.WeightedCluster_ClusterWeight{ + Name: envoy.Clustername(cluster), + Weight: protobuf.UInt32(cluster.Weight), + } + if cluster.RequestHeadersPolicy != nil { + c.RequestHeadersToAdd = HeaderValueList(cluster.RequestHeadersPolicy.Set, false) + c.RequestHeadersToRemove = cluster.RequestHeadersPolicy.Remove + } + if cluster.ResponseHeadersPolicy != nil { + c.ResponseHeadersToAdd = HeaderValueList(cluster.ResponseHeadersPolicy.Set, false) + c.ResponseHeadersToRemove = cluster.ResponseHeadersPolicy.Remove + } + wc.Clusters = append(wc.Clusters, c) + } + // Check if no weights were defined, if not default to even distribution + if total == 0 { + for _, c := range wc.Clusters { + c.Weight.Value = 1 + } + total = uint32(len(clusters)) + } + wc.TotalWeight = protobuf.UInt32(total) + + sort.Stable(sorter.For(wc.Clusters)) + return &wc +} + +// VirtualHost creates a new route.VirtualHost. +func VirtualHost(hostname string, routes ...*envoy_api_v2_route.Route) *envoy_api_v2_route.VirtualHost { + domains := []string{hostname} + if hostname != "*" { + // NOTE(jpeach) see also envoy.FilterMisdirectedRequests(). + domains = append(domains, hostname+":*") + } + + return &envoy_api_v2_route.VirtualHost{ + Name: envoy.Hashname(60, hostname), + Domains: domains, + Routes: routes, + } +} + +// RouteConfiguration returns a *v2.RouteConfiguration. +func RouteConfiguration(name string, virtualhosts ...*envoy_api_v2_route.VirtualHost) *v2.RouteConfiguration { + return &v2.RouteConfiguration{ + Name: name, + VirtualHosts: virtualhosts, + RequestHeadersToAdd: Headers( + AppendHeader("x-request-start", "t=%START_TIME(%s.%3f)%"), + ), + } +} + +func Headers(first *envoy_api_v2_core.HeaderValueOption, rest ...*envoy_api_v2_core.HeaderValueOption) []*envoy_api_v2_core.HeaderValueOption { + return append([]*envoy_api_v2_core.HeaderValueOption{first}, rest...) +} + +func AppendHeader(key, value string) *envoy_api_v2_core.HeaderValueOption { + return &envoy_api_v2_core.HeaderValueOption{ + Header: &envoy_api_v2_core.HeaderValue{ + Key: key, + Value: value, + }, + Append: protobuf.Bool(true), + } +} + +func headerMatcher(headers []dag.HeaderMatchCondition) []*envoy_api_v2_route.HeaderMatcher { + var envoyHeaders []*envoy_api_v2_route.HeaderMatcher + + for _, h := range headers { + header := &envoy_api_v2_route.HeaderMatcher{ + Name: h.Name, + InvertMatch: h.Invert, + } + + switch h.MatchType { + case "exact": + header.HeaderMatchSpecifier = &envoy_api_v2_route.HeaderMatcher_ExactMatch{ExactMatch: h.Value} + case "contains": + header.HeaderMatchSpecifier = containsMatch(h.Value) + case "present": + header.HeaderMatchSpecifier = &envoy_api_v2_route.HeaderMatcher_PresentMatch{PresentMatch: true} + } + envoyHeaders = append(envoyHeaders, header) + } + return envoyHeaders +} + +// containsMatch returns a HeaderMatchSpecifier which will match the +// supplied substring +func containsMatch(s string) *envoy_api_v2_route.HeaderMatcher_SafeRegexMatch { + // convert the substring s into a regular expression that matches s. + // note that Envoy expects the expression to match the entire string, not just the substring + // formed from s. see [projectcontour/contour/#1751 & envoyproxy/envoy#8283] + regex := fmt.Sprintf(".*%s.*", regexp.QuoteMeta(s)) + + return &envoy_api_v2_route.HeaderMatcher_SafeRegexMatch{ + SafeRegexMatch: envoy.SafeRegexMatch(regex), + } +} diff --git a/internal/envoy/route_test.go b/internal/envoy/v2/route_test.go similarity index 98% rename from internal/envoy/route_test.go rename to internal/envoy/v2/route_test.go index e11c8e5ef65..e589b294b0e 100644 --- a/internal/envoy/route_test.go +++ b/internal/envoy/v2/route_test.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package envoy +package v2 import ( "testing" @@ -22,6 +22,7 @@ import ( envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" "github.com/golang/protobuf/ptypes/wrappers" "github.com/projectcontour/contour/internal/dag" + "github.com/projectcontour/contour/internal/envoy" "github.com/projectcontour/contour/internal/fixture" "github.com/projectcontour/contour/internal/protobuf" "github.com/projectcontour/contour/internal/timeout" @@ -766,7 +767,7 @@ func TestRouteMatch(t *testing.T) { Name: "x-header", InvertMatch: false, HeaderMatchSpecifier: &envoy_api_v2_route.HeaderMatcher_SafeRegexMatch{ - SafeRegexMatch: SafeRegexMatch(".*11-22-33-44.*"), + SafeRegexMatch: envoy.SafeRegexMatch(".*11-22-33-44.*"), }, }}, }, @@ -785,7 +786,7 @@ func TestRouteMatch(t *testing.T) { Name: "x-header", InvertMatch: false, HeaderMatchSpecifier: &envoy_api_v2_route.HeaderMatcher_SafeRegexMatch{ - SafeRegexMatch: SafeRegexMatch(".*11\\.22\\.33\\.44.*"), + SafeRegexMatch: envoy.SafeRegexMatch(".*11\\.22\\.33\\.44.*"), }, }}, }, @@ -804,7 +805,7 @@ func TestRouteMatch(t *testing.T) { Name: "x-header", InvertMatch: false, HeaderMatchSpecifier: &envoy_api_v2_route.HeaderMatcher_SafeRegexMatch{ - SafeRegexMatch: SafeRegexMatch(".*11\\.\\[22\\]\\.\\*33\\.44.*"), + SafeRegexMatch: envoy.SafeRegexMatch(".*11\\.\\[22\\]\\.\\*33\\.44.*"), }, }}, }, @@ -832,7 +833,7 @@ func TestRouteMatch(t *testing.T) { // note, unlike header conditions this is not a quoted regex because // the value comes directly from the Ingress.Paths.Path value which // is permitted to be a bare regex. - SafeRegex: SafeRegexMatch("/v.1/*"), + SafeRegex: envoy.SafeRegexMatch("/v.1/*"), }, }, }, diff --git a/internal/envoy/v2/secret.go b/internal/envoy/v2/secret.go new file mode 100644 index 00000000000..64f1e9d84b6 --- /dev/null +++ b/internal/envoy/v2/secret.go @@ -0,0 +1,44 @@ +// 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 v2 + +import ( + // nolint:gosec + + envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" + envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" + "github.com/projectcontour/contour/internal/dag" + "github.com/projectcontour/contour/internal/envoy" +) + +// Secret creates new envoy_api_v2_auth.Secret from secret. +func Secret(s *dag.Secret) *envoy_api_v2_auth.Secret { + return &envoy_api_v2_auth.Secret{ + Name: envoy.Secretname(s), + Type: &envoy_api_v2_auth.Secret_TlsCertificate{ + TlsCertificate: &envoy_api_v2_auth.TlsCertificate{ + PrivateKey: &envoy_api_v2_core.DataSource{ + Specifier: &envoy_api_v2_core.DataSource_InlineBytes{ + InlineBytes: s.PrivateKey(), + }, + }, + CertificateChain: &envoy_api_v2_core.DataSource{ + Specifier: &envoy_api_v2_core.DataSource_InlineBytes{ + InlineBytes: s.Cert(), + }, + }, + }, + }, + } +} diff --git a/internal/envoy/secret_test.go b/internal/envoy/v2/secret_test.go similarity index 96% rename from internal/envoy/secret_test.go rename to internal/envoy/v2/secret_test.go index 810646a720b..4f413a4de21 100644 --- a/internal/envoy/secret_test.go +++ b/internal/envoy/v2/secret_test.go @@ -11,11 +11,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -package envoy +package v2 import ( "testing" + "github.com/projectcontour/contour/internal/envoy" + envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" "github.com/projectcontour/contour/internal/dag" @@ -110,7 +112,7 @@ func TestSecretname(t *testing.T) { for name, tc := range tests { t.Run(name, func(t *testing.T) { - got := Secretname(tc.secret) + got := envoy.Secretname(tc.secret) assert.Equal(t, tc.want, got) }) } diff --git a/internal/envoy/socket.go b/internal/envoy/v2/socket.go similarity index 99% rename from internal/envoy/socket.go rename to internal/envoy/v2/socket.go index 93ed67198cb..ae1a2f4ffc5 100644 --- a/internal/envoy/socket.go +++ b/internal/envoy/v2/socket.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package envoy +package v2 import ( envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" diff --git a/internal/envoy/socket_test.go b/internal/envoy/v2/socket_test.go similarity index 99% rename from internal/envoy/socket_test.go rename to internal/envoy/v2/socket_test.go index b347fc289c7..6e8bcda9850 100644 --- a/internal/envoy/socket_test.go +++ b/internal/envoy/v2/socket_test.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package envoy +package v2 import ( "testing" diff --git a/internal/envoy/stats.go b/internal/envoy/v2/stats.go similarity index 99% rename from internal/envoy/stats.go rename to internal/envoy/v2/stats.go index 4f7738b7a88..74dd7acee77 100644 --- a/internal/envoy/stats.go +++ b/internal/envoy/v2/stats.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package envoy +package v2 import ( v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" diff --git a/internal/envoy/stats_test.go b/internal/envoy/v2/stats_test.go similarity index 99% rename from internal/envoy/stats_test.go rename to internal/envoy/v2/stats_test.go index e35b2d779aa..4289ff0f948 100644 --- a/internal/envoy/stats_test.go +++ b/internal/envoy/v2/stats_test.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package envoy +package v2 import ( "testing" diff --git a/internal/envoy/v2/tcp_keepalive.go b/internal/envoy/v2/tcp_keepalive.go new file mode 100644 index 00000000000..c26f4e35d44 --- /dev/null +++ b/internal/envoy/v2/tcp_keepalive.go @@ -0,0 +1,62 @@ +// 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 v2 + +import ( + envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" + "github.com/projectcontour/contour/internal/envoy" +) + +func TCPKeepaliveSocketOptions() []*envoy_api_v2_core.SocketOption { + + // Note: TCP_KEEPIDLE + (TCP_KEEPINTVL * TCP_KEEPCNT) must be greater than + // the grpc.KeepaliveParams time + timeout (currently 60 + 20 = 80 seconds) + // otherwise TestGRPC/StreamClusters fails. + return []*envoy_api_v2_core.SocketOption{ + // Enable TCP keep-alive. + { + Description: "Enable TCP keep-alive", + Level: envoy.SOL_SOCKET, + Name: envoy.SO_KEEPALIVE, + Value: &envoy_api_v2_core.SocketOption_IntValue{IntValue: 1}, + State: envoy_api_v2_core.SocketOption_STATE_LISTENING, + }, + // The time (in seconds) the connection needs to remain idle + // before TCP starts sending keepalive probes. + { + Description: "TCP keep-alive initial idle time", + Level: envoy.IPPROTO_TCP, + Name: envoy.TCP_KEEPIDLE, + Value: &envoy_api_v2_core.SocketOption_IntValue{IntValue: 45}, + State: envoy_api_v2_core.SocketOption_STATE_LISTENING, + }, + // The time (in seconds) between individual keepalive probes. + { + Description: "TCP keep-alive time between probes", + Level: envoy.IPPROTO_TCP, + Name: envoy.TCP_KEEPINTVL, + Value: &envoy_api_v2_core.SocketOption_IntValue{IntValue: 5}, + State: envoy_api_v2_core.SocketOption_STATE_LISTENING, + }, + // The maximum number of TCP keep-alive probes to send before + // giving up and killing the connection if no response is + // obtained from the other end. + { + Description: "TCP keep-alive probe count", + Level: envoy.IPPROTO_TCP, + Name: envoy.TCP_KEEPCNT, + Value: &envoy_api_v2_core.SocketOption_IntValue{IntValue: 9}, + State: envoy_api_v2_core.SocketOption_STATE_LISTENING, + }, + } +} diff --git a/internal/featuretests/authorization_test.go b/internal/featuretests/authorization_test.go index 29d992675ac..9818f966163 100644 --- a/internal/featuretests/authorization_test.go +++ b/internal/featuretests/authorization_test.go @@ -18,7 +18,7 @@ import ( "testing" "time" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" envoy_api_v2_listener "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" @@ -26,7 +26,7 @@ import ( envoy_type "github.com/envoyproxy/go-control-plane/envoy/type" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/apis/projectcontour/v1alpha1" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" "github.com/projectcontour/contour/internal/k8s" "github.com/projectcontour/contour/internal/protobuf" @@ -70,15 +70,15 @@ func authzResponseTimeout(t *testing.T, rh cache.ResourceEventHandler, c *Contou cluster := grpcCluster("extension/auth/extension") cluster.GrpcService.Timeout = protobuf.Duration(10 * time.Minute) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: resources(t, defaultHTTPListener(), - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ filterchaintls(fqdn, @@ -100,7 +100,7 @@ func authzResponseTimeout(t *testing.T, rh cache.ResourceEventHandler, c *Contou ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener()), }).Status(p).Like(projcontour.HTTPProxyStatus{ @@ -132,7 +132,7 @@ func authzInvalidResponseTimeout(t *testing.T, rh cache.ResourceEventHandler, c cluster := grpcCluster("extension/auth/extension") cluster.GrpcService.Timeout = protobuf.Duration(10 * time.Minute) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: resources(t, staticListener()), }).Status(p).Equals(projcontour.HTTPProxyStatus{ @@ -162,15 +162,15 @@ func authzFailOpen(t *testing.T, rh cache.ResourceEventHandler, c *Contour) { rh.OnAdd(p) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: resources(t, defaultHTTPListener(), - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ filterchaintls(fqdn, @@ -193,7 +193,7 @@ func authzFailOpen(t *testing.T, rh cache.ResourceEventHandler, c *Contour) { ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener()), }).Status(p).Like(projcontour.HTTPProxyStatus{ @@ -221,7 +221,7 @@ func authzFallbackIncompat(t *testing.T, rh cache.ResourceEventHandler, c *Conto rh.OnAdd(p) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: resources(t, staticListener()), }).Status(p).Equals(projcontour.HTTPProxyStatus{ @@ -288,12 +288,12 @@ func authzOverrideDisabled(t *testing.T, rh cache.ResourceEventHandler, c *Conto }, }) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: routeType, Resources: resources(t, - envoy.RouteConfiguration( + v2.RouteConfiguration( path.Join("https", disabled), - envoy.VirtualHost(disabled, + v2.VirtualHost(disabled, &envoy_api_v2_route.Route{ Match: routePrefix("/enabled"), Action: routeCluster("default/app-server/80/da39a3ee5e"), @@ -305,9 +305,9 @@ func authzOverrideDisabled(t *testing.T, rh cache.ResourceEventHandler, c *Conto }, ), ), - envoy.RouteConfiguration( + v2.RouteConfiguration( path.Join("https", enabled), - envoy.VirtualHost(enabled, + v2.VirtualHost(enabled, &envoy_api_v2_route.Route{ Match: routePrefix("/disabled"), Action: routeCluster("default/app-server/80/da39a3ee5e"), @@ -319,9 +319,9 @@ func authzOverrideDisabled(t *testing.T, rh cache.ResourceEventHandler, c *Conto }, ), ), - envoy.RouteConfiguration( + v2.RouteConfiguration( "ingress_http", - envoy.VirtualHost(disabled, + v2.VirtualHost(disabled, &envoy_api_v2_route.Route{ Match: routePrefix("/enabled"), Action: withRedirect(), @@ -331,7 +331,7 @@ func authzOverrideDisabled(t *testing.T, rh cache.ResourceEventHandler, c *Conto Action: withRedirect(), }, ), - envoy.VirtualHost(enabled, + v2.VirtualHost(enabled, &envoy_api_v2_route.Route{ Match: routePrefix("/disabled"), Action: withRedirect(), @@ -396,12 +396,12 @@ func authzMergeRouteContext(t *testing.T, rh cache.ResourceEventHandler, c *Cont "leaf-element": "leaf", } - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: routeType, Resources: resources(t, - envoy.RouteConfiguration( + v2.RouteConfiguration( path.Join("https", fqdn), - envoy.VirtualHost(fqdn, + v2.VirtualHost(fqdn, &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/app-server/80/da39a3ee5e"), @@ -416,9 +416,9 @@ func authzMergeRouteContext(t *testing.T, rh cache.ResourceEventHandler, c *Cont }, ), ), - envoy.RouteConfiguration( + v2.RouteConfiguration( "ingress_http", - envoy.VirtualHost(fqdn, + v2.VirtualHost(fqdn, &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withRedirect(), @@ -454,7 +454,7 @@ func authzInvalidReference(t *testing.T, rh cache.ResourceEventHandler, c *Conto rh.OnDelete(invalid) rh.OnAdd(invalid) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: resources(t, staticListener()), }).Status(invalid).Equals(projcontour.HTTPProxyStatus{ @@ -471,7 +471,7 @@ func authzInvalidReference(t *testing.T, rh cache.ResourceEventHandler, c *Conto rh.OnDelete(invalid) rh.OnAdd(invalid) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: resources(t, staticListener()), }).Status(invalid).Equals(projcontour.HTTPProxyStatus{ @@ -487,15 +487,15 @@ func authzInvalidReference(t *testing.T, rh cache.ResourceEventHandler, c *Conto rh.OnDelete(invalid) rh.OnAdd(invalid) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: resources(t, defaultHTTPListener(), - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ filterchaintls(fqdn, @@ -518,7 +518,7 @@ func authzInvalidReference(t *testing.T, rh cache.ResourceEventHandler, c *Conto ), nil, "h2", "http/1.1"), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener()), }).Status(invalid).Like(projcontour.HTTPProxyStatus{ diff --git a/internal/featuretests/backendcavalidation_test.go b/internal/featuretests/backendcavalidation_test.go index ec159754ee9..f085bcf5f96 100644 --- a/internal/featuretests/backendcavalidation_test.go +++ b/internal/featuretests/backendcavalidation_test.go @@ -16,10 +16,10 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -67,15 +67,15 @@ func TestClusterServiceTLSBackendCAValidation(t *testing.T) { rh.OnAdd(p1) // assert that the insecure listener and the stats listener are present in LDS. - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -83,7 +83,7 @@ func TestClusterServiceTLSBackendCAValidation(t *testing.T) { }) // assert that there is a regular, non validation enabled cluster in CDS. - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, tlsCluster(cluster("default/kuard/443/da39a3ee5e", "default/kuard/securebackend", "default_kuard_443"), nil, "", ""), ), @@ -115,15 +115,15 @@ func TestClusterServiceTLSBackendCAValidation(t *testing.T) { rh.OnUpdate(p1, p2) // assert that the insecure listener and the stats listener are present in LDS. - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -131,7 +131,7 @@ func TestClusterServiceTLSBackendCAValidation(t *testing.T) { }) // assert that the cluster now has a certificate and subject name. - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, tlsCluster(cluster("default/kuard/443/98c0f31c72", "default/kuard/securebackend", "default_kuard_443"), []byte(CERTIFICATE), "subjname", ""), ), @@ -140,7 +140,7 @@ func TestClusterServiceTLSBackendCAValidation(t *testing.T) { // Contour does not use SDS to transmit the CA for upstream validation, issue 1405, // assert that SDS is empty. - c.Request(secretType).Equals(&v2.DiscoveryResponse{ + c.Request(secretType).Equals(&envoy_api_v2.DiscoveryResponse{ // we are asking for all SDS responses, the list is empty so // resources is nil, not []any.Any{} -- an empty slice. Resources: nil, @@ -172,15 +172,15 @@ func TestClusterServiceTLSBackendCAValidation(t *testing.T) { rh.OnAdd(hp1) // assert that the insecure listener and the stats listener are present in LDS. - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -188,7 +188,7 @@ func TestClusterServiceTLSBackendCAValidation(t *testing.T) { }) // assert that the cluster now has a certificate and subject name. - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, tlsCluster(cluster("default/kuard/443/98c0f31c72", "default/kuard/securebackend", "default_kuard_443"), []byte(CERTIFICATE), "subjname", ""), ), @@ -197,7 +197,7 @@ func TestClusterServiceTLSBackendCAValidation(t *testing.T) { // Contour does not use SDS to transmit the CA for upstream validation, issue 1405, // assert that SDS is empty. - c.Request(secretType).Equals(&v2.DiscoveryResponse{ + c.Request(secretType).Equals(&envoy_api_v2.DiscoveryResponse{ // we are asking for all SDS responses, the list is empty so // resources is nil, not []any.Any{} -- an empty slice. Resources: nil, diff --git a/internal/featuretests/cluster_test.go b/internal/featuretests/cluster_test.go index 99d3e919908..e75a8078db8 100644 --- a/internal/featuretests/cluster_test.go +++ b/internal/featuretests/cluster_test.go @@ -16,14 +16,12 @@ package featuretests import ( "testing" - projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" - + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_cluster "github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster" - "github.com/projectcontour/contour/internal/envoy" + projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" "github.com/projectcontour/contour/internal/protobuf" - - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" v1 "k8s.io/api/core/v1" "k8s.io/api/networking/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -55,7 +53,7 @@ func TestClusterLongServiceName(t *testing.T) { ) // check that it's been translated correctly. - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, cluster("default/kbujbkuh-c83ceb/8080/da39a3ee5e", "default/kbujbkuhdod66gjdmwmijz8xzgsx1nkfbrloezdjiulquzk4x3p0nnvpzi8r", "default_kbujbkuhdod66gjdmwmijz8xzgsx1nkfbrloezdjiulquzk4x3p0nnvpzi8r_8080"), ), @@ -113,7 +111,7 @@ func TestClusterAddUpdateDelete(t *testing.T) { rh.OnAdd(s1) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, cluster("default/kuard/80/da39a3ee5e", "default/kuard", "default_kuard_80"), ), @@ -128,7 +126,7 @@ func TestClusterAddUpdateDelete(t *testing.T) { rh.OnUpdate(s1, s2) // check that we get two CDS records because the port is now named. - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, cluster("default/kuard/80/da39a3ee5e", "default/kuard/http", "default_kuard_80"), ), @@ -148,7 +146,7 @@ func TestClusterAddUpdateDelete(t *testing.T) { // check that we get four CDS records. Order is important // because the CDS cache is sorted. - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, cluster("default/kuard/443/da39a3ee5e", "default/kuard/https", "default_kuard_443"), cluster("default/kuard/80/da39a3ee5e", "default/kuard/http", "default_kuard_80"), @@ -167,7 +165,7 @@ func TestClusterAddUpdateDelete(t *testing.T) { // check that we get two CDS records only, and that the 80 and http // records have been removed even though the service object remains. - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, cluster("default/kuard/443/da39a3ee5e", "default/kuard/https", "default_kuard_443"), ), @@ -217,7 +215,7 @@ func TestClusterRenameUpdateDelete(t *testing.T) { rh.OnAdd(s1) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, cluster("default/kuard/443/da39a3ee5e", "default/kuard/https", "default_kuard_443"), cluster("default/kuard/80/da39a3ee5e", "default/kuard/http", "default_kuard_80"), @@ -231,7 +229,7 @@ func TestClusterRenameUpdateDelete(t *testing.T) { rh.OnUpdate(s1, s2) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, cluster("default/kuard/443/da39a3ee5e", "default/kuard", "default_kuard_443"), ), @@ -241,7 +239,7 @@ func TestClusterRenameUpdateDelete(t *testing.T) { // now replace s2 with s1 to check it works in the other direction. rh.OnUpdate(s2, s1) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, cluster("default/kuard/443/da39a3ee5e", "default/kuard/https", "default_kuard_443"), cluster("default/kuard/80/da39a3ee5e", "default/kuard/http", "default_kuard_80"), @@ -252,7 +250,7 @@ func TestClusterRenameUpdateDelete(t *testing.T) { // cleanup and check rh.OnDelete(s1) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: nil, TypeUrl: clusterType, }) @@ -283,7 +281,7 @@ func TestIssue243(t *testing.T) { WithPorts(v1.ServicePort{Port: 80, TargetPort: intstr.FromInt(8080)}) rh.OnAdd(s1) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, cluster("default/kuard/80/da39a3ee5e", "default/kuard", "default_kuard_80"), ), @@ -320,7 +318,7 @@ func TestIssue247(t *testing.T) { WithPorts(v1.ServicePort{Port: 80, TargetPort: intstr.FromString("kuard")}) rh.OnAdd(s1) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, cluster("default/kuard/80/da39a3ee5e", "default/kuard", "default_kuard_80"), ), @@ -371,7 +369,7 @@ func TestCDSResourceFiltering(t *testing.T) { WithPorts(v1.ServicePort{Port: 8080, TargetPort: intstr.FromString("httpbin")}) rh.OnAdd(s2) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, // note, resources are sorted by Cluster.Name cluster("default/httpbin/8080/da39a3ee5e", "default/httpbin", "default_httpbin_8080"), @@ -381,14 +379,14 @@ func TestCDSResourceFiltering(t *testing.T) { }) // assert we can filter on one resource - c.Request(clusterType, "default/kuard/80/da39a3ee5e").Equals(&v2.DiscoveryResponse{ + c.Request(clusterType, "default/kuard/80/da39a3ee5e").Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, cluster("default/kuard/80/da39a3ee5e", "default/kuard", "default_kuard_80")), TypeUrl: clusterType, }) // assert a non matching filter returns a response with no entries. - c.Request(clusterType, "default/httpbin/9000").Equals(&v2.DiscoveryResponse{ + c.Request(clusterType, "default/httpbin/9000").Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: clusterType, }) } @@ -421,14 +419,14 @@ func TestClusterCircuitbreakerAnnotations(t *testing.T) { rh.OnAdd(s1) // check that it's been translated correctly. - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - DefaultCluster(&v2.Cluster{ + DefaultCluster(&envoy_api_v2.Cluster{ Name: "default/kuard/8080/da39a3ee5e", AltStatName: "default_kuard_8080", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard", }, CircuitBreakers: &envoy_cluster.CircuitBreakers{ @@ -454,14 +452,14 @@ func TestClusterCircuitbreakerAnnotations(t *testing.T) { rh.OnUpdate(s1, s2) // check that it's been translated correctly. - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - DefaultCluster(&v2.Cluster{ + DefaultCluster(&envoy_api_v2.Cluster{ Name: "default/kuard/8080/da39a3ee5e", AltStatName: "default_kuard_8080", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard", }, CircuitBreakers: &envoy_cluster.CircuitBreakers{ @@ -514,7 +512,7 @@ func TestClusterPerServiceParameters(t *testing.T) { }, }) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, // note, resources are sorted by Cluster.Name cluster("default/kuard/80/da39a3ee5e", "default/kuard", "default_kuard_80"), @@ -566,27 +564,27 @@ func TestClusterLoadBalancerStrategyPerRoute(t *testing.T) { }, }) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - DefaultCluster(&v2.Cluster{ + DefaultCluster(&envoy_api_v2.Cluster{ Name: "default/kuard/80/58d888c08a", AltStatName: "default_kuard_80", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard", }, - LbPolicy: v2.Cluster_RANDOM, + LbPolicy: envoy_api_v2.Cluster_RANDOM, }), - DefaultCluster(&v2.Cluster{ + DefaultCluster(&envoy_api_v2.Cluster{ Name: "default/kuard/80/8bf87fefba", AltStatName: "default_kuard_80", - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: "default/kuard", }, - LbPolicy: v2.Cluster_LEAST_REQUEST, + LbPolicy: envoy_api_v2.Cluster_LEAST_REQUEST, }), ), TypeUrl: clusterType, @@ -624,7 +622,7 @@ func TestClusterWithHealthChecks(t *testing.T) { }, }) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, clusterWithHealthCheck("default/kuard/80/bc862a33ca", "default/kuard", "default_kuard_80", "/healthz", true), ), @@ -670,7 +668,7 @@ func TestUnreferencedService(t *testing.T) { }, }) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, cluster("default/kuard/80/da39a3ee5e", "default/kuard", "default_kuard_80"), ), @@ -682,7 +680,7 @@ func TestUnreferencedService(t *testing.T) { WithPorts(v1.ServicePort{Port: 80, TargetPort: intstr.FromInt(8080)}), ) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, cluster("default/kuard/80/da39a3ee5e", "default/kuard", "default_kuard_80"), ), diff --git a/internal/featuretests/downstreamvalidation_test.go b/internal/featuretests/downstreamvalidation_test.go index 30741627f2d..b6a8a812df2 100644 --- a/internal/featuretests/downstreamvalidation_test.go +++ b/internal/featuretests/downstreamvalidation_test.go @@ -16,10 +16,10 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" "github.com/projectcontour/contour/internal/k8s" v1 "k8s.io/api/core/v1" @@ -77,20 +77,20 @@ func TestDownstreamTLSCertificateValidation(t *testing.T) { rh.OnAdd(proxy) - ingress_http := &v2.Listener{ + ingress_http := &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } - ingress_https := &v2.Listener{ + ingress_https := &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: appendFilterChains( filterchaintls("example.com", serverTLSSecret, @@ -103,10 +103,10 @@ func TestDownstreamTLSCertificateValidation(t *testing.T) { "h2", "http/1.1", ), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, ingress_http, ingress_https, diff --git a/internal/featuretests/endpoints_test.go b/internal/featuretests/endpoints_test.go index 3ff8bc69bd6..13bd71e908e 100644 --- a/internal/featuretests/endpoints_test.go +++ b/internal/featuretests/endpoints_test.go @@ -16,9 +16,9 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" ) @@ -70,20 +70,20 @@ func TestAddRemoveEndpoints(t *testing.T) { rh.OnAdd(e1) // check that it's been translated correctly. - c.Request(endpointType).Equals(&v2.DiscoveryResponse{ + c.Request(endpointType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/http", - Endpoints: envoy.WeightedEndpoints(1, - envoy.SocketAddress("172.16.0.1", 8000), // endpoints and cluster names should be sorted - envoy.SocketAddress("172.16.0.2", 8000), + Endpoints: v2.WeightedEndpoints(1, + v2.SocketAddress("172.16.0.1", 8000), // endpoints and cluster names should be sorted + v2.SocketAddress("172.16.0.2", 8000), ), }, - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/https", - Endpoints: envoy.WeightedEndpoints(1, - envoy.SocketAddress("172.16.0.1", 8443), - envoy.SocketAddress("172.16.0.2", 8443), + Endpoints: v2.WeightedEndpoints(1, + v2.SocketAddress("172.16.0.1", 8443), + v2.SocketAddress("172.16.0.2", 8443), ), }, ), @@ -93,10 +93,10 @@ func TestAddRemoveEndpoints(t *testing.T) { // remove e1 and check that the EDS cache is now empty. rh.OnDelete(e1) - c.Request(endpointType).Equals(&v2.DiscoveryResponse{ + c.Request(endpointType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/http"), - envoy.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/https"), + v2.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/http"), + v2.ClusterLoadAssignment("super-long-namespace-name-oh-boy/what-a-descriptive-service-name-you-must-be-so-proud/https"), ), TypeUrl: endpointType, }) @@ -161,20 +161,20 @@ func TestAddEndpointComplicated(t *testing.T) { rh.OnAdd(e1) - c.Request(endpointType).Equals(&v2.DiscoveryResponse{ + c.Request(endpointType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: endpointType, Resources: resources(t, - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/kuard/admin", - Endpoints: envoy.WeightedEndpoints(1, - envoy.SocketAddress("10.48.1.77", 9000), - envoy.SocketAddress("10.48.1.78", 9000), + Endpoints: v2.WeightedEndpoints(1, + v2.SocketAddress("10.48.1.77", 9000), + v2.SocketAddress("10.48.1.78", 9000), ), }, - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/kuard/foo", - Endpoints: envoy.WeightedEndpoints(1, - envoy.SocketAddress("10.48.1.78", 8080), + Endpoints: v2.WeightedEndpoints(1, + v2.SocketAddress("10.48.1.78", 8080), ), }, ), @@ -229,20 +229,20 @@ func TestEndpointFilter(t *testing.T) { }, )) - c.Request(endpointType, "default/kuard/foo").Equals(&v2.DiscoveryResponse{ + c.Request(endpointType, "default/kuard/foo").Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: endpointType, Resources: resources(t, - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/kuard/foo", - Endpoints: envoy.WeightedEndpoints(1, envoy.SocketAddress("10.48.1.78", 8080)), + Endpoints: v2.WeightedEndpoints(1, v2.SocketAddress("10.48.1.78", 8080)), }, ), }) - c.Request(endpointType, "default/kuard/bar").Equals(&v2.DiscoveryResponse{ + c.Request(endpointType, "default/kuard/bar").Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: endpointType, Resources: resources(t, - envoy.ClusterLoadAssignment("default/kuard/bar"), + v2.ClusterLoadAssignment("default/kuard/bar"), ), }) } @@ -278,11 +278,11 @@ func TestIssue602(t *testing.T) { rh.OnAdd(e1) // Assert endpoint was added - c.Request(endpointType).Equals(&v2.DiscoveryResponse{ + c.Request(endpointType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.ClusterLoadAssignment{ + &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "default/simple", - Endpoints: envoy.WeightedEndpoints(1, envoy.SocketAddress("192.168.183.24", 8080)), + Endpoints: v2.WeightedEndpoints(1, v2.SocketAddress("192.168.183.24", 8080)), }, ), TypeUrl: endpointType, @@ -292,8 +292,8 @@ func TestIssue602(t *testing.T) { e2 := endpoints("default", "simple") rh.OnUpdate(e1, e2) - c.Request(endpointType).Equals(&v2.DiscoveryResponse{ - Resources: resources(t, envoy.ClusterLoadAssignment("default/simple")), + c.Request(endpointType).Equals(&envoy_api_v2.DiscoveryResponse{ + Resources: resources(t, v2.ClusterLoadAssignment("default/simple")), TypeUrl: endpointType, }) } diff --git a/internal/featuretests/envoy.go b/internal/featuretests/envoy.go index 14732971725..77a675a7a1a 100644 --- a/internal/featuretests/envoy.go +++ b/internal/featuretests/envoy.go @@ -19,7 +19,7 @@ import ( "path" "time" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" envoy_api_v2_listener "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener" @@ -32,7 +32,7 @@ import ( "github.com/golang/protobuf/ptypes/any" "github.com/projectcontour/contour/internal/contour" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/protobuf" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -41,12 +41,12 @@ import ( // DefaultCluster returns a copy of the default Cluster, with each // Cluster given in the parameter slice merged on top. This makes it // relatively fluent to compose Clusters by tweaking a few fields. -func DefaultCluster(clusters ...*v2.Cluster) *v2.Cluster { +func DefaultCluster(clusters ...*envoy_api_v2.Cluster) *envoy_api_v2.Cluster { // NOTE: Keep this in sync with envoy.defaultCluster(). - defaults := &v2.Cluster{ + defaults := &envoy_api_v2.Cluster{ ConnectTimeout: protobuf.Duration(250 * time.Millisecond), - LbPolicy: v2.Cluster_ROUND_ROBIN, - CommonLbConfig: envoy.ClusterCommonLBConfig(), + LbPolicy: envoy_api_v2.Cluster_ROUND_ROBIN, + CommonLbConfig: v2.ClusterCommonLBConfig(), } for _, c := range clusters { @@ -56,7 +56,7 @@ func DefaultCluster(clusters ...*v2.Cluster) *v2.Cluster { return defaults } -func clusterWithHealthCheck(name, servicename, statName, healthCheckPath string, drainConnOnHostRemoval bool) *v2.Cluster { +func clusterWithHealthCheck(name, servicename, statName, healthCheckPath string, drainConnOnHostRemoval bool) *envoy_api_v2.Cluster { c := cluster(name, servicename, statName) c.HealthChecks = []*envoy_api_v2_core.HealthCheck{{ Timeout: protobuf.Duration(2 * time.Second), @@ -74,15 +74,15 @@ func clusterWithHealthCheck(name, servicename, statName, healthCheckPath string, return c } -func externalNameCluster(name, servicename, statName, externalName string, port int) *v2.Cluster { - return DefaultCluster(&v2.Cluster{ +func externalNameCluster(name, servicename, statName, externalName string, port int) *envoy_api_v2.Cluster { + return DefaultCluster(&envoy_api_v2.Cluster{ Name: name, - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_STRICT_DNS), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_STRICT_DNS), AltStatName: statName, - LoadAssignment: &v2.ClusterLoadAssignment{ + LoadAssignment: &envoy_api_v2.ClusterLoadAssignment{ ClusterName: servicename, - Endpoints: envoy.Endpoints( - envoy.SocketAddress(externalName, port), + Endpoints: v2.Endpoints( + v2.SocketAddress(externalName, port), ), }, }) @@ -99,7 +99,7 @@ func routeCluster(cluster string) *envoy_api_v2_route.Route_Route { } func routePrefix(prefix string, headers ...dag.HeaderMatchCondition) *envoy_api_v2_route.RouteMatch { - return envoy.RouteMatch(&dag.Route{ + return v2.RouteMatch(&dag.Route{ PathMatchCondition: &dag.PrefixMatchCondition{ Prefix: prefix, }, @@ -119,25 +119,25 @@ func routeHostRewrite(cluster, newHostName string) *envoy_api_v2_route.Route_Rou func upgradeHTTPS(match *envoy_api_v2_route.RouteMatch) *envoy_api_v2_route.Route { return &envoy_api_v2_route.Route{ Match: match, - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), } } -func cluster(name, servicename, statName string) *v2.Cluster { - return DefaultCluster(&v2.Cluster{ +func cluster(name, servicename, statName string) *envoy_api_v2.Cluster { + return DefaultCluster(&envoy_api_v2.Cluster{ Name: name, - ClusterDiscoveryType: envoy.ClusterDiscoveryType(v2.Cluster_EDS), + ClusterDiscoveryType: v2.ClusterDiscoveryType(envoy_api_v2.Cluster_EDS), AltStatName: statName, - EdsClusterConfig: &v2.Cluster_EdsClusterConfig{ - EdsConfig: envoy.ConfigSource("contour"), + EdsClusterConfig: &envoy_api_v2.Cluster_EdsClusterConfig{ + EdsConfig: v2.ConfigSource("contour"), ServiceName: servicename, }, }) } -func tlsCluster(c *v2.Cluster, ca []byte, subjectName string, sni string, alpnProtocols ...string) *v2.Cluster { - c.TransportSocket = envoy.UpstreamTLSTransportSocket( - envoy.UpstreamTLSContext( +func tlsCluster(c *envoy_api_v2.Cluster, ca []byte, subjectName string, sni string, alpnProtocols ...string) *envoy_api_v2.Cluster { + c.TransportSocket = v2.UpstreamTLSTransportSocket( + v2.UpstreamTLSContext( &dag.PeerValidationContext{ CACertificate: &dag.Secret{Object: &v1.Secret{ ObjectMeta: metav1.ObjectMeta{ @@ -155,7 +155,7 @@ func tlsCluster(c *v2.Cluster, ca []byte, subjectName string, sni string, alpnPr return c } -func h2cCluster(c *v2.Cluster) *v2.Cluster { +func h2cCluster(c *envoy_api_v2.Cluster) *envoy_api_v2.Cluster { c.Http2ProtocolOptions = &envoy_api_v2_core.Http2ProtocolOptions{} return c } @@ -269,43 +269,43 @@ func appendFilterChains(chains ...*envoy_api_v2_listener.FilterChain) []*envoy_a // filterchaintls returns a FilterChain wrapping the given virtual host. func filterchaintls(domain string, secret *v1.Secret, filter *envoy_api_v2_listener.Filter, peerValidationContext *dag.PeerValidationContext, alpn ...string) *envoy_api_v2_listener.FilterChain { - return envoy.FilterChainTLS( + return v2.FilterChainTLS( domain, - envoy.DownstreamTLSContext( + v2.DownstreamTLSContext( &dag.Secret{Object: secret}, envoy_api_v2_auth.TlsParameters_TLSv1_1, peerValidationContext, alpn...), - envoy.Filters(filter), + v2.Filters(filter), ) } // filterchaintlsfallback returns a FilterChain for the given TLS fallback certificate. func filterchaintlsfallback(fallbackSecret *v1.Secret, peerValidationContext *dag.PeerValidationContext, alpn ...string) *envoy_api_v2_listener.FilterChain { - return envoy.FilterChainTLSFallback( - envoy.DownstreamTLSContext( + return v2.FilterChainTLSFallback( + v2.DownstreamTLSContext( &dag.Secret{Object: fallbackSecret}, envoy_api_v2_auth.TlsParameters_TLSv1_1, peerValidationContext, alpn...), - envoy.Filters( - envoy.HTTPConnectionManagerBuilder(). + v2.Filters( + v2.HTTPConnectionManagerBuilder(). DefaultFilters(). RouteConfigName(contour.ENVOY_FALLBACK_ROUTECONFIG). MetricsPrefix(contour.ENVOY_HTTPS_LISTENER). - AccessLoggers(envoy.FileAccessLogEnvoy("/dev/stdout")). + AccessLoggers(v2.FileAccessLogEnvoy("/dev/stdout")). Get(), ), ) } func httpsFilterFor(vhost string) *envoy_api_v2_listener.Filter { - return envoy.HTTPConnectionManagerBuilder(). - AddFilter(envoy.FilterMisdirectedRequests(vhost)). + return v2.HTTPConnectionManagerBuilder(). + AddFilter(v2.FilterMisdirectedRequests(vhost)). DefaultFilters(). RouteConfigName(path.Join("https", vhost)). MetricsPrefix(contour.ENVOY_HTTPS_LISTENER). - AccessLoggers(envoy.FileAccessLogEnvoy("/dev/stdout")). + AccessLoggers(v2.FileAccessLogEnvoy("/dev/stdout")). Get() } @@ -316,8 +316,8 @@ func authzFilterFor( vhost string, authz *envoy_config_filter_http_ext_authz_v2.ExtAuthz, ) *envoy_api_v2_listener.Filter { - return envoy.HTTPConnectionManagerBuilder(). - AddFilter(envoy.FilterMisdirectedRequests(vhost)). + return v2.HTTPConnectionManagerBuilder(). + AddFilter(v2.FilterMisdirectedRequests(vhost)). DefaultFilters(). AddFilter(&http.HttpFilter{ Name: "envoy.filters.http.ext_authz", @@ -327,7 +327,7 @@ func authzFilterFor( }). RouteConfigName(path.Join("https", vhost)). MetricsPrefix(contour.ENVOY_HTTPS_LISTENER). - AccessLoggers(envoy.FileAccessLogEnvoy("/dev/stdout")). + AccessLoggers(v2.FileAccessLogEnvoy("/dev/stdout")). Get() } @@ -340,24 +340,24 @@ func tcpproxy(statPrefix, cluster string) *envoy_api_v2_listener.Filter { ClusterSpecifier: &envoy_config_v2_tcpproxy.TcpProxy_Cluster{ Cluster: cluster, }, - AccessLog: envoy.FileAccessLogEnvoy("/dev/stdout"), + AccessLog: v2.FileAccessLogEnvoy("/dev/stdout"), IdleTimeout: protobuf.Duration(9001 * time.Second), }), }, } } -func staticListener() *v2.Listener { - return envoy.StatsListener("0.0.0.0", 8002) +func staticListener() *envoy_api_v2.Listener { + return v2.StatsListener("0.0.0.0", 8002) } -func defaultHTTPListener() *v2.Listener { - return &v2.Listener{ +func defaultHTTPListener() *envoy_api_v2.Listener { + return &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } } diff --git a/internal/featuretests/extensionservice_test.go b/internal/featuretests/extensionservice_test.go index fc0f508fa6d..d0beee8c8a7 100644 --- a/internal/featuretests/extensionservice_test.go +++ b/internal/featuretests/extensionservice_test.go @@ -16,7 +16,7 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" envoy_api_v2_endpoint "github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint" @@ -24,7 +24,7 @@ import ( projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/apis/projectcontour/v1alpha1" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" corev1 "k8s.io/api/core/v1" "k8s.io/client-go/tools/cache" @@ -42,13 +42,13 @@ func extBasic(t *testing.T, rh cache.ResourceEventHandler, c *Contour) { }, }) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: clusterType, Resources: resources(t, DefaultCluster( h2cCluster(cluster("extension/ns/ext", "extension/ns/ext", "extension_ns_ext")), - &v2.Cluster{ - TransportSocket: envoy.UpstreamTLSTransportSocket( + &envoy_api_v2.Cluster{ + TransportSocket: v2.UpstreamTLSTransportSocket( &envoy_api_v2_auth.UpstreamTlsContext{ CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ AlpnProtocols: []string{"h2"}, @@ -61,13 +61,13 @@ func extBasic(t *testing.T, rh cache.ResourceEventHandler, c *Contour) { ), }) - c.Request(endpointType).Equals(&v2.DiscoveryResponse{ + c.Request(endpointType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: endpointType, - Resources: resources(t, &v2.ClusterLoadAssignment{ + Resources: resources(t, &envoy_api_v2.ClusterLoadAssignment{ ClusterName: "extension/ns/ext", Endpoints: []*envoy_api_v2_endpoint.LocalityLbEndpoints{ - envoy.WeightedEndpoints(1, envoy.SocketAddress("192.168.183.20", 8081))[0], - envoy.WeightedEndpoints(1, envoy.SocketAddress("192.168.183.21", 8082))[0], + v2.WeightedEndpoints(1, v2.SocketAddress("192.168.183.20", 8081))[0], + v2.WeightedEndpoints(1, v2.SocketAddress("192.168.183.21", 8082))[0], }, }), }) @@ -85,7 +85,7 @@ func extCleartext(t *testing.T, rh cache.ResourceEventHandler, c *Contour) { }, }) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: clusterType, Resources: resources(t, DefaultCluster( @@ -112,7 +112,7 @@ func extUpstreamValidation(t *testing.T, rh cache.ResourceEventHandler, c *Conto rh.OnAdd(ext) // Enabling validation add SNI as well as CA and server altname validation. - tlsSocket := envoy.UpstreamTLSTransportSocket( + tlsSocket := v2.UpstreamTLSTransportSocket( &envoy_api_v2_auth.UpstreamTlsContext{ Sni: "ext.projectcontour.io", CommonTlsContext: &envoy_api_v2_auth.CommonTlsContext{ @@ -135,12 +135,12 @@ func extUpstreamValidation(t *testing.T, rh cache.ResourceEventHandler, c *Conto }, ) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: clusterType, Resources: resources(t, DefaultCluster( h2cCluster(cluster("extension/ns/ext", "extension/ns/ext", "extension_ns_ext")), - &v2.Cluster{TransportSocket: tlsSocket}, + &envoy_api_v2.Cluster{TransportSocket: tlsSocket}, ), ), }) @@ -160,7 +160,7 @@ func extUpstreamValidation(t *testing.T, rh cache.ResourceEventHandler, c *Conto }) // No Clusters are build because the CACertificate secret didn't resolve. - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: clusterType, }) } @@ -187,7 +187,7 @@ func extExternalName(_ *testing.T, rh cache.ResourceEventHandler, c *Contour) { }) // Using externalname services isn't implemented, so doesn't build a cluster. - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: clusterType, }) } @@ -202,7 +202,7 @@ func extMissingService(_ *testing.T, rh cache.ResourceEventHandler, c *Contour) }, }) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: clusterType, }) } @@ -221,7 +221,7 @@ func extInvalidTimeout(_ *testing.T, rh cache.ResourceEventHandler, c *Contour) }, }) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: clusterType, }) } @@ -242,7 +242,7 @@ func extInconsistentProto(_ *testing.T, rh cache.ResourceEventHandler, c *Contou }) // Should have no clusters because Protocol and UpstreamValidation is inconsistent. - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: clusterType, }) } diff --git a/internal/featuretests/externalname_test.go b/internal/featuretests/externalname_test.go index dc99d58e104..159e1084683 100644 --- a/internal/featuretests/externalname_test.go +++ b/internal/featuretests/externalname_test.go @@ -16,11 +16,11 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" "k8s.io/api/networking/v1beta1" @@ -60,10 +60,10 @@ func TestExternalNameService(t *testing.T) { rh.OnAdd(s1) rh.OnAdd(i1) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/kuard/80/da39a3ee5e"), @@ -74,7 +74,7 @@ func TestExternalNameService(t *testing.T) { TypeUrl: routeType, }) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, externalNameCluster("default/kuard/80/da39a3ee5e", "default/kuard", "default_kuard_80", "foo.io", 80), ), @@ -95,10 +95,10 @@ func TestExternalNameService(t *testing.T) { }), ) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("kuard.projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("kuard.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/kuard/80/da39a3ee5e"), @@ -109,7 +109,7 @@ func TestExternalNameService(t *testing.T) { TypeUrl: routeType, }) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, externalNameCluster("default/kuard/80/da39a3ee5e", "default/kuard", "default_kuard_80", "foo.io", 80), ), @@ -137,11 +137,11 @@ func TestExternalNameService(t *testing.T) { }), ) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: routeType, Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("kuard.projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("kuard.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeHostRewrite("default/kuard/80/da39a3ee5e", "external.address"), @@ -151,7 +151,7 @@ func TestExternalNameService(t *testing.T) { ), }) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: clusterType, Resources: resources(t, externalNameCluster("default/kuard/80/da39a3ee5e", "default/kuard", "default_kuard_80", "foo.io", 80), @@ -182,11 +182,11 @@ func TestExternalNameService(t *testing.T) { }), ) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: routeType, Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("kuard.projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("kuard.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeHostRewrite("default/kuard/80/da39a3ee5e", "external.address"), @@ -196,17 +196,17 @@ func TestExternalNameService(t *testing.T) { ), }) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: clusterType, Resources: resources(t, DefaultCluster( externalNameCluster("default/kuard/80/da39a3ee5e", "default/kuard", "default_kuard_80", "foo.io", 80), - &v2.Cluster{ + &envoy_api_v2.Cluster{ Http2ProtocolOptions: &envoy_api_v2_core.Http2ProtocolOptions{}, }, - &v2.Cluster{ - TransportSocket: envoy.UpstreamTLSTransportSocket( - envoy.UpstreamTLSContext(nil, "external.address", "h2"), + &envoy_api_v2.Cluster{ + TransportSocket: v2.UpstreamTLSTransportSocket( + v2.UpstreamTLSContext(nil, "external.address", "h2"), ), }, ), @@ -237,11 +237,11 @@ func TestExternalNameService(t *testing.T) { }), ) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: routeType, Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("kuard.projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("kuard.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeHostRewrite("default/kuard/80/da39a3ee5e", "external.address"), @@ -251,14 +251,14 @@ func TestExternalNameService(t *testing.T) { ), }) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: clusterType, Resources: resources(t, DefaultCluster( externalNameCluster("default/kuard/80/da39a3ee5e", "default/kuard", "default_kuard_80", "foo.io", 80), - &v2.Cluster{ - TransportSocket: envoy.UpstreamTLSTransportSocket( - envoy.UpstreamTLSContext(nil, "external.address"), + &envoy_api_v2.Cluster{ + TransportSocket: v2.UpstreamTLSTransportSocket( + v2.UpstreamTLSContext(nil, "external.address"), ), }, ), diff --git a/internal/featuretests/fallbackcert_test.go b/internal/featuretests/fallbackcert_test.go index ce4dc542dfd..39bc7cbaea3 100644 --- a/internal/featuretests/fallbackcert_test.go +++ b/internal/featuretests/fallbackcert_test.go @@ -16,13 +16,13 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/internal/contour" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -90,21 +90,21 @@ func TestFallbackCertificate(t *testing.T) { rh.OnAdd(proxy1) // We should start with a single generic HTTPS service. - c.Request(listenerType, "ingress_https").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "ingress_https").Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: appendFilterChains( filterchaintls("fallback.example.com", sec1, httpsFilterFor("fallback.example.com"), nil, "h2", "http/1.1"), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, ), }) @@ -130,7 +130,7 @@ func TestFallbackCertificate(t *testing.T) { rh.OnUpdate(proxy1, proxy2) // Invalid since there's no TLSCertificateDelegation configured - c.Request(listenerType, "ingress_https").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "ingress_https").Equals(&envoy_api_v2.DiscoveryResponse{ Resources: nil, TypeUrl: listenerType, }) @@ -152,14 +152,14 @@ func TestFallbackCertificate(t *testing.T) { // Now we should still have the generic HTTPS service filter, // but also the fallback certificate filter. - c.Request(listenerType, "ingress_https").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "ingress_https").Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: appendFilterChains( filterchaintls("fallback.example.com", sec1, @@ -167,14 +167,14 @@ func TestFallbackCertificate(t *testing.T) { nil, "h2", "http/1.1"), filterchaintlsfallback(fallbackSecret, nil, "h2", "http/1.1"), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, ), }) rh.OnDelete(certDelegationAll) - c.Request(listenerType, "ingress_https").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "ingress_https").Equals(&envoy_api_v2.DiscoveryResponse{ Resources: nil, TypeUrl: listenerType, }) @@ -194,14 +194,14 @@ func TestFallbackCertificate(t *testing.T) { rh.OnAdd(certDelegationSingle) - c.Request(listenerType, "ingress_https").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "ingress_https").Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: appendFilterChains( filterchaintls("fallback.example.com", sec1, @@ -209,7 +209,7 @@ func TestFallbackCertificate(t *testing.T) { nil, "h2", "http/1.1"), filterchaintlsfallback(fallbackSecret, nil, "h2", "http/1.1"), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, ), }) @@ -237,7 +237,7 @@ func TestFallbackCertificate(t *testing.T) { rh.OnUpdate(proxy2, proxy3) - c.Request(listenerType, "ingress_https").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "ingress_https").Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: nil, }) @@ -263,14 +263,14 @@ func TestFallbackCertificate(t *testing.T) { rh.OnUpdate(proxy3, proxy2) // proxy3 is invalid, resolve that to test two valid proxies rh.OnAdd(proxy4) - c.Request(listenerType, "ingress_https").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "ingress_https").Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: appendFilterChains( filterchaintls("anotherfallback.example.com", sec1, @@ -281,14 +281,14 @@ func TestFallbackCertificate(t *testing.T) { nil, "h2", "http/1.1"), filterchaintlsfallback(fallbackSecret, nil, "h2", "http/1.1"), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, ), }) // We should have emitted TLS certificate secrets for both // the proxy certificate and for the fallback certificate. - c.Request(secretType).Equals(&v2.DiscoveryResponse{ + c.Request(secretType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: secretType, Resources: resources(t, &envoy_api_v2_auth.Secret{ @@ -330,7 +330,7 @@ func TestFallbackCertificate(t *testing.T) { rh.OnDelete(fallbackSecret) - c.Request(listenerType, "ingress_https").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "ingress_https").Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: nil, }) @@ -338,7 +338,7 @@ func TestFallbackCertificate(t *testing.T) { rh.OnDelete(proxy4) rh.OnDelete(proxy2) - c.Request(secretType).Equals(&v2.DiscoveryResponse{ + c.Request(secretType).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: secretType, Resources: nil, }) diff --git a/internal/featuretests/headercondition_test.go b/internal/featuretests/headercondition_test.go index d6b545c2d8a..99f8f6d0474 100644 --- a/internal/featuretests/headercondition_test.go +++ b/internal/featuretests/headercondition_test.go @@ -16,11 +16,12 @@ package featuretests import ( "testing" + v22 "github.com/projectcontour/contour/internal/envoy/v2" + v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -80,8 +81,8 @@ func TestConditions_ContainsHeader_HTTProxy(t *testing.T) { c.Request(routeType).Equals(&v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.world", + v22.RouteConfiguration("ingress_http", + v22.VirtualHost("hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/blog", dag.HeaderMatchCondition{ Name: "x-header", @@ -143,8 +144,8 @@ func TestConditions_ContainsHeader_HTTProxy(t *testing.T) { c.Request(routeType).Equals(&v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.world", + v22.RouteConfiguration("ingress_http", + v22.VirtualHost("hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/blog", dag.HeaderMatchCondition{ Name: "x-header", @@ -206,8 +207,8 @@ func TestConditions_ContainsHeader_HTTProxy(t *testing.T) { c.Request(routeType).Equals(&v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.world", + v22.RouteConfiguration("ingress_http", + v22.VirtualHost("hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/blog", dag.HeaderMatchCondition{ Name: "x-header", @@ -269,8 +270,8 @@ func TestConditions_ContainsHeader_HTTProxy(t *testing.T) { c.Request(routeType).Equals(&v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.world", + v22.RouteConfiguration("ingress_http", + v22.VirtualHost("hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/blog", dag.HeaderMatchCondition{ Name: "x-header", @@ -332,8 +333,8 @@ func TestConditions_ContainsHeader_HTTProxy(t *testing.T) { c.Request(routeType).Equals(&v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.world", + v22.RouteConfiguration("ingress_http", + v22.VirtualHost("hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/blog", dag.HeaderMatchCondition{ Name: "x-header", @@ -393,8 +394,8 @@ func TestConditions_ContainsHeader_HTTProxy(t *testing.T) { c.Request(routeType).Equals(&v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.world", + v22.RouteConfiguration("ingress_http", + v22.VirtualHost("hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/", dag.HeaderMatchCondition{ Name: "x-header", @@ -452,8 +453,8 @@ func TestConditions_ContainsHeader_HTTProxy(t *testing.T) { c.Request(routeType).Equals(&v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.world", + v22.RouteConfiguration("ingress_http", + v22.VirtualHost("hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/", dag.HeaderMatchCondition{ Name: "x-header", diff --git a/internal/featuretests/headerpolicy_test.go b/internal/featuretests/headerpolicy_test.go index c4d40ffa551..68ffda21028 100644 --- a/internal/featuretests/headerpolicy_test.go +++ b/internal/featuretests/headerpolicy_test.go @@ -17,7 +17,7 @@ import ( envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" "github.com/golang/protobuf/ptypes/wrappers" - "github.com/projectcontour/contour/internal/envoy" + v22 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" @@ -57,8 +57,8 @@ func TestHeaderPolicy_ReplaceHeader_HTTProxy(t *testing.T) { c.Request(routeType).Equals(&v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.world", + v22.RouteConfiguration("ingress_http", + v22.VirtualHost("hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeHostRewrite("default/svc1/80/da39a3ee5e", "goodbye.planet"), @@ -90,8 +90,8 @@ func TestHeaderPolicy_ReplaceHeader_HTTProxy(t *testing.T) { c.Request(routeType).Equals(&v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.world", + v22.RouteConfiguration("ingress_http", + v22.VirtualHost("hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/svc1/80/da39a3ee5e"), @@ -131,8 +131,8 @@ func TestHeaderPolicy_ReplaceHeader_HTTProxy(t *testing.T) { c.Request(routeType).Equals(&v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.world", + v22.RouteConfiguration("ingress_http", + v22.VirtualHost("hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/svc1/80/da39a3ee5e"), @@ -188,8 +188,8 @@ func TestHeaderPolicy_ReplaceHeader_HTTProxy(t *testing.T) { c.Request(routeType).Equals(&v2.DiscoveryResponse{ Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.world", + v22.RouteConfiguration("ingress_http", + v22.VirtualHost("hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: &envoy_api_v2_route.Route_Redirect{ @@ -201,8 +201,8 @@ func TestHeaderPolicy_ReplaceHeader_HTTProxy(t *testing.T) { }, }), ), - envoy.RouteConfiguration("https/hello.world", - envoy.VirtualHost("hello.world", + v22.RouteConfiguration("https/hello.world", + v22.VirtualHost("hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeHostRewrite("default/externalname/443/da39a3ee5e", "goodbye.planet"), diff --git a/internal/featuretests/ingressclass_test.go b/internal/featuretests/ingressclass_test.go index 717da672c5f..3feac13ff1b 100644 --- a/internal/featuretests/ingressclass_test.go +++ b/internal/featuretests/ingressclass_test.go @@ -16,11 +16,11 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/internal/contour" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" "github.com/projectcontour/contour/internal/k8s" v1 "k8s.io/api/core/v1" @@ -63,10 +63,10 @@ func TestIngressClassAnnotation_Configured(t *testing.T) { rh.OnAdd(ingressValid) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/kuard/8080/da39a3ee5e"), @@ -93,9 +93,9 @@ func TestIngressClassAnnotation_Configured(t *testing.T) { rh.OnUpdate(ingressValid, ingressWrongClass) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -112,9 +112,9 @@ func TestIngressClassAnnotation_Configured(t *testing.T) { } rh.OnUpdate(ingressWrongClass, ingressNoClass) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -122,10 +122,10 @@ func TestIngressClassAnnotation_Configured(t *testing.T) { // --- insert valid ingress object rh.OnAdd(ingressValid) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/kuard/8080/da39a3ee5e"), @@ -139,9 +139,9 @@ func TestIngressClassAnnotation_Configured(t *testing.T) { rh.OnDelete(ingressValid) // verify ingress is gone - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -166,10 +166,10 @@ func TestIngressClassAnnotation_Configured(t *testing.T) { rh.OnAdd(proxyValid) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/kuard/8080/da39a3ee5e"), @@ -198,9 +198,9 @@ func TestIngressClassAnnotation_Configured(t *testing.T) { rh.OnUpdate(proxyValid, proxyWrongClass) // ingress class does not match ingress controller, ignored. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -222,9 +222,9 @@ func TestIngressClassAnnotation_Configured(t *testing.T) { rh.OnUpdate(proxyWrongClass, proxyNoClass) // ingress class does not match ingress controller, ignored. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -232,10 +232,10 @@ func TestIngressClassAnnotation_Configured(t *testing.T) { // --- insert valid httpproxy object rh.OnAdd(proxyValid) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/kuard/8080/da39a3ee5e"), @@ -249,9 +249,9 @@ func TestIngressClassAnnotation_Configured(t *testing.T) { rh.OnDelete(proxyValid) // verify ingress is gone - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -285,10 +285,10 @@ func TestIngressClassAnnotation_NotConfigured(t *testing.T) { rh.OnAdd(ingressNoClass) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/kuard/8080/da39a3ee5e"), @@ -315,10 +315,10 @@ func TestIngressClassAnnotation_NotConfigured(t *testing.T) { rh.OnUpdate(ingressNoClass, ingressMatchingClass) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/kuard/8080/da39a3ee5e"), @@ -344,9 +344,9 @@ func TestIngressClassAnnotation_NotConfigured(t *testing.T) { } rh.OnUpdate(ingressMatchingClass, ingressNonMatchingClass) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -354,10 +354,10 @@ func TestIngressClassAnnotation_NotConfigured(t *testing.T) { // --- insert valid ingress object rh.OnAdd(ingressNoClass) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/kuard/8080/da39a3ee5e"), @@ -371,9 +371,9 @@ func TestIngressClassAnnotation_NotConfigured(t *testing.T) { rh.OnDelete(ingressNoClass) // verify ingress is gone - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -397,10 +397,10 @@ func TestIngressClassAnnotation_NotConfigured(t *testing.T) { rh.OnAdd(proxyNoClass) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/kuard/8080/da39a3ee5e"), @@ -428,10 +428,10 @@ func TestIngressClassAnnotation_NotConfigured(t *testing.T) { rh.OnUpdate(proxyNoClass, proxyMatchingClass) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/kuard/8080/da39a3ee5e"), @@ -460,9 +460,9 @@ func TestIngressClassAnnotation_NotConfigured(t *testing.T) { rh.OnUpdate(proxyMatchingClass, proxyNonMatchingClass) // ingress class does not match ingress controller, ignored. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -470,10 +470,10 @@ func TestIngressClassAnnotation_NotConfigured(t *testing.T) { // --- insert valid httpproxy object rh.OnAdd(proxyNoClass) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/kuard/8080/da39a3ee5e"), @@ -487,9 +487,9 @@ func TestIngressClassAnnotation_NotConfigured(t *testing.T) { rh.OnDelete(proxyNoClass) // verify ingress is gone - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -530,10 +530,10 @@ func TestIngressClassUpdate(t *testing.T) { rh.OnAdd(vhost) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("kuard.projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("kuard.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/kuard/8080/da39a3ee5e"), @@ -555,9 +555,9 @@ func TestIngressClassUpdate(t *testing.T) { rh.OnUpdate(orig, vhost) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }).NoStatus(vhost) diff --git a/internal/featuretests/listeners_test.go b/internal/featuretests/listeners_test.go index 64f49518467..e75c7884cd1 100644 --- a/internal/featuretests/listeners_test.go +++ b/internal/featuretests/listeners_test.go @@ -16,13 +16,13 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" envoy_api_v2_listener "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/internal/contour" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" "k8s.io/api/networking/v1beta1" @@ -36,7 +36,7 @@ func TestNonTLSListener(t *testing.T) { // assert that without any ingress objects registered // there are no active listeners - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "0", Resources: resources(t, staticListener(), @@ -64,13 +64,13 @@ func TestNonTLSListener(t *testing.T) { // add it and assert that we now have a ingress_http listener rh.OnAdd(i1) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -96,7 +96,7 @@ func TestNonTLSListener(t *testing.T) { // update i1 to i2 and verify that ingress_http has gone. rh.OnUpdate(i1, i2) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, staticListener(), ), @@ -123,13 +123,13 @@ func TestNonTLSListener(t *testing.T) { // update i2 to i3 and check that ingress_http has returned rh.OnUpdate(i2, i3) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -185,7 +185,7 @@ func TestTLSListener(t *testing.T) { rh.OnAdd(s1) // assert that there is only a static listener - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, staticListener(), ), @@ -194,26 +194,26 @@ func TestTLSListener(t *testing.T) { // add ingress and assert the existence of ingress_http and ingres_https rh.OnAdd(i1) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ filterchaintls("kuard.example.com", s1, httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -252,20 +252,20 @@ func TestTLSListener(t *testing.T) { // update i1 to i2 and verify that ingress_http has gone. rh.OnUpdate(i1, i2) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ filterchaintls("kuard.example.com", s1, httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -274,7 +274,7 @@ func TestTLSListener(t *testing.T) { // delete secret and assert that ingress_https is removed rh.OnDelete(s1) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, staticListener(), ), @@ -355,25 +355,25 @@ func TestHTTPProxyTLSListener(t *testing.T) { rh.OnAdd(secret1) // assert that there is only a static listener - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, staticListener(), ), TypeUrl: listenerType, }) - l1 := &v2.Listener{ + l1 := &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ filterchaintls("kuard.example.com", secret1, httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } // add service @@ -382,15 +382,15 @@ func TestHTTPProxyTLSListener(t *testing.T) { // add ingress and assert the existence of ingress_http and ingres_https rh.OnAdd(p1) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, l1, staticListener(), @@ -401,7 +401,7 @@ func TestHTTPProxyTLSListener(t *testing.T) { // delete secret and assert both listeners are removed because the // httpproxy is no longer valid. rh.OnDelete(secret1) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, staticListener(), ), @@ -411,37 +411,37 @@ func TestHTTPProxyTLSListener(t *testing.T) { rh.OnDelete(p1) // add secret rh.OnAdd(secret1) - l2 := &v2.Listener{ + l2 := &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ - envoy.FilterChainTLS( + v2.FilterChainTLS( "kuard.example.com", - envoy.DownstreamTLSContext( + v2.DownstreamTLSContext( &dag.Secret{Object: secret1}, envoy_api_v2_auth.TlsParameters_TLSv1_3, nil, "h2", "http/1.1"), - envoy.Filters(httpsFilterFor("kuard.example.com")), + v2.Filters(httpsFilterFor("kuard.example.com")), ), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } // add ingress and assert the existence of ingress_http and ingres_https rh.OnAdd(p2) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, l2, staticListener(), @@ -499,42 +499,42 @@ func TestLDSFilter(t *testing.T) { // add ingress and fetch ingress_https rh.OnAdd(i1) - c.Request(listenerType, "ingress_https").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "ingress_https").Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ filterchaintls("kuard.example.com", s1, httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, ), TypeUrl: listenerType, }) // fetch ingress_http - c.Request(listenerType, "ingress_http").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "ingress_http").Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, ), TypeUrl: listenerType, }) // fetch something non existent. - c.Request(listenerType, "HTTP").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "HTTP").Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, }) } @@ -544,7 +544,7 @@ func TestLDSStreamEmpty(t *testing.T) { defer done() // assert that streaming LDS with no ingresses does not stall. - c.Request(listenerType, "HTTP").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "HTTP").Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "0", TypeUrl: listenerType, Nonce: "0", @@ -559,7 +559,7 @@ func TestLDSIngressHTTPUseProxyProtocol(t *testing.T) { // assert that without any ingress objects registered // there is only a static listener - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "0", Resources: resources(t, staticListener(), @@ -588,17 +588,17 @@ func TestLDSIngressHTTPUseProxyProtocol(t *testing.T) { // add it and assert that we now have a ingress_http listener using // the proxy protocol (the true param to filterchain) rh.OnAdd(i1) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "1", Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - ListenerFilters: envoy.ListenerFilters( - envoy.ProxyProtocol(), + Address: v2.SocketAddress("0.0.0.0", 8080), + ListenerFilters: v2.ListenerFilters( + v2.ProxyProtocol(), ), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -654,7 +654,7 @@ func TestLDSIngressHTTPSUseProxyProtocol(t *testing.T) { rh.OnAdd(s1) // assert that there is only a static listener - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, staticListener(), ), @@ -668,30 +668,30 @@ func TestLDSIngressHTTPSUseProxyProtocol(t *testing.T) { // are using proxy protocol rh.OnAdd(i1) - ingress_https := &v2.Listener{ + ingress_https := &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.ProxyProtocol(), - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.ProxyProtocol(), + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ filterchaintls("kuard.example.com", s1, httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - ListenerFilters: envoy.ListenerFilters( - envoy.ProxyProtocol(), + Address: v2.SocketAddress("0.0.0.0", 8080), + ListenerFilters: v2.ListenerFilters( + v2.ProxyProtocol(), ), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0)), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + FilterChains: v2.FilterChains(v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0)), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, ingress_https, staticListener(), @@ -750,7 +750,7 @@ func TestLDSCustomAddressAndPort(t *testing.T) { rh.OnAdd(s1) // assert that there is only a static listener - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "0", Resources: resources(t, staticListener(), @@ -766,28 +766,28 @@ func TestLDSCustomAddressAndPort(t *testing.T) { // are using proxy protocol rh.OnAdd(i1) - ingress_http := &v2.Listener{ + ingress_http := &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("127.0.0.100", 9100), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("127.0.0.100", 9100), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } - ingress_https := &v2.Listener{ + ingress_https := &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("127.0.0.200", 9200), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("127.0.0.200", 9200), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ filterchaintls("kuard.example.com", s1, httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, ingress_http, ingress_https, @@ -848,7 +848,7 @@ func TestLDSCustomAccessLogPaths(t *testing.T) { rh.OnAdd(s1) // assert that there is only a static listener - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "0", Resources: resources(t, staticListener(), @@ -859,34 +859,34 @@ func TestLDSCustomAccessLogPaths(t *testing.T) { rh.OnAdd(i1) - ingress_http := &v2.Listener{ + ingress_http := &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/tmp/http_access.log"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/tmp/http_access.log"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } - ingress_https := &v2.Listener{ + ingress_https := &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ filterchaintls("kuard.example.com", s1, - envoy.HTTPConnectionManagerBuilder(). - AddFilter(envoy.FilterMisdirectedRequests("kuard.example.com")). + v2.HTTPConnectionManagerBuilder(). + AddFilter(v2.FilterMisdirectedRequests("kuard.example.com")). DefaultFilters(). RouteConfigName("https/kuard.example.com"). MetricsPrefix(contour.ENVOY_HTTPS_LISTENER). - AccessLoggers(envoy.FileAccessLogEnvoy("/tmp/https_access.log")). + AccessLoggers(v2.FileAccessLogEnvoy("/tmp/https_access.log")). Get(), nil, "h2", "http/1.1"), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "1", Resources: resources(t, ingress_http, @@ -903,7 +903,7 @@ func TestHTTPProxyHTTPS(t *testing.T) { defer done() // assert that there is only a static listener - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "0", Resources: resources(t, staticListener(), @@ -959,29 +959,29 @@ func TestHTTPProxyHTTPS(t *testing.T) { // add httpproxy rh.OnAdd(p1) - ingressHTTP := &v2.Listener{ + ingressHTTP := &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } - ingressHTTPS := &v2.Listener{ + ingressHTTPS := &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ filterchaintls("example.com", s1, httpsFilterFor("example.com"), nil, "h2", "http/1.1"), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "1", Resources: resources(t, ingressHTTP, @@ -1041,36 +1041,36 @@ func TestHTTPProxyMinimumTLSVersion(t *testing.T) { } rh.OnAdd(p1) - l1 := &v2.Listener{ + l1 := &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ - envoy.FilterChainTLS( + v2.FilterChainTLS( "kuard.example.com", - envoy.DownstreamTLSContext( + v2.DownstreamTLSContext( &dag.Secret{Object: secret1}, envoy_api_v2_auth.TlsParameters_TLSv1_2, nil, "h2", "http/1.1"), - envoy.Filters(httpsFilterFor("kuard.example.com")), + v2.Filters(httpsFilterFor("kuard.example.com")), ), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } // verify that p1's TLS 1.1 minimum has been upgraded to 1.2 - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, l1, staticListener(), @@ -1106,36 +1106,36 @@ func TestHTTPProxyMinimumTLSVersion(t *testing.T) { } rh.OnUpdate(p1, p2) - l2 := &v2.Listener{ + l2 := &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ - envoy.FilterChainTLS( + v2.FilterChainTLS( "kuard.example.com", - envoy.DownstreamTLSContext( + v2.DownstreamTLSContext( &dag.Secret{Object: secret1}, envoy_api_v2_auth.TlsParameters_TLSv1_3, nil, "h2", "http/1.1"), - envoy.Filters(httpsFilterFor("kuard.example.com")), + v2.Filters(httpsFilterFor("kuard.example.com")), ), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } // verify that p2's TLS 1.3 minimum has NOT been downgraded to 1.2 - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, l2, staticListener(), @@ -1195,15 +1195,15 @@ func TestLDSHTTPProxyRootCannotDelegateToAnotherRoot(t *testing.T) { // verify that port 80 is present because while it is not possible to // delegate to it, child can host a vhost which opens port 80. - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), diff --git a/internal/featuretests/loadbalancerpolicy_test.go b/internal/featuretests/loadbalancerpolicy_test.go index 62662e0081c..e72799b49b5 100644 --- a/internal/featuretests/loadbalancerpolicy_test.go +++ b/internal/featuretests/loadbalancerpolicy_test.go @@ -16,10 +16,10 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/intstr" @@ -52,10 +52,10 @@ func TestLoadBalancerPolicySessionAffinity(t *testing.T) { }) rh.OnAdd(proxy1) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/cart"), Action: withSessionAffinity(routeCluster("default/app/80/e4f81994fe")), @@ -88,10 +88,10 @@ func TestLoadBalancerPolicySessionAffinity(t *testing.T) { }), ) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/cart"), Action: withSessionAffinity( diff --git a/internal/featuretests/mirrorpolicy_test.go b/internal/featuretests/mirrorpolicy_test.go index 131d76098e2..977ef082001 100644 --- a/internal/featuretests/mirrorpolicy_test.go +++ b/internal/featuretests/mirrorpolicy_test.go @@ -16,11 +16,11 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/internal/contour" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -60,10 +60,10 @@ func TestMirrorPolicy(t *testing.T) { } rh.OnAdd(p1) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost(p1.Spec.VirtualHost.Fqdn, + v2.RouteConfiguration("ingress_http", + v2.VirtualHost(p1.Spec.VirtualHost.Fqdn, &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withMirrorPolicy(routeCluster("default/kuard/8080/da39a3ee5e"), "default/mirror/8080/da39a3ee5e"), @@ -76,7 +76,7 @@ func TestMirrorPolicy(t *testing.T) { // assert that are two clusters in CDS, one for the route service // and one for the mirror service. - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, cluster("default/kuard/8080/da39a3ee5e", "default/kuard", "default_kuard_8080"), cluster("default/mirror/8080/da39a3ee5e", "default/mirror", "default_mirror_8080"), diff --git a/internal/featuretests/replaceprefix_test.go b/internal/featuretests/replaceprefix_test.go index a2b81f08982..cbb94a4ad52 100644 --- a/internal/featuretests/replaceprefix_test.go +++ b/internal/featuretests/replaceprefix_test.go @@ -16,10 +16,10 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" "github.com/projectcontour/contour/internal/k8s" v1 "k8s.io/api/core/v1" @@ -67,10 +67,10 @@ func basic(t *testing.T) { rh.OnAdd(vhost) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("kuard.projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("kuard.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/api/"), Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/v1/"), @@ -93,13 +93,13 @@ func basic(t *testing.T) { vhost.Spec.Routes[0].PathRewritePolicy.ReplacePrefix = []projcontour.ReplacePrefix{ {Replacement: "/api/v1"}, - {Replacement: "/api/v2"}, + {Replacement: "/api/envoy_api_v2"}, } }) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }).Status(vhost).Equals(projcontour.HTTPProxyStatus{ @@ -113,21 +113,21 @@ func basic(t *testing.T) { vhost.Spec.Routes[0].PathRewritePolicy.ReplacePrefix = []projcontour.ReplacePrefix{ {Prefix: "/foo", Replacement: "/api/v1"}, - {Prefix: "/api", Replacement: "/api/v2"}, + {Prefix: "/api", Replacement: "/api/envoy_api_v2"}, } }) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("kuard.projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("kuard.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/api/"), - Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/v2/"), + Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/envoy_api_v2/"), }, &envoy_api_v2_route.Route{ Match: routePrefix("/api"), - Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/v2"), + Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/envoy_api_v2"), }, ), ), @@ -144,13 +144,13 @@ func basic(t *testing.T) { vhost.Spec.Routes[0].PathRewritePolicy.ReplacePrefix = []projcontour.ReplacePrefix{ {Prefix: "/foo", Replacement: "/api/v1"}, - {Prefix: "/foo", Replacement: "/api/v2"}, + {Prefix: "/foo", Replacement: "/api/envoy_api_v2"}, } }) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }).Status(vhost).Equals(projcontour.HTTPProxyStatus{ @@ -168,10 +168,10 @@ func basic(t *testing.T) { } }) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("kuard.projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("kuard.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/api/"), Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/full/"), @@ -196,10 +196,10 @@ func basic(t *testing.T) { vhost.Spec.Routes[0].Conditions = nil }) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("kuard.projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("kuard.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/empty"), @@ -240,7 +240,7 @@ func multiInclude(t *testing.T) { Includes: []projcontour.Include{{ Name: "app", Namespace: "default", - Conditions: matchconditions(prefixMatchCondition("/v2")), + Conditions: matchconditions(prefixMatchCondition("/envoy_api_v2")), }}, }) @@ -253,7 +253,7 @@ func multiInclude(t *testing.T) { }}, PathRewritePolicy: &projcontour.PathRewritePolicy{ ReplacePrefix: []projcontour.ReplacePrefix{ - {Prefix: "/v2", Replacement: "/api/v2"}, + {Prefix: "/envoy_api_v2", Replacement: "/api/envoy_api_v2"}, {Prefix: "/v1", Replacement: "/api/v1"}, }, }, @@ -264,10 +264,10 @@ func multiInclude(t *testing.T) { rh.OnAdd(vhost2) rh.OnAdd(app) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("host1.projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("host1.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/v1/"), Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/v1/"), @@ -277,14 +277,14 @@ func multiInclude(t *testing.T) { Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/v1"), }, ), - envoy.VirtualHost("host2.projectcontour.io", + v2.VirtualHost("host2.projectcontour.io", &envoy_api_v2_route.Route{ - Match: routePrefix("/v2/"), - Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/v2/"), + Match: routePrefix("/envoy_api_v2/"), + Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/envoy_api_v2/"), }, &envoy_api_v2_route.Route{ - Match: routePrefix("/v2"), - Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/v2"), + Match: routePrefix("/envoy_api_v2"), + Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/envoy_api_v2"), }, ), ), @@ -305,10 +305,10 @@ func multiInclude(t *testing.T) { } }) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("host1.projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("host1.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/v1/"), Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/v1/"), @@ -318,9 +318,9 @@ func multiInclude(t *testing.T) { Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/api/v1"), }, ), - envoy.VirtualHost("host2.projectcontour.io", + v2.VirtualHost("host2.projectcontour.io", &envoy_api_v2_route.Route{ - Match: routePrefix("/v2"), + Match: routePrefix("/envoy_api_v2"), Action: routeCluster("default/kuard/8080/da39a3ee5e"), }, ), @@ -385,10 +385,10 @@ func replaceWithSlash(t *testing.T) { // Make sure that when we rewrite prefix routing conditions // '/foo' and '/foo/' to '/', we don't omit the '/' or emit // too many '/'s. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("host1.projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("host1.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/foo/"), Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/"), @@ -398,7 +398,7 @@ func replaceWithSlash(t *testing.T) { Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/"), }, ), - envoy.VirtualHost("host2.projectcontour.io", + v2.VirtualHost("host2.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/bar/"), Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/"), @@ -430,10 +430,10 @@ func replaceWithSlash(t *testing.T) { } }) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("host1.projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("host1.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/foo/"), Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/"), @@ -443,7 +443,7 @@ func replaceWithSlash(t *testing.T) { Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/"), }, ), - envoy.VirtualHost("host2.projectcontour.io", + v2.VirtualHost("host2.projectcontour.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withPrefixRewrite(routeCluster("default/kuard/8080/da39a3ee5e"), "/bar"), @@ -481,10 +481,10 @@ func artifactoryDocker(t *testing.T) { }}, PathRewritePolicy: &projcontour.PathRewritePolicy{ ReplacePrefix: []projcontour.ReplacePrefix{ - {Prefix: "/v2/container-sandbox", Replacement: "/artifactory/api/docker/container-sandbox/v2"}, - {Prefix: "/v2/container-release", Replacement: "/artifactory/api/docker/container-release/v2"}, - {Prefix: "/v2/container-external", Replacement: "/artifactory/api/docker/container-external/v2"}, - {Prefix: "/v2/container-public", Replacement: "/artifactory/api/docker/container-public/v2"}, + {Prefix: "/envoy_api_v2/container-sandbox", Replacement: "/artifactory/api/docker/container-sandbox/envoy_api_v2"}, + {Prefix: "/envoy_api_v2/container-release", Replacement: "/artifactory/api/docker/container-release/envoy_api_v2"}, + {Prefix: "/envoy_api_v2/container-external", Replacement: "/artifactory/api/docker/container-external/envoy_api_v2"}, + {Prefix: "/envoy_api_v2/container-public", Replacement: "/artifactory/api/docker/container-public/envoy_api_v2"}, }, }, }}, @@ -497,58 +497,58 @@ func artifactoryDocker(t *testing.T) { Fqdn: "artifactory.projectcontour.io", }, Includes: []projcontour.Include{ - {Name: "routes", Conditions: matchconditions(prefixMatchCondition("/v2/container-sandbox"))}, - {Name: "routes", Conditions: matchconditions(prefixMatchCondition("/v2/container-release"))}, - {Name: "routes", Conditions: matchconditions(prefixMatchCondition("/v2/container-external"))}, - {Name: "routes", Conditions: matchconditions(prefixMatchCondition("/v2/container-public"))}, + {Name: "routes", Conditions: matchconditions(prefixMatchCondition("/envoy_api_v2/container-sandbox"))}, + {Name: "routes", Conditions: matchconditions(prefixMatchCondition("/envoy_api_v2/container-release"))}, + {Name: "routes", Conditions: matchconditions(prefixMatchCondition("/envoy_api_v2/container-external"))}, + {Name: "routes", Conditions: matchconditions(prefixMatchCondition("/envoy_api_v2/container-public"))}, }, }), ) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("artifactory.projectcontour.io", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("artifactory.projectcontour.io", &envoy_api_v2_route.Route{ - Match: routePrefix("/v2/container-sandbox/"), + Match: routePrefix("/envoy_api_v2/container-sandbox/"), Action: withPrefixRewrite(routeCluster("artifactory/service/8080/da39a3ee5e"), - "/artifactory/api/docker/container-sandbox/v2/"), + "/artifactory/api/docker/container-sandbox/envoy_api_v2/"), }, &envoy_api_v2_route.Route{ - Match: routePrefix("/v2/container-sandbox"), + Match: routePrefix("/envoy_api_v2/container-sandbox"), Action: withPrefixRewrite(routeCluster("artifactory/service/8080/da39a3ee5e"), - "/artifactory/api/docker/container-sandbox/v2"), + "/artifactory/api/docker/container-sandbox/envoy_api_v2"), }, &envoy_api_v2_route.Route{ - Match: routePrefix("/v2/container-release/"), + Match: routePrefix("/envoy_api_v2/container-release/"), Action: withPrefixRewrite(routeCluster("artifactory/service/8080/da39a3ee5e"), - "/artifactory/api/docker/container-release/v2/"), + "/artifactory/api/docker/container-release/envoy_api_v2/"), }, &envoy_api_v2_route.Route{ - Match: routePrefix("/v2/container-release"), + Match: routePrefix("/envoy_api_v2/container-release"), Action: withPrefixRewrite(routeCluster("artifactory/service/8080/da39a3ee5e"), - "/artifactory/api/docker/container-release/v2"), + "/artifactory/api/docker/container-release/envoy_api_v2"), }, &envoy_api_v2_route.Route{ - Match: routePrefix("/v2/container-public/"), + Match: routePrefix("/envoy_api_v2/container-public/"), Action: withPrefixRewrite(routeCluster("artifactory/service/8080/da39a3ee5e"), - "/artifactory/api/docker/container-public/v2/"), + "/artifactory/api/docker/container-public/envoy_api_v2/"), }, &envoy_api_v2_route.Route{ - Match: routePrefix("/v2/container-public"), + Match: routePrefix("/envoy_api_v2/container-public"), Action: withPrefixRewrite(routeCluster("artifactory/service/8080/da39a3ee5e"), - "/artifactory/api/docker/container-public/v2"), + "/artifactory/api/docker/container-public/envoy_api_v2"), }, &envoy_api_v2_route.Route{ - Match: routePrefix("/v2/container-external/"), + Match: routePrefix("/envoy_api_v2/container-external/"), Action: withPrefixRewrite(routeCluster("artifactory/service/8080/da39a3ee5e"), - "/artifactory/api/docker/container-external/v2/"), + "/artifactory/api/docker/container-external/envoy_api_v2/"), }, &envoy_api_v2_route.Route{ - Match: routePrefix("/v2/container-external"), + Match: routePrefix("/envoy_api_v2/container-external"), Action: withPrefixRewrite(routeCluster("artifactory/service/8080/da39a3ee5e"), - "/artifactory/api/docker/container-external/v2"), + "/artifactory/api/docker/container-external/envoy_api_v2"), }, ), ), diff --git a/internal/featuretests/retrypolicy_test.go b/internal/featuretests/retrypolicy_test.go index 5ed019dafe1..d625896c1a3 100644 --- a/internal/featuretests/retrypolicy_test.go +++ b/internal/featuretests/retrypolicy_test.go @@ -17,10 +17,10 @@ import ( "testing" "time" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" "k8s.io/api/networking/v1beta1" @@ -52,10 +52,10 @@ func TestRetryPolicy(t *testing.T) { } rh.OnAdd(i1) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withRetryPolicy(routeCluster("default/backend/80/da39a3ee5e"), "5xx,gateway-error", 7, 120*time.Millisecond), @@ -81,10 +81,10 @@ func TestRetryPolicy(t *testing.T) { } rh.OnUpdate(i1, i2) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withRetryPolicy(routeCluster("default/backend/80/da39a3ee5e"), "5xx,gateway-error", 7, 120*time.Millisecond), @@ -110,10 +110,10 @@ func TestRetryPolicy(t *testing.T) { } rh.OnUpdate(i2, i3) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withRetryPolicy(routeCluster("default/backend/80/da39a3ee5e"), "5xx,gateway-error", 7, 120*time.Millisecond), @@ -147,10 +147,10 @@ func TestRetryPolicy(t *testing.T) { } rh.OnAdd(hp1) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost(hp1.Spec.VirtualHost.Fqdn, + v2.RouteConfiguration("ingress_http", + v2.VirtualHost(hp1.Spec.VirtualHost.Fqdn, &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withRetryPolicy(routeCluster("default/backend/80/da39a3ee5e"), "5xx", 5, 105*time.Second), diff --git a/internal/featuretests/rootnamespaces_test.go b/internal/featuretests/rootnamespaces_test.go index bf4c3ed5cc1..f6e3b29147f 100644 --- a/internal/featuretests/rootnamespaces_test.go +++ b/internal/featuretests/rootnamespaces_test.go @@ -16,11 +16,11 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/internal/contour" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -44,7 +44,7 @@ func TestRootNamespaces(t *testing.T) { rh.OnAdd(svc2) // assert that there is only a static listener - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, staticListener(), ), @@ -52,7 +52,7 @@ func TestRootNamespaces(t *testing.T) { }) // assert that the route tables are empty - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: nil, TypeUrl: routeType, }) @@ -79,7 +79,7 @@ func TestRootNamespaces(t *testing.T) { rh.OnAdd(hp1) // assert that hp1 has no effect on the listener set. - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, staticListener(), ), @@ -87,9 +87,9 @@ func TestRootNamespaces(t *testing.T) { }) // assert that the route tables are present but empty. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -116,15 +116,15 @@ func TestRootNamespaces(t *testing.T) { rh.OnAdd(hp2) // assert that hp2 creates port 80 listener. - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -132,10 +132,10 @@ func TestRootNamespaces(t *testing.T) { }) // assert that hp2.example.com's routes are visible. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hp2.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("hp2.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("roots/kuard/8080/da39a3ee5e"), diff --git a/internal/featuretests/route_test.go b/internal/featuretests/route_test.go index 4f16c825468..d38b4b289bf 100644 --- a/internal/featuretests/route_test.go +++ b/internal/featuretests/route_test.go @@ -19,12 +19,12 @@ import ( "path" "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/internal/contour" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" "github.com/projectcontour/contour/internal/protobuf" v1 "k8s.io/api/core/v1" @@ -83,11 +83,11 @@ func TestEditIngress(t *testing.T) { rh.OnAdd(old) // check that it's been translated correctly. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "1", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", &envoy_api_v2_route.Route{ + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/80/da39a3ee5e"), }), @@ -118,11 +118,11 @@ func TestEditIngress(t *testing.T) { }) // check that ingress_http has been updated. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "2", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", &envoy_api_v2_route.Route{ + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/testing"), Action: routecluster("default/kuard/80/da39a3ee5e"), }), @@ -177,11 +177,11 @@ func TestIngressPathRouteWithoutHost(t *testing.T) { rh.OnAdd(s1) // check that it's been translated correctly. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "2", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/hello"), Action: routecluster("default/hello/80/da39a3ee5e"), @@ -227,11 +227,11 @@ func TestEditIngressInPlace(t *testing.T) { WithPorts(v1.ServicePort{Name: "http", Port: 9000, TargetPort: intstr.FromInt(8080)}) rh.OnAdd(s2) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "2", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("hello.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/wowie/80/da39a3ee5e"), @@ -270,11 +270,11 @@ func TestEditIngressInPlace(t *testing.T) { }, } rh.OnUpdate(i1, i2) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "3", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("hello.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/whoop"), Action: routecluster("default/kerpow/9000/da39a3ee5e"), @@ -322,18 +322,18 @@ func TestEditIngressInPlace(t *testing.T) { }, } rh.OnUpdate(i2, i3) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "4", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("hello.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/whoop"), - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), }, &envoy_api_v2_route.Route{ Match: routePrefix("/"), - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), }, ), ), @@ -388,23 +388,23 @@ func TestEditIngressInPlace(t *testing.T) { }, } rh.OnUpdate(i3, i4) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "5", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("hello.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("hello.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/whoop"), - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), }, &envoy_api_v2_route.Route{ Match: routePrefix("/"), - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), }, ), ), - envoy.RouteConfiguration("https/hello.example.com", - envoy.VirtualHost("hello.example.com", + v2.RouteConfiguration("https/hello.example.com", + v2.VirtualHost("hello.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/whoop"), Action: routecluster("default/kerpow/9000/da39a3ee5e"), @@ -497,18 +497,18 @@ func TestSSLRedirectOverlay(t *testing.T) { WithPorts(v1.ServicePort{Name: "http", Port: 8009, TargetPort: intstr.FromInt(8080)})) assertRDS(t, c, "5", virtualhosts( - envoy.VirtualHost("example.com", + v2.VirtualHost("example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/.well-known/acme-challenge/gVJl5NWL2owUqZekjHkt_bo3OHYC2XNDURRRgLI5JTk"), Action: routecluster("nginx-ingress/challenge-service/8009/da39a3ee5e"), }, &envoy_api_v2_route.Route{ Match: routePrefix("/"), // match all - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), }, ), ), virtualhosts( - envoy.VirtualHost("example.com", + v2.VirtualHost("example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/.well-known/acme-challenge/gVJl5NWL2owUqZekjHkt_bo3OHYC2XNDURRRgLI5JTk"), Action: routecluster("nginx-ingress/challenge-service/8009/da39a3ee5e"), @@ -565,7 +565,7 @@ func TestInvalidCertInIngress(t *testing.T) { }) assertRDS(t, c, "1", virtualhosts( - envoy.VirtualHost("kuard.io", + v2.VirtualHost("kuard.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/80/da39a3ee5e"), @@ -584,14 +584,14 @@ func TestInvalidCertInIngress(t *testing.T) { }) assertRDS(t, c, "2", virtualhosts( - envoy.VirtualHost("kuard.io", + v2.VirtualHost("kuard.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/80/da39a3ee5e"), }, ), ), virtualhosts( - envoy.VirtualHost("kuard.io", + v2.VirtualHost("kuard.io", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/80/da39a3ee5e"), @@ -639,7 +639,7 @@ func TestIssue257(t *testing.T) { rh.OnAdd(s1) assertRDS(t, c, "2", virtualhosts( - envoy.VirtualHost("*", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/80/da39a3ee5e"), @@ -692,7 +692,7 @@ func TestIssue257(t *testing.T) { rh.OnUpdate(i1, i2) assertRDS(t, c, "3", virtualhosts( - envoy.VirtualHost("kuard.db.gd-ms.com", + v2.VirtualHost("kuard.db.gd-ms.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/80/da39a3ee5e"), @@ -776,23 +776,23 @@ func TestRDSFilter(t *testing.T) { WithPorts(v1.ServicePort{Name: "http", Port: 8009, TargetPort: intstr.FromInt(8080)}) rh.OnAdd(s2) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "5", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/.well-known/acme-challenge/gVJl5NWL2owUqZekjHkt_bo3OHYC2XNDURRRgLI5JTk"), Action: routecluster("nginx-ingress/challenge-service/8009/da39a3ee5e"), }, &envoy_api_v2_route.Route{ Match: routePrefix("/"), // match all - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), }, ), ), - envoy.RouteConfiguration("https/example.com", - envoy.VirtualHost("example.com", + v2.RouteConfiguration("https/example.com", + v2.VirtualHost("example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/.well-known/acme-challenge/gVJl5NWL2owUqZekjHkt_bo3OHYC2XNDURRRgLI5JTk"), Action: routecluster("nginx-ingress/challenge-service/8009/da39a3ee5e"), @@ -864,11 +864,11 @@ func TestDefaultBackendDoesNotOverwriteNamedHost(t *testing.T) { }, }) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "1", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/kuard"), Action: routecluster("default/kuard/8080/da39a3ee5e"), @@ -878,7 +878,7 @@ func TestDefaultBackendDoesNotOverwriteNamedHost(t *testing.T) { Action: routecluster("default/kuard/80/da39a3ee5e"), }, ), - envoy.VirtualHost("test-gui", + v2.VirtualHost("test-gui", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/test-gui/80/da39a3ee5e"), @@ -920,7 +920,7 @@ func TestRDSIngressClassAnnotation(t *testing.T) { } rh.OnAdd(i1) assertRDS(t, c, "1", virtualhosts( - envoy.VirtualHost("*", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/8080/da39a3ee5e"), @@ -981,7 +981,7 @@ func TestRDSIngressClassAnnotation(t *testing.T) { } rh.OnUpdate(i3, i4) assertRDS(t, c, "3", virtualhosts( - envoy.VirtualHost("*", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/8080/da39a3ee5e"), @@ -1006,7 +1006,7 @@ func TestRDSIngressClassAnnotation(t *testing.T) { } rh.OnUpdate(i4, i5) assertRDS(t, c, "4", virtualhosts( - envoy.VirtualHost("*", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/kuard/8080/da39a3ee5e"), @@ -1116,7 +1116,7 @@ func TestRDSIngressSpecMissingHTTPKey(t *testing.T) { WithPorts(v1.ServicePort{Name: "http", Port: 9001, TargetPort: intstr.FromInt(8080)})) assertRDS(t, c, "2", virtualhosts( - envoy.VirtualHost("test2.test.com", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("default/network-test/9001/da39a3ee5e"), @@ -1154,7 +1154,7 @@ func TestRouteWithAServiceWeight(t *testing.T) { rh.OnAdd(p1) assertRDS(t, c, "1", virtualhosts( - envoy.VirtualHost("test2.test.com", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/a"), Action: routecluster("default/kuard/80/da39a3ee5e"), @@ -1188,7 +1188,7 @@ func TestRouteWithAServiceWeight(t *testing.T) { rh.OnUpdate(p1, p2) assertRDS(t, c, "2", virtualhosts( - envoy.VirtualHost("test2.test.com", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/a"), Action: routeweightedcluster( @@ -1242,19 +1242,19 @@ func TestRouteWithTLS(t *testing.T) { rh.OnAdd(p1) // check that ingress_http has been updated. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "1", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), Match: routePrefix("/a"), }, ), ), - envoy.RouteConfiguration("https/test2.test.com", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("https/test2.test.com", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/a"), Action: routecluster("default/kuard/80/da39a3ee5e"), @@ -1321,14 +1321,14 @@ func TestRouteWithTLS_InsecurePaths(t *testing.T) { rh.OnAdd(p1) // check that ingress_http has been updated. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "1", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/secure"), - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), }, &envoy_api_v2_route.Route{ Match: routePrefix("/insecure"), @@ -1336,8 +1336,8 @@ func TestRouteWithTLS_InsecurePaths(t *testing.T) { }, ), ), - envoy.RouteConfiguration("https/test2.test.com", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("https/test2.test.com", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/secure"), Action: routecluster("default/svc2/80/da39a3ee5e"), @@ -1418,23 +1418,23 @@ func TestRouteWithTLS_InsecurePaths_DisablePermitInsecureTrue(t *testing.T) { rh.OnAdd(p1) // check that ingress_http has been updated. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "1", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/secure"), - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), }, &envoy_api_v2_route.Route{ Match: routePrefix("/insecure"), - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), }, ), ), - envoy.RouteConfiguration("https/test2.test.com", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("https/test2.test.com", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/secure"), Action: routecluster("default/svc2/80/da39a3ee5e"), @@ -1488,11 +1488,11 @@ func TestRoutePrefixRouteRegex(t *testing.T) { rh.OnAdd(old) // check that it's been translated correctly. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "1", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routeRegex("/[^/]+/invoices(/.*|/?)"), Action: routecluster("default/kuard/80/da39a3ee5e"), @@ -1512,16 +1512,16 @@ func TestRoutePrefixRouteRegex(t *testing.T) { func assertRDS(t *testing.T, c *Contour, versioninfo string, ingressHTTP, ingressHTTPS []*envoy_api_v2_route.VirtualHost) { t.Helper() - routes := []*v2.RouteConfiguration{ - envoy.RouteConfiguration("ingress_http", ingressHTTP...), + routes := []*envoy_api_v2.RouteConfiguration{ + v2.RouteConfiguration("ingress_http", ingressHTTP...), } for _, vh := range ingressHTTPS { routes = append(routes, - envoy.RouteConfiguration(path.Join("https", vh.Name), vh)) + v2.RouteConfiguration(path.Join("https", vh.Name), vh)) } - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: versioninfo, Resources: routeResources(t, routes...), TypeUrl: routeType, @@ -1535,7 +1535,7 @@ type weightedcluster struct { } func routeRegex(regex string, headers ...dag.HeaderMatchCondition) *envoy_api_v2_route.RouteMatch { - return envoy.RouteMatch(&dag.Route{ + return v2.RouteMatch(&dag.Route{ PathMatchCondition: &dag.RegexMatchCondition{ Regex: regex, }, @@ -1604,7 +1604,7 @@ func TestHTTPProxyRouteWithAServiceWeight(t *testing.T) { rh.OnAdd(proxy1) assertRDS(t, c, "1", virtualhosts( - envoy.VirtualHost("test2.test.com", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/a"), Action: routecluster("default/kuard/80/da39a3ee5e"), @@ -1636,7 +1636,7 @@ func TestHTTPProxyRouteWithAServiceWeight(t *testing.T) { rh.OnUpdate(proxy1, proxy2) assertRDS(t, c, "2", virtualhosts( - envoy.VirtualHost("test2.test.com", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/a"), Action: routeweightedcluster( @@ -1688,19 +1688,19 @@ func TestHTTPProxyRouteWithTLS(t *testing.T) { rh.OnAdd(proxy1) // check that ingress_http has been updated. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "1", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/a"), - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), }, ), ), - envoy.RouteConfiguration("https/test2.test.com", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("https/test2.test.com", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/a"), Action: routecluster("default/kuard/80/da39a3ee5e"), @@ -1763,14 +1763,14 @@ func TestHTTPProxyRouteWithTLS_InsecurePaths(t *testing.T) { rh.OnAdd(proxy1) // check that ingress_http has been updated. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "1", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/secure"), - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), }, &envoy_api_v2_route.Route{ Match: routePrefix("/insecure"), @@ -1778,8 +1778,8 @@ func TestHTTPProxyRouteWithTLS_InsecurePaths(t *testing.T) { }, ), ), - envoy.RouteConfiguration("https/test2.test.com", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("https/test2.test.com", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/secure"), Action: routecluster("default/svc2/80/da39a3ee5e"), @@ -1856,23 +1856,23 @@ func TestHTTPProxyRouteWithTLS_InsecurePaths_DisablePermitInsecureTrue(t *testin rh.OnAdd(proxy1) // check that ingress_http has been updated. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "1", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/secure"), - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), }, &envoy_api_v2_route.Route{ Match: routePrefix("/insecure"), - Action: envoy.UpgradeHTTPS(), + Action: v2.UpgradeHTTPS(), }, ), ), - envoy.RouteConfiguration("https/test2.test.com", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("https/test2.test.com", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/secure"), Action: routecluster("default/svc2/80/da39a3ee5e"), @@ -1935,11 +1935,11 @@ func TestRDSHTTPProxyRootCannotDelegateToAnotherRoot(t *testing.T) { // verify that child's route is present because while it is not possible to // delegate to it, it can host www.containersteve.com. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "2", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("www.containersteve.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("www.containersteve.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routecluster("marketing/green/80/da39a3ee5e"), @@ -2043,10 +2043,10 @@ func TestRDSHTTPProxyDuplicateIncludeConditions(t *testing.T) { rh.OnAdd(proxyChildA) rh.OnAdd(proxyChildB) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "2", Resources: routeResources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, Nonce: "2", diff --git a/internal/featuretests/secrets_test.go b/internal/featuretests/secrets_test.go index d4972aa0da7..1eeeec19efe 100644 --- a/internal/featuretests/secrets_test.go +++ b/internal/featuretests/secrets_test.go @@ -16,10 +16,10 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" "k8s.io/api/networking/v1beta1" @@ -45,7 +45,7 @@ func TestSDSVisibility(t *testing.T) { // assert that the secret is _not_ visible as it is // not referenced by any ingress/httpproxy - c.Request(secretType).Equals(&v2.DiscoveryResponse{ + c.Request(secretType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "0", Resources: nil, TypeUrl: secretType, @@ -81,7 +81,7 @@ func TestSDSVisibility(t *testing.T) { rh.OnAdd(i1) // i1 has a default route to backend:80, but there is no matching service. - c.Request(secretType).Equals(&v2.DiscoveryResponse{ + c.Request(secretType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "1", Resources: nil, TypeUrl: secretType, @@ -137,7 +137,7 @@ func TestSDSShouldNotIncrementVersionNumberForUnrelatedSecret(t *testing.T) { rh.OnAdd(fixture.NewService("backend"). WithPorts(v1.ServicePort{Name: "http", Port: 80})) - c.Request(secretType).Equals(&v2.DiscoveryResponse{ + c.Request(secretType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "2", Resources: resources(t, secret(s1)), TypeUrl: secretType, @@ -147,7 +147,7 @@ func TestSDSShouldNotIncrementVersionNumberForUnrelatedSecret(t *testing.T) { // verify that requesting the same resource without change // does not bump the current version_info. - c.Request(secretType).Equals(&v2.DiscoveryResponse{ + c.Request(secretType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "2", Resources: resources(t, secret(s1)), TypeUrl: secretType, @@ -165,7 +165,7 @@ func TestSDSShouldNotIncrementVersionNumberForUnrelatedSecret(t *testing.T) { } rh.OnAdd(s2) - c.Request(secretType).Equals(&v2.DiscoveryResponse{ + c.Request(secretType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "2", Resources: resources(t, secret(s1)), TypeUrl: secretType, @@ -222,7 +222,7 @@ func TestSDSshouldNotPublishInvalidSecret(t *testing.T) { rh.OnAdd(i1) // SDS should be empty - c.Request(secretType).Equals(&v2.DiscoveryResponse{ + c.Request(secretType).Equals(&envoy_api_v2.DiscoveryResponse{ VersionInfo: "1", Resources: nil, TypeUrl: secretType, @@ -231,7 +231,7 @@ func TestSDSshouldNotPublishInvalidSecret(t *testing.T) { } func secret(sec *v1.Secret) *envoy_api_v2_auth.Secret { - return envoy.Secret(&dag.Secret{ + return v2.Secret(&dag.Secret{ Object: sec, }) } diff --git a/internal/featuretests/tcpproxy_test.go b/internal/featuretests/tcpproxy_test.go index 2ba1a537102..b6235dcfe47 100644 --- a/internal/featuretests/tcpproxy_test.go +++ b/internal/featuretests/tcpproxy_test.go @@ -16,11 +16,11 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_listener "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -75,18 +75,18 @@ func TestTCPProxy(t *testing.T) { } rh.OnAdd(hp1) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: appendFilterChains( filterchaintls("kuard-tcp.example.com", s1, tcpproxy("ingress_https", "default/correct-backend/80/da39a3ee5e"), nil), ), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -94,9 +94,9 @@ func TestTCPProxy(t *testing.T) { }) // check that ingress_http is empty - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -159,18 +159,18 @@ func TestTCPProxyDelegation(t *testing.T) { rh.OnAdd(hp1) rh.OnAdd(hp2) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: appendFilterChains( filterchaintls("kuard-tcp.example.com", s1, tcpproxy("ingress_https", "app/backend/80/da39a3ee5e"), nil), ), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -178,9 +178,9 @@ func TestTCPProxyDelegation(t *testing.T) { }) // check that ingress_http is empty - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -227,23 +227,23 @@ func TestTCPProxyTLSPassthrough(t *testing.T) { } rh.OnAdd(hp1) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ - Filters: envoy.Filters( + Filters: v2.Filters( tcpproxy("ingress_https", "default/correct-backend/80/da39a3ee5e"), ), FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"kuard-tcp.example.com"}, }, }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -251,9 +251,9 @@ func TestTCPProxyTLSPassthrough(t *testing.T) { }) // check that ingress_http is empty - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -304,25 +304,25 @@ func TestTCPProxyTLSBackend(t *testing.T) { rh.OnAdd(svc) rh.OnAdd(hp1) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: appendFilterChains( filterchaintls("k8s.run.ubisoft.org", s1, tcpproxy("ingress_https", svc.Namespace+"/"+svc.Name+"/443/da39a3ee5e"), nil), ), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), TypeUrl: listenerType, }) - c.Request(clusterType).Equals(&v2.DiscoveryResponse{ + c.Request(clusterType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, tlsCluster(cluster( svc.Namespace+"/"+svc.Name+"/443/da39a3ee5e", @@ -334,9 +334,9 @@ func TestTCPProxyTLSBackend(t *testing.T) { }) // check that ingress_http is empty - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -391,30 +391,30 @@ func TestTCPProxyAndHTTPService(t *testing.T) { rh.OnAdd(svc) rh.OnAdd(hp1) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ // ingress_http is present for // http://kuard-tcp.example.com/ -> default/backend:80 Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, - &v2.Listener{ + &envoy_api_v2.Listener{ // ingress_https is present for // kuard-tcp.example.com:443 terminated at envoy then forwarded to default/backend:80 Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: appendFilterChains( filterchaintls("kuard-tcp.example.com", s1, tcpproxy("ingress_https", "default/backend/80/da39a3ee5e"), nil), ), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -425,10 +425,10 @@ func TestTCPProxyAndHTTPService(t *testing.T) { // There should be an unconditional 301 HTTPS upgrade for http://kuard-tcp.example.com/. // ingress_https should be empty, no route should be present as kuard-tcp.example.com:443 // is in tcpproxy mode. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("kuard-tcp.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("kuard-tcp.example.com", upgradeHTTPS(routePrefix("/")), ), ), @@ -487,30 +487,30 @@ func TestTCPProxyAndHTTPServicePermitInsecure(t *testing.T) { rh.OnAdd(svc) rh.OnAdd(hp1) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ // ingress_http is present for // http://kuard-tcp.example.com/ -> default/backend:80 Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, - &v2.Listener{ + &envoy_api_v2.Listener{ // ingress_https is present for // kuard-tcp.example.com:443 terminated at envoy then tcpproxied to default/backend:80 Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: appendFilterChains( filterchaintls("kuard-tcp.example.com", s1, tcpproxy("ingress_https", "default/backend/80/da39a3ee5e"), nil), ), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -520,10 +520,10 @@ func TestTCPProxyAndHTTPServicePermitInsecure(t *testing.T) { // check that routes exist on port 80 (ingress_http) only. // ingress_https should be empty, no route should be present as kuard-tcp.example.com:443 // is in tcpproxy mode. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("kuard-tcp.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("kuard-tcp.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), // this is a regular route cluster, not a 301 upgrade as @@ -576,35 +576,35 @@ func TestTCPProxyTLSPassthroughAndHTTPService(t *testing.T) { rh.OnAdd(svc) rh.OnAdd(hp1) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ // ingress_http is present for // http://kuard-tcp.example.com/ -> default/backend:80 Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, - &v2.Listener{ + &envoy_api_v2.Listener{ // ingress_https is present for // kuard-tcp.example.com:443 direct to default/backend:80 Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ - Filters: envoy.Filters( + Filters: v2.Filters( tcpproxy("ingress_https", "default/backend/80/da39a3ee5e"), ), FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"kuard-tcp.example.com"}, }, }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -612,13 +612,13 @@ func TestTCPProxyTLSPassthroughAndHTTPService(t *testing.T) { }) // check port 80 is open and the route is a 301 upgrade. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", + v2.RouteConfiguration("ingress_http", // 301 upgrade because permitInsecure is false, thus // the route is present on port 80, but unconditionally // upgrades to HTTPS. - envoy.VirtualHost("kuard-tcp.example.com", + v2.VirtualHost("kuard-tcp.example.com", upgradeHTTPS(routePrefix("/")), ), ), @@ -669,37 +669,37 @@ func TestTCPProxyTLSPassthroughAndHTTPServicePermitInsecure(t *testing.T) { rh.OnAdd(svc) rh.OnAdd(hp1) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ // ingress_http is present for // http://kuard-tcp.example.com/ -> default/backend:80, this is not 301 upgraded // because permitInsecure: true is in use. Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, - &v2.Listener{ + &envoy_api_v2.Listener{ // ingress_https is present for // kuard-tcp.example.com:443 direct to default/backend:80, envoy does not handle // the TLS handshake beyond SNI demux because passthrough: true is in use. Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), + Address: v2.SocketAddress("0.0.0.0", 8443), FilterChains: []*envoy_api_v2_listener.FilterChain{{ - Filters: envoy.Filters( + Filters: v2.Filters( tcpproxy("ingress_https", "default/backend/80/da39a3ee5e"), ), FilterChainMatch: &envoy_api_v2_listener.FilterChainMatch{ ServerNames: []string{"kuard-tcp.example.com"}, }, }}, - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, staticListener(), ), @@ -709,10 +709,10 @@ func TestTCPProxyTLSPassthroughAndHTTPServicePermitInsecure(t *testing.T) { // check that routes exist on port 80 (ingress_http) only. // ingress_https should be empty, no route should be present as kuard-tcp.example.com:443 // is in tcpproxy mode. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("kuard-tcp.example.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("kuard-tcp.example.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), // not a 301 upgrade because permitInsecure: true is in use. @@ -773,7 +773,7 @@ func TestTCPProxyMissingTLS(t *testing.T) { rh.OnAdd(svc) rh.OnAdd(hp1) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, // ingress_http and ingress_https should be missing // as hp1 is not valid. @@ -782,11 +782,11 @@ func TestTCPProxyMissingTLS(t *testing.T) { TypeUrl: listenerType, }) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, // ingress_http and ingress_https should be empty // as hp1 is not valid. - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -819,7 +819,7 @@ func TestTCPProxyMissingTLS(t *testing.T) { } rh.OnUpdate(hp1, hp2) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, // ingress_http and ingress_https should be missing // as hp2 is not valid. @@ -828,11 +828,11 @@ func TestTCPProxyMissingTLS(t *testing.T) { TypeUrl: listenerType, }) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, // ingress_http and ingress_https should be empty // as hp2 is not valid. - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) diff --git a/internal/featuretests/timeoutpolicy_test.go b/internal/featuretests/timeoutpolicy_test.go index cb2ff1a5b97..91cbf65413e 100644 --- a/internal/featuretests/timeoutpolicy_test.go +++ b/internal/featuretests/timeoutpolicy_test.go @@ -17,11 +17,11 @@ import ( "testing" "time" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/internal/contour" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" "k8s.io/api/networking/v1beta1" @@ -52,10 +52,10 @@ func TestTimeoutPolicyRequestTimeout(t *testing.T) { rh.OnAdd(i1) // check annotation with explicit timeout is propagated - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withResponseTimeout(routeCluster("default/kuard/8080/da39a3ee5e"), 80*time.Second), @@ -79,10 +79,10 @@ func TestTimeoutPolicyRequestTimeout(t *testing.T) { rh.OnUpdate(i1, i2) // check annotation with infinite timeout is propogated - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withResponseTimeout(routeCluster("default/kuard/8080/da39a3ee5e"), 0), // zero means infinity @@ -106,10 +106,10 @@ func TestTimeoutPolicyRequestTimeout(t *testing.T) { rh.OnUpdate(i2, i3) // check annotation with malformed timeout is not propagated - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: routeCluster("default/kuard/8080/da39a3ee5e"), @@ -134,10 +134,10 @@ func TestTimeoutPolicyRequestTimeout(t *testing.T) { rh.OnUpdate(i3, i4) // assert that projectcontour.io/response-timeout takes priority. - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("*", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("*", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withResponseTimeout(routeCluster("default/kuard/8080/da39a3ee5e"), 99*time.Second), @@ -171,9 +171,9 @@ func TestTimeoutPolicyRequestTimeout(t *testing.T) { rh.OnAdd(p1) // check timeout policy with malformed response timeout is not propogated - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -197,10 +197,10 @@ func TestTimeoutPolicyRequestTimeout(t *testing.T) { rh.OnUpdate(p1, p2) // check timeout policy with response timeout is propogated correctly - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withResponseTimeout(routeCluster("default/kuard/8080/da39a3ee5e"), 180*time.Second), @@ -230,10 +230,10 @@ func TestTimeoutPolicyRequestTimeout(t *testing.T) { rh.OnUpdate(p2, p3) // check timeout policy with explicit infine response timeout is propogated as infinity - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withResponseTimeout(routeCluster("default/kuard/8080/da39a3ee5e"), 0), // zero means infinity @@ -275,9 +275,9 @@ func TestTimeoutPolicyIdleTimeout(t *testing.T) { rh.OnAdd(p1) // check timeout policy with malformed response timeout is not propogated - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http"), + v2.RouteConfiguration("ingress_http"), ), TypeUrl: routeType, }) @@ -301,10 +301,10 @@ func TestTimeoutPolicyIdleTimeout(t *testing.T) { rh.OnUpdate(p1, p2) // check timeout policy with response timeout is propogated correctly - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withIdleTimeout(routeCluster("default/kuard/8080/da39a3ee5e"), 180*time.Second), @@ -334,10 +334,10 @@ func TestTimeoutPolicyIdleTimeout(t *testing.T) { rh.OnUpdate(p2, p3) // check timeout policy with explicit infine response timeout is propogated as infinity - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("test2.test.com", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("test2.test.com", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withIdleTimeout(routeCluster("default/kuard/8080/da39a3ee5e"), 0), // zero means infinity diff --git a/internal/featuretests/timeouts_test.go b/internal/featuretests/timeouts_test.go index 011c16974f4..774aea14284 100644 --- a/internal/featuretests/timeouts_test.go +++ b/internal/featuretests/timeouts_test.go @@ -17,10 +17,10 @@ import ( "testing" "time" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/internal/contour" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" "github.com/projectcontour/contour/internal/timeout" v1 "k8s.io/api/core/v1" @@ -56,17 +56,17 @@ func TestTimeoutsNotSpecified(t *testing.T) { } rh.OnAdd(hp1) - c.Request(listenerType, contour.ENVOY_HTTP_LISTENER).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, contour.ENVOY_HTTP_LISTENER).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: contour.ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManagerBuilder(). + Address: v2.SocketAddress("0.0.0.0", 8080), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + FilterChains: v2.FilterChains(v2.HTTPConnectionManagerBuilder(). RouteConfigName(contour.ENVOY_HTTP_LISTENER). MetricsPrefix(contour.ENVOY_HTTP_LISTENER). - AccessLoggers(envoy.FileAccessLogEnvoy(contour.DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(contour.DEFAULT_HTTP_ACCESS_LOG)). DefaultFilters(). Get(), ), @@ -109,17 +109,17 @@ func TestNonZeroTimeoutsSpecified(t *testing.T) { } rh.OnAdd(hp1) - c.Request(listenerType, contour.ENVOY_HTTP_LISTENER).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, contour.ENVOY_HTTP_LISTENER).Equals(&envoy_api_v2.DiscoveryResponse{ TypeUrl: listenerType, Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: contour.ENVOY_HTTP_LISTENER, - Address: envoy.SocketAddress("0.0.0.0", 8080), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), - FilterChains: envoy.FilterChains(envoy.HTTPConnectionManagerBuilder(). + Address: v2.SocketAddress("0.0.0.0", 8080), + SocketOptions: v2.TCPKeepaliveSocketOptions(), + FilterChains: v2.FilterChains(v2.HTTPConnectionManagerBuilder(). RouteConfigName(contour.ENVOY_HTTP_LISTENER). MetricsPrefix(contour.ENVOY_HTTP_LISTENER). - AccessLoggers(envoy.FileAccessLogEnvoy(contour.DEFAULT_HTTP_ACCESS_LOG)). + AccessLoggers(v2.FileAccessLogEnvoy(contour.DEFAULT_HTTP_ACCESS_LOG)). DefaultFilters(). ConnectionIdleTimeout(timeout.DurationSetting(7 * time.Second)). StreamIdleTimeout(timeout.DurationSetting(70 * time.Second)). diff --git a/internal/featuretests/tlscertificatedelegation_test.go b/internal/featuretests/tlscertificatedelegation_test.go index 876f58fe23b..c76c7ab6fda 100644 --- a/internal/featuretests/tlscertificatedelegation_test.go +++ b/internal/featuretests/tlscertificatedelegation_test.go @@ -16,9 +16,9 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -29,7 +29,7 @@ func TestTLSCertificateDelegation(t *testing.T) { defer done() // assert that there is only a static listener - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, staticListener(), ), @@ -79,7 +79,7 @@ func TestTLSCertificateDelegation(t *testing.T) { rh.OnAdd(p1) // assert there are no listeners - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, staticListener(), ), @@ -103,30 +103,30 @@ func TestTLSCertificateDelegation(t *testing.T) { } rh.OnAdd(t1) - ingress_http := &v2.Listener{ + ingress_http := &envoy_api_v2.Listener{ Name: "ingress_http", - Address: envoy.SocketAddress("0.0.0.0", 8080), - FilterChains: envoy.FilterChains( - envoy.HTTPConnectionManager("ingress_http", envoy.FileAccessLogEnvoy("/dev/stdout"), 0), + Address: v2.SocketAddress("0.0.0.0", 8080), + FilterChains: v2.FilterChains( + v2.HTTPConnectionManager("ingress_http", v2.FileAccessLogEnvoy("/dev/stdout"), 0), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } - ingress_https := &v2.Listener{ + ingress_https := &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: appendFilterChains( filterchaintls("example.com", sec1, httpsFilterFor("example.com"), nil, "h2", "http/1.1"), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, ingress_http, ingress_https, @@ -152,7 +152,7 @@ func TestTLSCertificateDelegation(t *testing.T) { } rh.OnUpdate(t1, t2) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, ingress_http, ingress_https, @@ -178,7 +178,7 @@ func TestTLSCertificateDelegation(t *testing.T) { } rh.OnUpdate(t2, t3) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, staticListener(), ), @@ -202,7 +202,7 @@ func TestTLSCertificateDelegation(t *testing.T) { } rh.OnUpdate(t3, t4) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, staticListener(), ), @@ -237,7 +237,7 @@ func TestTLSCertificateDelegation(t *testing.T) { rh.OnAdd(hp1) // assert there are no listeners - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, staticListener(), ), @@ -260,7 +260,7 @@ func TestTLSCertificateDelegation(t *testing.T) { } rh.OnAdd(t5) - c.Request(listenerType).Equals(&v2.DiscoveryResponse{ + c.Request(listenerType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, ingress_http, ingress_https, diff --git a/internal/featuretests/tlsprotocolversion_test.go b/internal/featuretests/tlsprotocolversion_test.go index 35cc2bb0d6e..fa87b7c6afc 100644 --- a/internal/featuretests/tlsprotocolversion_test.go +++ b/internal/featuretests/tlsprotocolversion_test.go @@ -16,12 +16,12 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" envoy_api_v2_listener "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/internal/dag" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" "k8s.io/api/networking/v1beta1" @@ -70,20 +70,20 @@ func TestTLSMinimumProtocolVersion(t *testing.T) { } rh.OnAdd(i1) - c.Request(listenerType, "ingress_https").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "ingress_https").Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - &v2.Listener{ + &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: appendFilterChains( filterchaintls("kuard.example.com", sec1, httpsFilterFor("kuard.example.com"), nil, "h2", "http/1.1"), ), - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), }, ), TypeUrl: listenerType, @@ -116,27 +116,27 @@ func TestTLSMinimumProtocolVersion(t *testing.T) { } rh.OnUpdate(i1, i2) - l1 := &v2.Listener{ + l1 := &envoy_api_v2.Listener{ Name: "ingress_https", - Address: envoy.SocketAddress("0.0.0.0", 8443), - ListenerFilters: envoy.ListenerFilters( - envoy.TLSInspector(), + Address: v2.SocketAddress("0.0.0.0", 8443), + ListenerFilters: v2.ListenerFilters( + v2.TLSInspector(), ), FilterChains: []*envoy_api_v2_listener.FilterChain{ - envoy.FilterChainTLS( + v2.FilterChainTLS( "kuard.example.com", - envoy.DownstreamTLSContext( + v2.DownstreamTLSContext( &dag.Secret{Object: sec1}, envoy_api_v2_auth.TlsParameters_TLSv1_3, nil, "h2", "http/1.1"), - envoy.Filters(httpsFilterFor("kuard.example.com")), + v2.Filters(httpsFilterFor("kuard.example.com")), ), }, - SocketOptions: envoy.TCPKeepaliveSocketOptions(), + SocketOptions: v2.TCPKeepaliveSocketOptions(), } - c.Request(listenerType, "ingress_https").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "ingress_https").Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, l1, ), @@ -169,7 +169,7 @@ func TestTLSMinimumProtocolVersion(t *testing.T) { } rh.OnAdd(hp1) - c.Request(listenerType, "ingress_https").Equals(&v2.DiscoveryResponse{ + c.Request(listenerType, "ingress_https").Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, l1, ), diff --git a/internal/featuretests/websockets_test.go b/internal/featuretests/websockets_test.go index 030df0848c8..4743e915f70 100644 --- a/internal/featuretests/websockets_test.go +++ b/internal/featuretests/websockets_test.go @@ -16,10 +16,10 @@ package featuretests import ( "testing" - v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" + envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" envoy_api_v2_route "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" projcontour "github.com/projectcontour/contour/apis/projectcontour/v1" - "github.com/projectcontour/contour/internal/envoy" + v2 "github.com/projectcontour/contour/internal/envoy/v2" "github.com/projectcontour/contour/internal/fixture" v1 "k8s.io/api/core/v1" "k8s.io/api/networking/v1beta1" @@ -63,10 +63,10 @@ func TestWebsocketsIngress(t *testing.T) { rh.OnAdd(i1) // check legacy websocket annotation - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("websocket.hello.world", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("websocket.hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/"), Action: withWebsocket(routeCluster("default/ws/80/da39a3ee5e")), @@ -105,10 +105,10 @@ func TestWebsocketsIngress(t *testing.T) { rh.OnUpdate(i1, i2) // check websocket annotation - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("websocket.hello.world", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("websocket.hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/ws2"), Action: withWebsocket(routeCluster("default/ws/80/da39a3ee5e")), @@ -164,10 +164,10 @@ func TestWebsocketHTTPProxy(t *testing.T) { } rh.OnAdd(hp1) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("websocket.hello.world", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("websocket.hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/ws-2"), Action: withWebsocket(routeCluster("default/ws/80/da39a3ee5e")), @@ -221,10 +221,10 @@ func TestWebsocketHTTPProxy(t *testing.T) { } rh.OnUpdate(hp1, hp2) - c.Request(routeType).Equals(&v2.DiscoveryResponse{ + c.Request(routeType).Equals(&envoy_api_v2.DiscoveryResponse{ Resources: resources(t, - envoy.RouteConfiguration("ingress_http", - envoy.VirtualHost("websocket.hello.world", + v2.RouteConfiguration("ingress_http", + v2.VirtualHost("websocket.hello.world", &envoy_api_v2_route.Route{ Match: routePrefix("/ws-2"), Action: withWebsocket(routeCluster("default/ws/80/da39a3ee5e")),