Skip to content

Commit

Permalink
internal: Refactor common bits from envoy/listeners
Browse files Browse the repository at this point in the history
Updates projectcontour#1898

Signed-off-by: Steve Sloka <slokas@vmware.com>
  • Loading branch information
stevesloka committed Nov 11, 2020
1 parent 2885e38 commit 044e6e1
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 93 deletions.
12 changes: 6 additions & 6 deletions cmd/contour/servecontext.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
"strings"
"time"

envoy_v2 "github.com/projectcontour/contour/internal/envoy/v2"
"github.com/projectcontour/contour/internal/envoy"
xdscache_v2 "github.com/projectcontour/contour/internal/xdscache/v2"
"github.com/projectcontour/contour/pkg/config"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -234,19 +234,19 @@ func (ctx *serveContext) proxyRootNamespaces() []string {

// parseDefaultHTTPVersions parses a list of supported HTTP versions
// (of the form "HTTP/xx") into a slice of unique version constants.
func parseDefaultHTTPVersions(versions []config.HTTPVersionType) []envoy_v2.HTTPVersionType {
wanted := map[envoy_v2.HTTPVersionType]struct{}{}
func parseDefaultHTTPVersions(versions []config.HTTPVersionType) []envoy.HTTPVersionType {
wanted := map[envoy.HTTPVersionType]struct{}{}

for _, v := range versions {
switch v {
case config.HTTPVersion1:
wanted[envoy_v2.HTTPVersion1] = struct{}{}
wanted[envoy.HTTPVersion1] = struct{}{}
case config.HTTPVersion2:
wanted[envoy_v2.HTTPVersion2] = struct{}{}
wanted[envoy.HTTPVersion2] = struct{}{}
}
}

var parsed []envoy_v2.HTTPVersionType
var parsed []envoy.HTTPVersionType
for k := range wanted {
parsed = append(parsed, k)

Expand Down
11 changes: 6 additions & 5 deletions cmd/contour/servecontext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ import (
"testing"
"time"

envoy_v2 "github.com/projectcontour/contour/internal/envoy/v2"
"github.com/projectcontour/contour/internal/envoy"

"github.com/projectcontour/contour/internal/fixture"
"github.com/projectcontour/contour/pkg/config"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -327,25 +328,25 @@ func peekError(conn net.Conn) error {
func TestParseHTTPVersions(t *testing.T) {
cases := map[string]struct {
versions []config.HTTPVersionType
parseVersions []envoy_v2.HTTPVersionType
parseVersions []envoy.HTTPVersionType
}{
"empty": {
versions: []config.HTTPVersionType{},
parseVersions: nil,
},
"http/1.1": {
versions: []config.HTTPVersionType{config.HTTPVersion1},
parseVersions: []envoy_v2.HTTPVersionType{envoy_v2.HTTPVersion1},
parseVersions: []envoy.HTTPVersionType{envoy.HTTPVersion1},
},
"http/1.1+http/2": {
versions: []config.HTTPVersionType{config.HTTPVersion1, config.HTTPVersion2},
parseVersions: []envoy_v2.HTTPVersionType{envoy_v2.HTTPVersion1, envoy_v2.HTTPVersion2},
parseVersions: []envoy.HTTPVersionType{envoy.HTTPVersion1, envoy.HTTPVersion2},
},
"http/1.1+http/2 duplicated": {
versions: []config.HTTPVersionType{
config.HTTPVersion1, config.HTTPVersion2,
config.HTTPVersion1, config.HTTPVersion2},
parseVersions: []envoy_v2.HTTPVersionType{envoy_v2.HTTPVersion1, envoy_v2.HTTPVersion2},
parseVersions: []envoy.HTTPVersionType{envoy.HTTPVersion1, envoy.HTTPVersion2},
},
}

Expand Down
79 changes: 79 additions & 0 deletions internal/envoy/listener.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// 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 (
"log"

http "github.com/envoyproxy/go-control-plane/envoy/config/filter/network/http_connection_manager/v2"
)

type HTTPVersionType = http.HttpConnectionManager_CodecType

const (
HTTPVersionAuto HTTPVersionType = http.HttpConnectionManager_AUTO
HTTPVersion1 HTTPVersionType = http.HttpConnectionManager_HTTP1
HTTPVersion2 HTTPVersionType = http.HttpConnectionManager_HTTP2
HTTPVersion3 HTTPVersionType = http.HttpConnectionManager_HTTP3
)

// ProtoNamesForVersions returns the slice of ALPN protocol names for the give HTTP versions.
func ProtoNamesForVersions(versions ...HTTPVersionType) []string {
protocols := map[HTTPVersionType]string{
HTTPVersion1: "http/1.1",
HTTPVersion2: "h2",
HTTPVersion3: "",
}
defaultVersions := []string{"h2", "http/1.1"}
wantedVersions := map[HTTPVersionType]struct{}{}

if versions == nil {
return defaultVersions
}

for _, v := range versions {
wantedVersions[v] = struct{}{}
}

var alpn []string

// Check for versions in preference order.
for _, v := range []HTTPVersionType{HTTPVersionAuto, HTTPVersion2, HTTPVersion1} {
if _, ok := wantedVersions[v]; ok {
if v == HTTPVersionAuto {
return defaultVersions
}

log.Printf("wanted %d -> %s", v, protocols[v])
alpn = append(alpn, protocols[v])
}
}

return alpn
}

// 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
}
}
36 changes: 36 additions & 0 deletions internal/envoy/listener_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// 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"

"github.com/stretchr/testify/assert"
)

func TestCodecForVersions(t *testing.T) {
assert.Equal(t, CodecForVersions(HTTPVersionAuto), HTTPVersionAuto)
assert.Equal(t, CodecForVersions(HTTPVersion1, HTTPVersion2), HTTPVersionAuto)
assert.Equal(t, CodecForVersions(HTTPVersion1), HTTPVersion1)
assert.Equal(t, CodecForVersions(HTTPVersion2), HTTPVersion2)
}

func TestProtoNamesForVersions(t *testing.T) {
assert.Equal(t, ProtoNamesForVersions(), []string{"h2", "http/1.1"})
assert.Equal(t, ProtoNamesForVersions(HTTPVersionAuto), []string{"h2", "http/1.1"})
assert.Equal(t, ProtoNamesForVersions(HTTPVersion1), []string{"http/1.1"})
assert.Equal(t, ProtoNamesForVersions(HTTPVersion2), []string{"h2"})
assert.Equal(t, ProtoNamesForVersions(HTTPVersion3), []string(nil))
assert.Equal(t, ProtoNamesForVersions(HTTPVersion1, HTTPVersion2), []string{"h2", "http/1.1"})
}
64 changes: 2 additions & 62 deletions internal/envoy/v2/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ package v2

import (
"fmt"
"log"
"sort"
"strings"
"time"
Expand All @@ -38,65 +37,6 @@ import (
"github.com/projectcontour/contour/internal/timeout"
)

type HTTPVersionType = http.HttpConnectionManager_CodecType

const (
HTTPVersionAuto HTTPVersionType = http.HttpConnectionManager_AUTO
HTTPVersion1 HTTPVersionType = http.HttpConnectionManager_HTTP1
HTTPVersion2 HTTPVersionType = http.HttpConnectionManager_HTTP2
HTTPVersion3 HTTPVersionType = http.HttpConnectionManager_HTTP3
)

// ProtoNamesForVersions returns the slice of ALPN protocol names for the give HTTP versions.
func ProtoNamesForVersions(versions ...HTTPVersionType) []string {
protocols := map[HTTPVersionType]string{
HTTPVersion1: "http/1.1",
HTTPVersion2: "h2",
HTTPVersion3: "",
}
defaultVersions := []string{"h2", "http/1.1"}
wantedVersions := map[HTTPVersionType]struct{}{}

if versions == nil {
return defaultVersions
}

for _, v := range versions {
wantedVersions[v] = struct{}{}
}

var alpn []string

// Check for versions in preference order.
for _, v := range []HTTPVersionType{HTTPVersionAuto, HTTPVersion2, HTTPVersion1} {
if _, ok := wantedVersions[v]; ok {
if v == HTTPVersionAuto {
return defaultVersions
}

log.Printf("wanted %d -> %s", v, protocols[v])
alpn = append(alpn, protocols[v])
}
}

return alpn
}

// 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
}
}

// TLSInspector returns a new TLS inspector listener filter.
func TLSInspector() *envoy_api_v2_listener.ListenerFilter {
return &envoy_api_v2_listener.ListenerFilter{
Expand Down Expand Up @@ -140,7 +80,7 @@ type httpConnectionManagerBuilder struct {
maxConnectionDuration timeout.Setting
connectionShutdownGracePeriod timeout.Setting
filters []*http.HttpFilter
codec HTTPVersionType // Note the zero value is AUTO, which is the default we want.
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
Expand All @@ -161,7 +101,7 @@ func (b *httpConnectionManagerBuilder) MetricsPrefix(prefix string) *httpConnect
}

// Codec sets the HTTP codec for the manager. The default is AUTO.
func (b *httpConnectionManagerBuilder) Codec(codecType HTTPVersionType) *httpConnectionManagerBuilder {
func (b *httpConnectionManagerBuilder) Codec(codecType envoy.HTTPVersionType) *httpConnectionManagerBuilder {
b.codec = codecType
return b
}
Expand Down
16 changes: 0 additions & 16 deletions internal/envoy/v2/listener_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,6 @@ import (
"k8s.io/apimachinery/pkg/util/intstr"
)

func TestCodecForVersions(t *testing.T) {
assert.Equal(t, CodecForVersions(HTTPVersionAuto), HTTPVersionAuto)
assert.Equal(t, CodecForVersions(HTTPVersion1, HTTPVersion2), HTTPVersionAuto)
assert.Equal(t, CodecForVersions(HTTPVersion1), HTTPVersion1)
assert.Equal(t, CodecForVersions(HTTPVersion2), HTTPVersion2)
}

func TestProtoNamesForVersions(t *testing.T) {
assert.Equal(t, ProtoNamesForVersions(), []string{"h2", "http/1.1"})
assert.Equal(t, ProtoNamesForVersions(HTTPVersionAuto), []string{"h2", "http/1.1"})
assert.Equal(t, ProtoNamesForVersions(HTTPVersion1), []string{"http/1.1"})
assert.Equal(t, ProtoNamesForVersions(HTTPVersion2), []string{"h2"})
assert.Equal(t, ProtoNamesForVersions(HTTPVersion3), []string(nil))
assert.Equal(t, ProtoNamesForVersions(HTTPVersion1, HTTPVersion2), []string{"h2", "http/1.1"})
}

func TestListener(t *testing.T) {
tests := map[string]struct {
name, address string
Expand Down
14 changes: 14 additions & 0 deletions internal/envoy/v3/listener_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright Project Contour Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package v3
9 changes: 5 additions & 4 deletions internal/xdscache/v2/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/golang/protobuf/proto"
"github.com/projectcontour/contour/internal/contour"
"github.com/projectcontour/contour/internal/dag"
"github.com/projectcontour/contour/internal/envoy"
envoy_v2 "github.com/projectcontour/contour/internal/envoy/v2"
"github.com/projectcontour/contour/internal/protobuf"
"github.com/projectcontour/contour/internal/sorter"
Expand Down Expand Up @@ -86,7 +87,7 @@ type ListenerConfig struct {
// supported versions are accepted. This is applied to both
// HTTP and HTTPS listeners but has practical effect only for
// HTTPS, because we don't support h2c.
DefaultHTTPVersions []envoy_v2.HTTPVersionType
DefaultHTTPVersions []envoy.HTTPVersionType

// AccessLogType defines if Envoy logs should be output as Envoy's default or JSON.
// Valid values: 'envoy', 'json'
Expand Down Expand Up @@ -317,7 +318,7 @@ func visitListeners(root dag.Vertex, lvc *ListenerConfig) map[string]*envoy_api_
if lv.http {
// Add a listener if there are vhosts bound to http.
cm := envoy_v2.HTTPConnectionManagerBuilder().
Codec(envoy_v2.CodecForVersions(lv.DefaultHTTPVersions...)).
Codec(envoy.CodecForVersions(lv.DefaultHTTPVersions...)).
DefaultFilters().
RouteConfigName(ENVOY_HTTP_LISTENER).
MetricsPrefix(ENVOY_HTTP_LISTENER).
Expand Down Expand Up @@ -401,7 +402,7 @@ func (v *listenerVisitor) visit(vertex dag.Vertex) {
// coded into monitoring dashboards.
filters = envoy_v2.Filters(
envoy_v2.HTTPConnectionManagerBuilder().
Codec(envoy_v2.CodecForVersions(v.DefaultHTTPVersions...)).
Codec(envoy.CodecForVersions(v.DefaultHTTPVersions...)).
AddFilter(envoy_v2.FilterMisdirectedRequests(vh.VirtualHost.Name)).
DefaultFilters().
AddFilter(authFilter).
Expand All @@ -416,7 +417,7 @@ func (v *listenerVisitor) visit(vertex dag.Vertex) {
Get(),
)

alpnProtos = envoy_v2.ProtoNamesForVersions(v.DefaultHTTPVersions...)
alpnProtos = envoy.ProtoNamesForVersions(v.DefaultHTTPVersions...)
} else {
filters = envoy_v2.Filters(
envoy_v2.TCPProxy(ENVOY_HTTPS_LISTENER,
Expand Down

0 comments on commit 044e6e1

Please sign in to comment.