support dynamically defined rds

This commit is contained in:
Caleb Doxsey 2023-04-13 17:03:00 -06:00
parent 4d3c2be99b
commit a8350a17e3
3 changed files with 60 additions and 39 deletions

View file

@ -166,7 +166,7 @@ func (b *Builder) BuildBootstrapStaticResources(
return nil, fmt.Errorf("error building clusters: %w", err)
}
staticResources.Listeners, err = b.BuildListeners(ctx, cfg)
staticResources.Listeners, err = b.BuildListeners(ctx, cfg, fullyStatic)
if err != nil {
return nil, fmt.Errorf("error building listeners: %w", err)
}

View file

@ -56,11 +56,15 @@ func init() {
}
// BuildListeners builds envoy listeners from the given config.
func (b *Builder) BuildListeners(ctx context.Context, cfg *config.Config) ([]*envoy_config_listener_v3.Listener, error) {
func (b *Builder) BuildListeners(
ctx context.Context,
cfg *config.Config,
fullyStatic bool,
) ([]*envoy_config_listener_v3.Listener, error) {
var listeners []*envoy_config_listener_v3.Listener
if config.IsAuthenticate(cfg.Options.Services) || config.IsProxy(cfg.Options.Services) {
li, err := b.buildMainListener(ctx, cfg)
li, err := b.buildMainListener(ctx, cfg, fullyStatic)
if err != nil {
return nil, err
}
@ -128,7 +132,11 @@ func (b *Builder) buildTLSSocket(ctx context.Context, cfg *config.Config, certs
}, nil
}
func (b *Builder) buildMainListener(ctx context.Context, cfg *config.Config) (*envoy_config_listener_v3.Listener, error) {
func (b *Builder) buildMainListener(
ctx context.Context,
cfg *config.Config,
fullyStatic bool,
) (*envoy_config_listener_v3.Listener, error) {
li := newEnvoyListener("http-ingress")
if cfg.Options.UseProxyProtocol {
li.ListenerFilters = append(li.ListenerFilters, ProxyProtocolFilter())
@ -137,7 +145,7 @@ func (b *Builder) buildMainListener(ctx context.Context, cfg *config.Config) (*e
if cfg.Options.InsecureServer {
li.Address = buildAddress(cfg.Options.Addr, 80)
filter, err := b.buildMainHTTPConnectionManagerFilter(cfg.Options)
filter, err := b.buildMainHTTPConnectionManagerFilter(ctx, cfg, fullyStatic)
if err != nil {
return nil, err
}
@ -156,7 +164,7 @@ func (b *Builder) buildMainListener(ctx context.Context, cfg *config.Config) (*e
return nil, err
}
filter, err := b.buildMainHTTPConnectionManagerFilter(cfg.Options, allCertificates...)
filter, err := b.buildMainHTTPConnectionManagerFilter(ctx, cfg, fullyStatic)
if err != nil {
return nil, err
}
@ -254,12 +262,13 @@ func (b *Builder) buildMetricsListener(cfg *config.Config) (*envoy_config_listen
}
func (b *Builder) buildMainHTTPConnectionManagerFilter(
options *config.Options,
certs ...tls.Certificate,
ctx context.Context,
cfg *config.Config,
fullyStatic bool,
) (*envoy_config_listener_v3.Filter, error) {
var grpcClientTimeout *durationpb.Duration
if options.GRPCClientTimeout != 0 {
grpcClientTimeout = durationpb.New(options.GRPCClientTimeout)
if cfg.Options.GRPCClientTimeout != 0 {
grpcClientTimeout = durationpb.New(cfg.Options.GRPCClientTimeout)
} else {
grpcClientTimeout = durationpb.New(30 * time.Second)
}
@ -274,21 +283,48 @@ func (b *Builder) buildMainHTTPConnectionManagerFilter(
filters = append(filters, HTTPRouterFilter())
var maxStreamDuration *durationpb.Duration
if options.WriteTimeout > 0 {
maxStreamDuration = durationpb.New(options.WriteTimeout)
if cfg.Options.WriteTimeout > 0 {
maxStreamDuration = durationpb.New(cfg.Options.WriteTimeout)
}
tracingProvider, err := buildTracingHTTP(options)
tracingProvider, err := buildTracingHTTP(cfg.Options)
if err != nil {
return nil, err
}
return HTTPConnectionManagerFilter(&envoy_http_connection_manager.HttpConnectionManager{
mgr := &envoy_http_connection_manager.HttpConnectionManager{
AlwaysSetRequestIdInResponse: true,
CodecType: cfg.Options.GetCodecType().ToEnvoy(),
StatPrefix: "ingress",
HttpFilters: filters,
AccessLog: buildAccessLogs(cfg.Options),
CommonHttpProtocolOptions: &envoy_config_core_v3.HttpProtocolOptions{
IdleTimeout: durationpb.New(cfg.Options.IdleTimeout),
MaxStreamDuration: maxStreamDuration,
},
HttpProtocolOptions: http1ProtocolOptions,
RequestTimeout: durationpb.New(cfg.Options.ReadTimeout),
Tracing: &envoy_http_connection_manager.HttpConnectionManager_Tracing{
RandomSampling: &envoy_type_v3.Percent{Value: cfg.Options.TracingSampleRate * 100},
Provider: tracingProvider,
},
// See https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-forwarded-for
UseRemoteAddress: &wrappers.BoolValue{Value: true},
SkipXffAppend: cfg.Options.SkipXffAppend,
XffNumTrustedHops: cfg.Options.XffNumTrustedHops,
LocalReplyConfig: b.buildLocalReplyConfig(cfg.Options, false),
}
CodecType: options.GetCodecType().ToEnvoy(),
StatPrefix: "ingress",
RouteSpecifier: &envoy_http_connection_manager.HttpConnectionManager_Rds{
if fullyStatic {
routeConfiguration, err := b.buildMainRouteConfiguration(ctx, cfg)
if err != nil {
return nil, err
}
mgr.RouteSpecifier = &envoy_http_connection_manager.HttpConnectionManager_RouteConfig{
RouteConfig: routeConfiguration,
}
} else {
mgr.RouteSpecifier = &envoy_http_connection_manager.HttpConnectionManager_Rds{
Rds: &envoy_http_connection_manager.Rds{
ConfigSource: &envoy_config_core_v3.ConfigSource{
ResourceApiVersion: envoy_config_core_v3.ApiVersion_V3,
@ -296,25 +332,10 @@ func (b *Builder) buildMainHTTPConnectionManagerFilter(
},
RouteConfigName: "main",
},
},
HttpFilters: filters,
AccessLog: buildAccessLogs(options),
CommonHttpProtocolOptions: &envoy_config_core_v3.HttpProtocolOptions{
IdleTimeout: durationpb.New(options.IdleTimeout),
MaxStreamDuration: maxStreamDuration,
},
HttpProtocolOptions: http1ProtocolOptions,
RequestTimeout: durationpb.New(options.ReadTimeout),
Tracing: &envoy_http_connection_manager.HttpConnectionManager_Tracing{
RandomSampling: &envoy_type_v3.Percent{Value: options.TracingSampleRate * 100},
Provider: tracingProvider,
},
// See https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-forwarded-for
UseRemoteAddress: &wrappers.BoolValue{Value: true},
SkipXffAppend: options.SkipXffAppend,
XffNumTrustedHops: options.XffNumTrustedHops,
LocalReplyConfig: b.buildLocalReplyConfig(options, false),
}), nil
}
}
return HTTPConnectionManagerFilter(mgr), nil
}
func (b *Builder) buildMetricsHTTPConnectionManagerFilter() (*envoy_config_listener_v3.Filter, error) {

View file

@ -65,7 +65,7 @@ func Test_buildMainHTTPConnectionManagerFilter(t *testing.T) {
options.SkipXffAppend = true
options.XffNumTrustedHops = 1
options.AuthenticateURLString = "https://authenticate.example.com"
filter, err := b.buildMainHTTPConnectionManagerFilter(options)
filter, err := b.buildMainHTTPConnectionManagerFilter(context.Background(), &config.Config{Options: options}, false)
require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, testData(t, "main_http_connection_manager_filter.json", nil), filter)
}
@ -353,7 +353,7 @@ func Test_requireProxyProtocol(t *testing.T) {
li, err := b.buildMainListener(context.Background(), &config.Config{Options: &config.Options{
UseProxyProtocol: true,
InsecureServer: true,
}})
}}, false)
require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, `[
{
@ -368,7 +368,7 @@ func Test_requireProxyProtocol(t *testing.T) {
li, err := b.buildMainListener(context.Background(), &config.Config{Options: &config.Options{
UseProxyProtocol: false,
InsecureServer: true,
}})
}}, false)
require.NoError(t, err)
assert.Len(t, li.GetListenerFilters(), 0)
})