Fix enable opentracing per location (#4983)

This commit is contained in:
Manuel Alejandro de Brito Fontes 2020-01-29 12:20:05 -03:00 committed by GitHub
parent 19e9e9d7ed
commit 5d05e19cc3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 147 additions and 35 deletions

View file

@ -30,10 +30,15 @@ type opentracing struct {
// Config contains the configuration to be used in the Ingress // Config contains the configuration to be used in the Ingress
type Config struct { type Config struct {
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
Set bool `json:"set"`
} }
// Equal tests for equality between two Config types // Equal tests for equality between two Config types
func (bd1 *Config) Equal(bd2 *Config) bool { func (bd1 *Config) Equal(bd2 *Config) bool {
if bd1.Set != bd2.Set {
return false
}
if bd1.Enabled != bd2.Enabled { if bd1.Enabled != bd2.Enabled {
return false return false
} }
@ -49,8 +54,8 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation {
func (s opentracing) Parse(ing *networking.Ingress) (interface{}, error) { func (s opentracing) Parse(ing *networking.Ingress) (interface{}, error) {
enabled, err := parser.GetBoolAnnotation("enable-opentracing", ing) enabled, err := parser.GetBoolAnnotation("enable-opentracing", ing)
if err != nil { if err != nil {
return &Config{Enabled: false}, nil return &Config{Set: false, Enabled: false}, nil
} }
return &Config{Enabled: enabled}, nil return &Config{Set: true, Enabled: enabled}, nil
} }

View file

@ -662,11 +662,9 @@ func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error {
return err return err
} }
if cfg.EnableOpentracing { err = createOpentracingCfg(cfg)
err := createOpentracingCfg(cfg) if err != nil {
if err != nil { return err
return err
}
} }
err = n.testTemplate(content) err = n.testTemplate(content)

View file

@ -178,6 +178,7 @@ var (
"buildHTTPListener": buildHTTPListener, "buildHTTPListener": buildHTTPListener,
"buildHTTPSListener": buildHTTPSListener, "buildHTTPSListener": buildHTTPSListener,
"buildOpentracingForLocation": buildOpentracingForLocation, "buildOpentracingForLocation": buildOpentracingForLocation,
"shouldLoadOpentracingModule": shouldLoadOpentracingModule,
} }
) )
@ -928,14 +929,20 @@ func randomString() string {
return string(b) return string(b)
} }
func buildOpentracing(input interface{}) string { func buildOpentracing(c interface{}, s interface{}) string {
cfg, ok := input.(config.Configuration) cfg, ok := c.(config.Configuration)
if !ok { if !ok {
klog.Errorf("expected a 'config.Configuration' type but %T was returned", input) klog.Errorf("expected a 'config.Configuration' type but %T was returned", c)
return "" return ""
} }
if !cfg.EnableOpentracing { servers, ok := s.([]*ingress.Server)
if !ok {
klog.Errorf("expected an '[]*ingress.Server' type but %T was returned", s)
return ""
}
if !shouldLoadOpentracingModule(cfg, servers) {
return "" return ""
} }
@ -1272,18 +1279,60 @@ func httpsListener(addresses []string, co string, tc config.TemplateConfig) []st
func buildOpentracingForLocation(isOTEnabled bool, location *ingress.Location) string { func buildOpentracingForLocation(isOTEnabled bool, location *ingress.Location) string {
isOTEnabledInLoc := location.Opentracing.Enabled isOTEnabledInLoc := location.Opentracing.Enabled
isOTSetInLoc := location.Opentracing.Set
if isOTEnabled { if isOTEnabled {
if !isOTEnabledInLoc { if isOTSetInLoc && !isOTEnabledInLoc {
return "opentracing off;" return "opentracing off;"
} }
return opentracingPropagateContext(location) opc := opentracingPropagateContext(location)
if opc != "" {
opc = fmt.Sprintf("opentracing on;\n%v", opc)
}
return opc
} }
if isOTEnabledInLoc { if isOTSetInLoc && isOTEnabledInLoc {
return opentracingPropagateContext(location) opc := opentracingPropagateContext(location)
if opc != "" {
opc = fmt.Sprintf("opentracing on;\n%v", opc)
}
return opc
} }
return "" return ""
} }
// shouldLoadOpentracingModule determines whether or not the Opentracing module needs to be loaded.
// First, it checks if `enable-opentracing` is set in the ConfigMap. If it is not, it iterates over all locations to
// check if Opentracing is enabled by the annotation `nginx.ingress.kubernetes.io/enable-opentracing`.
func shouldLoadOpentracingModule(c interface{}, s interface{}) bool {
cfg, ok := c.(config.Configuration)
if !ok {
klog.Errorf("expected a 'config.Configuration' type but %T was returned", c)
return false
}
servers, ok := s.([]*ingress.Server)
if !ok {
klog.Errorf("expected an '[]*ingress.Server' type but %T was returned", s)
return false
}
if cfg.EnableOpentracing {
return true
}
for _, server := range servers {
for _, location := range server.Locations {
if location.Opentracing.Enabled {
return true
}
}
}
return false
}

View file

@ -1153,7 +1153,7 @@ func TestBuildInfluxDB(t *testing.T) {
func TestBuildOpenTracing(t *testing.T) { func TestBuildOpenTracing(t *testing.T) {
invalidType := &ingress.Ingress{} invalidType := &ingress.Ingress{}
expected := "" expected := ""
actual := buildOpentracing(invalidType) actual := buildOpentracing(invalidType, []*ingress.Server{})
if expected != actual { if expected != actual {
t.Errorf("Expected '%v' but returned '%v'", expected, actual) t.Errorf("Expected '%v' but returned '%v'", expected, actual)
@ -1164,7 +1164,7 @@ func TestBuildOpenTracing(t *testing.T) {
JaegerCollectorHost: "jaeger-host.com", JaegerCollectorHost: "jaeger-host.com",
} }
expected = "opentracing_load_tracer /usr/local/lib/libjaegertracing_plugin.so /etc/nginx/opentracing.json;\r\n" expected = "opentracing_load_tracer /usr/local/lib/libjaegertracing_plugin.so /etc/nginx/opentracing.json;\r\n"
actual = buildOpentracing(cfgJaeger) actual = buildOpentracing(cfgJaeger, []*ingress.Server{})
if expected != actual { if expected != actual {
t.Errorf("Expected '%v' but returned '%v'", expected, actual) t.Errorf("Expected '%v' but returned '%v'", expected, actual)
@ -1175,7 +1175,7 @@ func TestBuildOpenTracing(t *testing.T) {
ZipkinCollectorHost: "zipkin-host.com", ZipkinCollectorHost: "zipkin-host.com",
} }
expected = "opentracing_load_tracer /usr/local/lib/libzipkin_opentracing.so /etc/nginx/opentracing.json;\r\n" expected = "opentracing_load_tracer /usr/local/lib/libzipkin_opentracing.so /etc/nginx/opentracing.json;\r\n"
actual = buildOpentracing(cfgZipkin) actual = buildOpentracing(cfgZipkin, []*ingress.Server{})
if expected != actual { if expected != actual {
t.Errorf("Expected '%v' but returned '%v'", expected, actual) t.Errorf("Expected '%v' but returned '%v'", expected, actual)
@ -1186,7 +1186,7 @@ func TestBuildOpenTracing(t *testing.T) {
DatadogCollectorHost: "datadog-host.com", DatadogCollectorHost: "datadog-host.com",
} }
expected = "opentracing_load_tracer /usr/local/lib64/libdd_opentracing.so /etc/nginx/opentracing.json;\r\n" expected = "opentracing_load_tracer /usr/local/lib64/libdd_opentracing.so /etc/nginx/opentracing.json;\r\n"
actual = buildOpentracing(cfgDatadog) actual = buildOpentracing(cfgDatadog, []*ingress.Server{})
if expected != actual { if expected != actual {
t.Errorf("Expected '%v' but returned '%v'", expected, actual) t.Errorf("Expected '%v' but returned '%v'", expected, actual)
@ -1283,25 +1283,89 @@ func TestShouldLoadModSecurityModule(t *testing.T) {
} }
func TestOpentracingForLocation(t *testing.T) { func TestOpentracingForLocation(t *testing.T) {
trueVal := true
loadOT := `opentracing on;
opentracing_propagate_context;`
testCases := []struct { testCases := []struct {
description string description string
globalOT bool globalOT bool
isOTInLoc bool isSetInLoc bool
isOTInLoc *bool
expected string expected string
}{ }{
{"globally enabled but not in location", true, false, "opentracing off;"}, {"globally enabled, without annotation", true, false, nil, loadOT},
{"globally enabled and enabled in location", true, true, "opentracing_propagate_context;"}, {"globally enabled and enabled in location", true, true, &trueVal, loadOT},
{"globally disabled and not enabled in location", false, false, ""}, {"globally disabled and not enabled in location", false, false, nil, ""},
{"globally disabled but enabled in location", false, true, "opentracing_propagate_context;"}, {"globally disabled but enabled in location", false, true, &trueVal, loadOT},
{"globally disabled, enabled in location but false", false, true, &trueVal, loadOT},
} }
for _, testCase := range testCases { for _, testCase := range testCases {
actual := buildOpentracingForLocation(testCase.globalOT, &ingress.Location{ il := &ingress.Location{
Opentracing: opentracing.Config{Enabled: testCase.isOTInLoc}, Opentracing: opentracing.Config{Set: testCase.isSetInLoc},
}) }
if il.Opentracing.Set {
il.Opentracing.Enabled = *testCase.isOTInLoc
}
actual := buildOpentracingForLocation(testCase.globalOT, il)
if testCase.expected != actual { if testCase.expected != actual {
t.Errorf("%v: expected '%v' but returned '%v'", testCase.description, testCase.expected, actual) t.Errorf("%v: expected '%v' but returned '%v'", testCase.description, testCase.expected, actual)
} }
} }
} }
func TestShouldLoadOpentracingModule(t *testing.T) {
// ### Invalid argument type tests ###
// The first tests should return false.
expected := false
invalidType := &ingress.Ingress{}
actual := shouldLoadOpentracingModule(config.Configuration{}, invalidType)
if expected != actual {
t.Errorf("Expected '%v' but returned '%v'", expected, actual)
}
actual = shouldLoadOpentracingModule(invalidType, []*ingress.Server{})
if expected != actual {
t.Errorf("Expected '%v' but returned '%v'", expected, actual)
}
// ### Functional tests ###
actual = shouldLoadOpentracingModule(config.Configuration{}, []*ingress.Server{})
if expected != actual {
t.Errorf("Expected '%v' but returned '%v'", expected, actual)
}
// All further tests should return true.
expected = true
configuration := config.Configuration{EnableOpentracing: true}
actual = shouldLoadOpentracingModule(configuration, []*ingress.Server{})
if expected != actual {
t.Errorf("Expected '%v' but returned '%v'", expected, actual)
}
servers := []*ingress.Server{
{
Locations: []*ingress.Location{
{
Opentracing: opentracing.Config{
Enabled: true,
},
},
},
},
}
actual = shouldLoadOpentracingModule(config.Configuration{}, servers)
if expected != actual {
t.Errorf("Expected '%v' but returned '%v'", expected, actual)
}
actual = shouldLoadOpentracingModule(configuration, servers)
if expected != actual {
t.Errorf("Expected '%v' but returned '%v'", expected, actual)
}
}

View file

@ -20,7 +20,7 @@ load_module /etc/nginx/modules/ngx_http_geoip2_module.so;
load_module /etc/nginx/modules/ngx_http_modsecurity_module.so; load_module /etc/nginx/modules/ngx_http_modsecurity_module.so;
{{ end }} {{ end }}
{{ if $cfg.EnableOpentracing }} {{ if (shouldLoadOpentracingModule $cfg $servers) }}
load_module /etc/nginx/modules/ngx_http_opentracing_module.so; load_module /etc/nginx/modules/ngx_http_opentracing_module.so;
{{ end }} {{ end }}
@ -224,11 +224,7 @@ http {
limit_req_status {{ $cfg.LimitReqStatusCode }}; limit_req_status {{ $cfg.LimitReqStatusCode }};
limit_conn_status {{ $cfg.LimitConnStatusCode }}; limit_conn_status {{ $cfg.LimitConnStatusCode }};
{{ if $cfg.EnableOpentracing }} {{ buildOpentracing $cfg $servers }}
opentracing on;
{{ end }}
{{ buildOpentracing $cfg }}
include /etc/nginx/mime.types; include /etc/nginx/mime.types;
default_type text/html; default_type text/html;
@ -1021,13 +1017,13 @@ stream {
set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; set $proxy_upstream_name {{ buildUpstreamName $location | quote }};
set $proxy_host $proxy_upstream_name; set $proxy_host $proxy_upstream_name;
set $pass_access_scheme $scheme; set $pass_access_scheme $scheme;
{{ if $all.Cfg.UseProxyProtocol }} {{ if $all.Cfg.UseProxyProtocol }}
set $pass_server_port $proxy_protocol_server_port; set $pass_server_port $proxy_protocol_server_port;
{{ else }} {{ else }}
set $pass_server_port $server_port; set $pass_server_port $server_port;
{{ end }} {{ end }}
set $best_http_host $http_host; set $best_http_host $http_host;
set $pass_port $pass_server_port; set $pass_port $pass_server_port;