Merge pull request #3474 from aledbf/improve-parsing

Improve parsing of annotations and use of Ingress wrapper
This commit is contained in:
Kubernetes Prow Robot 2018-12-05 03:33:18 -08:00 committed by GitHub
commit c4ba23832a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 302 additions and 354 deletions

View file

@ -123,9 +123,6 @@ func (a authReq) Parse(ing *extensions.Ingress) (interface{}, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if urlString == "" {
return nil, ing_errors.NewLocationDenied("an empty string is not a valid URL")
}
authURL, err := url.Parse(urlString) authURL, err := url.Parse(urlString)
if err != nil { if err != nil {

View file

@ -105,6 +105,10 @@ func TestAnnotations(t *testing.T) {
} }
continue continue
} }
if err != nil {
t.Errorf("%v: unexpected error: %v", test.title, err)
}
u, ok := i.(*Config) u, ok := i.(*Config)
if !ok { if !ok {
t.Errorf("%v: expected an External type", test.title) t.Errorf("%v: expected an External type", test.title)

View file

@ -87,52 +87,45 @@ type authTLS struct {
// Parse parses the annotations contained in the ingress // Parse parses the annotations contained in the ingress
// rule used to use a Certificate as authentication method // rule used to use a Certificate as authentication method
func (a authTLS) Parse(ing *extensions.Ingress) (interface{}, error) { func (a authTLS) Parse(ing *extensions.Ingress) (interface{}, error) {
var err error
config := &Config{}
tlsauthsecret, err := parser.GetStringAnnotation("auth-tls-secret", ing) tlsauthsecret, err := parser.GetStringAnnotation("auth-tls-secret", ing)
if err != nil { if err != nil {
return &Config{}, err return &Config{}, err
} }
if tlsauthsecret == "" {
return &Config{}, ing_errors.NewLocationDenied("an empty string is not a valid secret name")
}
_, _, err = k8s.ParseNameNS(tlsauthsecret) _, _, err = k8s.ParseNameNS(tlsauthsecret)
if err != nil { if err != nil {
return &Config{}, ing_errors.NewLocationDenied(err.Error()) return &Config{}, ing_errors.NewLocationDenied(err.Error())
} }
tlsVerifyClient, err := parser.GetStringAnnotation("auth-tls-verify-client", ing)
if err != nil || !authVerifyClientRegex.MatchString(tlsVerifyClient) {
tlsVerifyClient = defaultAuthVerifyClient
}
tlsdepth, err := parser.GetIntAnnotation("auth-tls-verify-depth", ing)
if err != nil || tlsdepth == 0 {
tlsdepth = defaultAuthTLSDepth
}
authCert, err := a.r.GetAuthCertificate(tlsauthsecret) authCert, err := a.r.GetAuthCertificate(tlsauthsecret)
if err != nil { if err != nil {
e := errors.Wrap(err, "error obtaining certificate") e := errors.Wrap(err, "error obtaining certificate")
return &Config{}, ing_errors.LocationDenied{Reason: e} return &Config{}, ing_errors.LocationDenied{Reason: e}
} }
config.AuthSSLCert = *authCert
errorpage, err := parser.GetStringAnnotation("auth-tls-error-page", ing) config.VerifyClient, err = parser.GetStringAnnotation("auth-tls-verify-client", ing)
if err != nil || errorpage == "" { if err != nil || !authVerifyClientRegex.MatchString(config.VerifyClient) {
errorpage = "" config.VerifyClient = defaultAuthVerifyClient
} }
passCert, err := parser.GetBoolAnnotation("auth-tls-pass-certificate-to-upstream", ing) config.ValidationDepth, err = parser.GetIntAnnotation("auth-tls-verify-depth", ing)
if err != nil || config.ValidationDepth == 0 {
config.ValidationDepth = defaultAuthTLSDepth
}
config.ErrorPage, err = parser.GetStringAnnotation("auth-tls-error-page", ing)
if err != nil { if err != nil {
passCert = false config.ErrorPage = ""
} }
return &Config{ config.PassCertToUpstream, err = parser.GetBoolAnnotation("auth-tls-pass-certificate-to-upstream", ing)
AuthSSLCert: *authCert, if err != nil {
VerifyClient: tlsVerifyClient, config.PassCertToUpstream = false
ValidationDepth: tlsdepth, }
ErrorPage: errorpage,
PassCertToUpstream: passCert, return config, nil
}, nil
} }

View file

@ -38,7 +38,6 @@ func TestParse(t *testing.T) {
annotations map[string]string annotations map[string]string
expected *Config expected *Config
}{ }{
{map[string]string{annotation: ""}, &Config{Enabled: true, Header: ""}},
{map[string]string{annotation: "keep-alive"}, &Config{Enabled: true, Header: "keep-alive"}}, {map[string]string{annotation: "keep-alive"}, &Config{Enabled: true, Header: "keep-alive"}},
{map[string]string{}, &Config{Enabled: false}}, {map[string]string{}, &Config{Enabled: false}},
{nil, &Config{Enabled: false}}, {nil, &Config{Enabled: false}},

View file

@ -97,43 +97,39 @@ func (c1 *Config) Equal(c2 *Config) bool {
// Parse parses the annotations contained in the ingress // Parse parses the annotations contained in the ingress
// rule used to indicate if the location/s should allows CORS // rule used to indicate if the location/s should allows CORS
func (c cors) Parse(ing *extensions.Ingress) (interface{}, error) { func (c cors) Parse(ing *extensions.Ingress) (interface{}, error) {
corsenabled, err := parser.GetBoolAnnotation("enable-cors", ing) var err error
config := &Config{}
config.CorsEnabled, err = parser.GetBoolAnnotation("enable-cors", ing)
if err != nil { if err != nil {
corsenabled = false config.CorsEnabled = false
} }
corsalloworigin, err := parser.GetStringAnnotation("cors-allow-origin", ing) config.CorsAllowOrigin, err = parser.GetStringAnnotation("cors-allow-origin", ing)
if err != nil || corsalloworigin == "" || !corsOriginRegex.MatchString(corsalloworigin) { if err != nil || !corsOriginRegex.MatchString(config.CorsAllowOrigin) {
corsalloworigin = "*" config.CorsAllowOrigin = "*"
} }
corsallowheaders, err := parser.GetStringAnnotation("cors-allow-headers", ing) config.CorsAllowHeaders, err = parser.GetStringAnnotation("cors-allow-headers", ing)
if err != nil || corsallowheaders == "" || !corsHeadersRegex.MatchString(corsallowheaders) { if err != nil || !corsHeadersRegex.MatchString(config.CorsAllowHeaders) {
corsallowheaders = defaultCorsHeaders config.CorsAllowHeaders = defaultCorsHeaders
} }
corsallowmethods, err := parser.GetStringAnnotation("cors-allow-methods", ing) config.CorsAllowMethods, err = parser.GetStringAnnotation("cors-allow-methods", ing)
if err != nil || corsallowmethods == "" || !corsMethodsRegex.MatchString(corsallowmethods) { if err != nil || !corsMethodsRegex.MatchString(config.CorsAllowMethods) {
corsallowmethods = defaultCorsMethods config.CorsAllowMethods = defaultCorsMethods
} }
corsallowcredentials, err := parser.GetBoolAnnotation("cors-allow-credentials", ing) config.CorsAllowCredentials, err = parser.GetBoolAnnotation("cors-allow-credentials", ing)
if err != nil { if err != nil {
corsallowcredentials = true config.CorsAllowCredentials = true
} }
corsmaxage, err := parser.GetIntAnnotation("cors-max-age", ing) config.CorsMaxAge, err = parser.GetIntAnnotation("cors-max-age", ing)
if err != nil { if err != nil {
corsmaxage = defaultCorsMaxAge config.CorsMaxAge = defaultCorsMaxAge
} }
return &Config{ return config, nil
CorsEnabled: corsenabled,
CorsAllowOrigin: corsalloworigin,
CorsAllowHeaders: corsallowheaders,
CorsAllowMethods: corsallowmethods,
CorsAllowCredentials: corsallowcredentials,
CorsMaxAge: corsmaxage,
}, nil
} }

View file

@ -43,40 +43,37 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation {
// Parse parses the annotations to look for InfluxDB configurations // Parse parses the annotations to look for InfluxDB configurations
func (c influxdb) Parse(ing *extensions.Ingress) (interface{}, error) { func (c influxdb) Parse(ing *extensions.Ingress) (interface{}, error) {
influxdbEnabled, err := parser.GetBoolAnnotation("enable-influxdb", ing) var err error
config := &Config{}
config.InfluxDBEnabled, err = parser.GetBoolAnnotation("enable-influxdb", ing)
if err != nil { if err != nil {
influxdbEnabled = false config.InfluxDBEnabled = false
} }
influxdbMeasurement, err := parser.GetStringAnnotation("influxdb-measurement", ing) config.InfluxDBMeasurement, err = parser.GetStringAnnotation("influxdb-measurement", ing)
if err != nil { if err != nil {
influxdbMeasurement = "default" config.InfluxDBMeasurement = "default"
} }
influxdbPort, err := parser.GetStringAnnotation("influxdb-port", ing) config.InfluxDBPort, err = parser.GetStringAnnotation("influxdb-port", ing)
if err != nil { if err != nil {
// This is not the default 8086 port but the port usually used to expose // This is not the default 8086 port but the port usually used to expose
// influxdb in UDP, the module uses UDP to talk to influx via the line protocol. // influxdb in UDP, the module uses UDP to talk to influx via the line protocol.
influxdbPort = "8089" config.InfluxDBPort = "8089"
} }
influxdbHost, err := parser.GetStringAnnotation("influxdb-host", ing) config.InfluxDBHost, err = parser.GetStringAnnotation("influxdb-host", ing)
if err != nil { if err != nil {
influxdbHost = "127.0.0.1" config.InfluxDBHost = "127.0.0.1"
} }
influxdbServerName, err := parser.GetStringAnnotation("influxdb-server-name", ing) config.InfluxDBServerName, err = parser.GetStringAnnotation("influxdb-server-name", ing)
if err != nil { if err != nil {
influxdbServerName = "nginx-ingress" config.InfluxDBServerName = "nginx-ingress"
} }
return &Config{ return config, nil
InfluxDBEnabled: influxdbEnabled,
InfluxDBMeasurement: influxdbMeasurement,
InfluxDBPort: influxdbPort,
InfluxDBHost: influxdbHost,
InfluxDBServerName: influxdbServerName,
}, nil
} }
// Equal tests for equality between two Config types // Equal tests for equality between two Config types

View file

@ -54,15 +54,18 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation {
// Parse parses the annotations contained in the ingress // Parse parses the annotations contained in the ingress
// rule used to indicate if the location/s should enable logs // rule used to indicate if the location/s should enable logs
func (l log) Parse(ing *extensions.Ingress) (interface{}, error) { func (l log) Parse(ing *extensions.Ingress) (interface{}, error) {
accessEnabled, err := parser.GetBoolAnnotation("enable-access-log", ing) var err error
config := &Config{}
config.Access, err = parser.GetBoolAnnotation("enable-access-log", ing)
if err != nil { if err != nil {
accessEnabled = true config.Access = true
} }
rewriteEnabled, err := parser.GetBoolAnnotation("enable-rewrite-log", ing) config.Rewrite, err = parser.GetBoolAnnotation("enable-rewrite-log", ing)
if err != nil { if err != nil {
rewriteEnabled = false config.Rewrite = false
} }
return &Config{Access: accessEnabled, Rewrite: rewriteEnabled}, nil return config, nil
} }

View file

@ -86,43 +86,38 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation {
// used to indicate if the location/s contains a fragment of // used to indicate if the location/s contains a fragment of
// configuration to be included inside the paths of the rules // configuration to be included inside the paths of the rules
func (a luarestywaf) Parse(ing *extensions.Ingress) (interface{}, error) { func (a luarestywaf) Parse(ing *extensions.Ingress) (interface{}, error) {
var err error
config := &Config{}
mode, err := parser.GetStringAnnotation("lua-resty-waf", ing) mode, err := parser.GetStringAnnotation("lua-resty-waf", ing)
if err != nil { if err != nil {
return &Config{}, err return &Config{}, err
} }
mode = strings.ToUpper(mode) config.Mode = strings.ToUpper(mode)
if _, ok := luaRestyWAFModes[mode]; !ok { if _, ok := luaRestyWAFModes[config.Mode]; !ok {
return &Config{}, errors.NewInvalidAnnotationContent("lua-resty-waf", mode) return &Config{}, errors.NewInvalidAnnotationContent("lua-resty-waf", mode)
} }
debug, _ := parser.GetBoolAnnotation("lua-resty-waf-debug", ing) config.Debug, _ = parser.GetBoolAnnotation("lua-resty-waf-debug", ing)
ignoredRuleSetsStr, _ := parser.GetStringAnnotation("lua-resty-waf-ignore-rulesets", ing) ignoredRuleSetsStr, _ := parser.GetStringAnnotation("lua-resty-waf-ignore-rulesets", ing)
ignoredRuleSets := strings.FieldsFunc(ignoredRuleSetsStr, func(c rune) bool { config.IgnoredRuleSets = strings.FieldsFunc(ignoredRuleSetsStr, func(c rune) bool {
strC := string(c) strC := string(c)
return strC == "," || strC == " " return strC == "," || strC == " "
}) })
// TODO(elvinefendi) maybe validate the ruleset string here // TODO(elvinefendi) maybe validate the ruleset string here
extraRulesetString, _ := parser.GetStringAnnotation("lua-resty-waf-extra-rules", ing) config.ExtraRulesetString, _ = parser.GetStringAnnotation("lua-resty-waf-extra-rules", ing)
scoreThreshold, _ := parser.GetIntAnnotation("lua-resty-waf-score-threshold", ing) config.ScoreThreshold, _ = parser.GetIntAnnotation("lua-resty-waf-score-threshold", ing)
allowUnknownContentTypes, _ := parser.GetBoolAnnotation("lua-resty-waf-allow-unknown-content-types", ing) config.AllowUnknownContentTypes, _ = parser.GetBoolAnnotation("lua-resty-waf-allow-unknown-content-types", ing)
processMultipartBody, err := parser.GetBoolAnnotation("lua-resty-waf-process-multipart-body", ing) config.ProcessMultipartBody, err = parser.GetBoolAnnotation("lua-resty-waf-process-multipart-body", ing)
if err != nil { if err != nil {
processMultipartBody = true config.ProcessMultipartBody = true
} }
return &Config{ return config, nil
Mode: mode,
Debug: debug,
IgnoredRuleSets: ignoredRuleSets,
ExtraRulesetString: extraRulesetString,
ScoreThreshold: scoreThreshold,
AllowUnknownContentTypes: allowUnknownContentTypes,
ProcessMultipartBody: processMultipartBody,
}, nil
} }

View file

@ -66,31 +66,28 @@ type modSecurity struct {
// Parse parses the annotations contained in the ingress // Parse parses the annotations contained in the ingress
// rule used to enable ModSecurity in a particular location // rule used to enable ModSecurity in a particular location
func (a modSecurity) Parse(ing *extensions.Ingress) (interface{}, error) { func (a modSecurity) Parse(ing *extensions.Ingress) (interface{}, error) {
var err error
config := &Config{}
enableModSecurity, err := parser.GetBoolAnnotation("enable-modsecurity", ing) config.Enable, err = parser.GetBoolAnnotation("enable-modsecurity", ing)
if err != nil { if err != nil {
enableModSecurity = false config.Enable = false
} }
owaspRules, err := parser.GetBoolAnnotation("enable-owasp-core-rules", ing) config.OWASPRules, err = parser.GetBoolAnnotation("enable-owasp-core-rules", ing)
if err != nil { if err != nil {
owaspRules = false config.OWASPRules = false
} }
transactionID, err := parser.GetStringAnnotation("modsecurity-transaction-id", ing) config.TransactionID, err = parser.GetStringAnnotation("modsecurity-transaction-id", ing)
if err != nil { if err != nil {
transactionID = "" config.TransactionID = ""
} }
snippet, err := parser.GetStringAnnotation("modsecurity-snippet", ing) config.Snippet, err = parser.GetStringAnnotation("modsecurity-snippet", ing)
if err != nil { if err != nil {
snippet = "" config.Snippet = ""
} }
return Config{ return config, nil
Enable: enableModSecurity,
OWASPRules: owaspRules,
TransactionID: transactionID,
Snippet: snippet,
}, nil
} }

View file

@ -70,7 +70,8 @@ func TestParse(t *testing.T) {
for _, testCase := range testCases { for _, testCase := range testCases {
ing.SetAnnotations(testCase.annotations) ing.SetAnnotations(testCase.annotations)
result, _ := ap.Parse(ing) result, _ := ap.Parse(ing)
if result != testCase.expected { config := result.(*Config)
if !config.Equal(&testCase.expected) {
t.Errorf("expected %v but returned %v, annotations: %s", testCase.expected, result, testCase.annotations) t.Errorf("expected %v but returned %v, annotations: %s", testCase.expected, result, testCase.annotations)
} }
} }

View file

@ -52,6 +52,10 @@ func (a ingAnnotations) parseBool(name string) (bool, error) {
func (a ingAnnotations) parseString(name string) (string, error) { func (a ingAnnotations) parseString(name string) (string, error) {
val, ok := a[name] val, ok := a[name]
if ok { if ok {
if len(val) == 0 {
return "", errors.NewInvalidAnnotationContent(name, val)
}
return val, nil return val, nil
} }
return "", errors.ErrMissingAnnotations return "", errors.ErrMissingAnnotations
@ -97,6 +101,7 @@ func GetStringAnnotation(name string, ing *extensions.Ingress) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
return ingAnnotations(ing.GetAnnotations()).parseString(v) return ingAnnotations(ing.GetAnnotations()).parseString(v)
} }

View file

@ -79,7 +79,7 @@ func TestGetStringAnnotation(t *testing.T) {
_, err := GetStringAnnotation("", nil) _, err := GetStringAnnotation("", nil)
if err == nil { if err == nil {
t.Errorf("expected error but retuned nil") t.Errorf("expected error but none returned")
} }
tests := []struct { tests := []struct {
@ -91,6 +91,7 @@ func TestGetStringAnnotation(t *testing.T) {
}{ }{
{"valid - A", "string", "A", "A", false}, {"valid - A", "string", "A", "A", false},
{"valid - B", "string", "B", "B", false}, {"valid - B", "string", "B", "B", false},
{"empty", "string", "", "", true},
} }
data := map[string]string{} data := map[string]string{}
@ -102,7 +103,7 @@ func TestGetStringAnnotation(t *testing.T) {
s, err := GetStringAnnotation(test.field, ing) s, err := GetStringAnnotation(test.field, ing)
if test.expErr { if test.expErr {
if err == nil { if err == nil {
t.Errorf("%v: expected error but retuned nil", test.name) t.Errorf("%v: expected error but none returned", test.name)
} }
continue continue
} }

View file

@ -103,72 +103,75 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation {
// ParseAnnotations parses the annotations contained in the ingress // ParseAnnotations parses the annotations contained in the ingress
// rule used to configure upstream check parameters // rule used to configure upstream check parameters
func (a proxy) Parse(ing *extensions.Ingress) (interface{}, error) { func (a proxy) Parse(ing *extensions.Ingress) (interface{}, error) {
defBackend := a.r.GetDefaultBackend() defBackend := a.r.GetDefaultBackend()
ct, err := parser.GetIntAnnotation("proxy-connect-timeout", ing) config := &Config{}
var err error
config.ConnectTimeout, err = parser.GetIntAnnotation("proxy-connect-timeout", ing)
if err != nil { if err != nil {
ct = defBackend.ProxyConnectTimeout config.ConnectTimeout = defBackend.ProxyConnectTimeout
} }
st, err := parser.GetIntAnnotation("proxy-send-timeout", ing) config.SendTimeout, err = parser.GetIntAnnotation("proxy-send-timeout", ing)
if err != nil { if err != nil {
st = defBackend.ProxySendTimeout config.SendTimeout = defBackend.ProxySendTimeout
} }
rt, err := parser.GetIntAnnotation("proxy-read-timeout", ing) config.ReadTimeout, err = parser.GetIntAnnotation("proxy-read-timeout", ing)
if err != nil { if err != nil {
rt = defBackend.ProxyReadTimeout config.ReadTimeout = defBackend.ProxyReadTimeout
} }
bufs, err := parser.GetStringAnnotation("proxy-buffer-size", ing) config.BufferSize, err = parser.GetStringAnnotation("proxy-buffer-size", ing)
if err != nil || bufs == "" {
bufs = defBackend.ProxyBufferSize
}
cp, err := parser.GetStringAnnotation("proxy-cookie-path", ing)
if err != nil || cp == "" {
cp = defBackend.ProxyCookiePath
}
cd, err := parser.GetStringAnnotation("proxy-cookie-domain", ing)
if err != nil || cd == "" {
cd = defBackend.ProxyCookieDomain
}
bs, err := parser.GetStringAnnotation("proxy-body-size", ing)
if err != nil || bs == "" {
bs = defBackend.ProxyBodySize
}
nu, err := parser.GetStringAnnotation("proxy-next-upstream", ing)
if err != nil || nu == "" {
nu = defBackend.ProxyNextUpstream
}
nut, err := parser.GetIntAnnotation("proxy-next-upstream-tries", ing)
if err != nil { if err != nil {
nut = defBackend.ProxyNextUpstreamTries config.BufferSize = defBackend.ProxyBufferSize
} }
rb, err := parser.GetStringAnnotation("proxy-request-buffering", ing) config.CookiePath, err = parser.GetStringAnnotation("proxy-cookie-path", ing)
if err != nil || rb == "" { if err != nil {
rb = defBackend.ProxyRequestBuffering config.CookiePath = defBackend.ProxyCookiePath
} }
prf, err := parser.GetStringAnnotation("proxy-redirect-from", ing) config.CookieDomain, err = parser.GetStringAnnotation("proxy-cookie-domain", ing)
if err != nil || prf == "" { if err != nil {
prf = defBackend.ProxyRedirectFrom config.CookieDomain = defBackend.ProxyCookieDomain
} }
prt, err := parser.GetStringAnnotation("proxy-redirect-to", ing) config.BodySize, err = parser.GetStringAnnotation("proxy-body-size", ing)
if err != nil || rb == "" { if err != nil {
prt = defBackend.ProxyRedirectTo config.BodySize = defBackend.ProxyBodySize
} }
pb, err := parser.GetStringAnnotation("proxy-buffering", ing) config.NextUpstream, err = parser.GetStringAnnotation("proxy-next-upstream", ing)
if err != nil || pb == "" { if err != nil {
pb = defBackend.ProxyBuffering config.NextUpstream = defBackend.ProxyNextUpstream
} }
return &Config{bs, ct, st, rt, bufs, cd, cp, nu, nut, prf, prt, rb, pb}, nil config.NextUpstreamTries, err = parser.GetIntAnnotation("proxy-next-upstream-tries", ing)
if err != nil {
config.NextUpstreamTries = defBackend.ProxyNextUpstreamTries
}
config.RequestBuffering, err = parser.GetStringAnnotation("proxy-request-buffering", ing)
if err != nil {
config.RequestBuffering = defBackend.ProxyRequestBuffering
}
config.ProxyRedirectFrom, err = parser.GetStringAnnotation("proxy-redirect-from", ing)
if err != nil {
config.ProxyRedirectFrom = defBackend.ProxyRedirectFrom
}
config.ProxyRedirectTo, err = parser.GetStringAnnotation("proxy-redirect-to", ing)
if err != nil {
config.ProxyRedirectTo = defBackend.ProxyRedirectTo
}
config.ProxyBuffering, err = parser.GetStringAnnotation("proxy-buffering", ing)
if err != nil {
config.ProxyBuffering = defBackend.ProxyBuffering
}
return config, nil
} }

View file

@ -87,27 +87,24 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation {
// ParseAnnotations parses the annotations contained in the ingress // ParseAnnotations parses the annotations contained in the ingress
// rule used to rewrite the defined paths // rule used to rewrite the defined paths
func (a rewrite) Parse(ing *extensions.Ingress) (interface{}, error) { func (a rewrite) Parse(ing *extensions.Ingress) (interface{}, error) {
rt, _ := parser.GetStringAnnotation("rewrite-target", ing) var err error
sslRe, err := parser.GetBoolAnnotation("ssl-redirect", ing) config := &Config{}
if err != nil {
sslRe = a.r.GetDefaultBackend().SSLRedirect
}
fSslRe, err := parser.GetBoolAnnotation("force-ssl-redirect", ing)
if err != nil {
fSslRe = a.r.GetDefaultBackend().ForceSSLRedirect
}
abu, _ := parser.GetBoolAnnotation("add-base-url", ing)
bus, _ := parser.GetStringAnnotation("base-url-scheme", ing)
ar, _ := parser.GetStringAnnotation("app-root", ing)
ur, _ := parser.GetBoolAnnotation("use-regex", ing)
return &Config{ config.Target, _ = parser.GetStringAnnotation("rewrite-target", ing)
Target: rt, config.SSLRedirect, err = parser.GetBoolAnnotation("ssl-redirect", ing)
AddBaseURL: abu, if err != nil {
BaseURLScheme: bus, config.SSLRedirect = a.r.GetDefaultBackend().SSLRedirect
SSLRedirect: sslRe, }
ForceSSLRedirect: fSslRe,
AppRoot: ar, config.ForceSSLRedirect, err = parser.GetBoolAnnotation("force-ssl-redirect", ing)
UseRegex: ur, if err != nil {
}, nil config.ForceSSLRedirect = a.r.GetDefaultBackend().ForceSSLRedirect
}
config.AddBaseURL, _ = parser.GetBoolAnnotation("add-base-url", ing)
config.BaseURLScheme, _ = parser.GetStringAnnotation("base-url-scheme", ing)
config.AppRoot, _ = parser.GetStringAnnotation("app-root", ing)
config.UseRegex, _ = parser.GetBoolAnnotation("use-regex", ing)
return config, nil
} }

View file

@ -81,42 +81,39 @@ type Cookie struct {
// cookieAffinityParse gets the annotation values related to Cookie Affinity // cookieAffinityParse gets the annotation values related to Cookie Affinity
// It also sets default values when no value or incorrect value is found // It also sets default values when no value or incorrect value is found
func (a affinity) cookieAffinityParse(ing *extensions.Ingress) *Cookie { func (a affinity) cookieAffinityParse(ing *extensions.Ingress) *Cookie {
var err error
cookie := &Cookie{} cookie := &Cookie{}
sn, err := parser.GetStringAnnotation(annotationAffinityCookieName, ing)
if err != nil || sn == "" { cookie.Name, err = parser.GetStringAnnotation(annotationAffinityCookieName, ing)
if err != nil {
glog.V(3).Infof("Ingress %v: No value found in annotation %v. Using the default %v", ing.Name, annotationAffinityCookieName, defaultAffinityCookieName) glog.V(3).Infof("Ingress %v: No value found in annotation %v. Using the default %v", ing.Name, annotationAffinityCookieName, defaultAffinityCookieName)
sn = defaultAffinityCookieName cookie.Name = defaultAffinityCookieName
} }
cookie.Name = sn
sh, err := parser.GetStringAnnotation(annotationAffinityCookieHash, ing) cookie.Hash, err = parser.GetStringAnnotation(annotationAffinityCookieHash, ing)
if err != nil || !affinityCookieHashRegex.MatchString(cookie.Hash) {
if err != nil || !affinityCookieHashRegex.MatchString(sh) {
glog.V(3).Infof("Invalid or no annotation value found in Ingress %v: %v. Setting it to default %v", ing.Name, annotationAffinityCookieHash, defaultAffinityCookieHash) glog.V(3).Infof("Invalid or no annotation value found in Ingress %v: %v. Setting it to default %v", ing.Name, annotationAffinityCookieHash, defaultAffinityCookieHash)
sh = defaultAffinityCookieHash cookie.Hash = defaultAffinityCookieHash
} }
cookie.Hash = sh
se, err := parser.GetStringAnnotation(annotationAffinityCookieExpires, ing) cookie.Expires, err = parser.GetStringAnnotation(annotationAffinityCookieExpires, ing)
if err != nil || !affinityCookieExpiresRegex.MatchString(se) { if err != nil || !affinityCookieExpiresRegex.MatchString(cookie.Expires) {
glog.V(3).Infof("Invalid or no annotation value found in Ingress %v: %v. Ignoring it", ing.Name, annotationAffinityCookieExpires) glog.V(3).Infof("Invalid or no annotation value found in Ingress %v: %v. Ignoring it", ing.Name, annotationAffinityCookieExpires)
se = "" cookie.Expires = ""
} }
cookie.Expires = se
sm, err := parser.GetStringAnnotation(annotationAffinityCookieMaxAge, ing) cookie.MaxAge, err = parser.GetStringAnnotation(annotationAffinityCookieMaxAge, ing)
if err != nil || !affinityCookieExpiresRegex.MatchString(sm) { if err != nil || !affinityCookieExpiresRegex.MatchString(cookie.MaxAge) {
glog.V(3).Infof("Invalid or no annotation value found in Ingress %v: %v. Ignoring it", ing.Name, annotationAffinityCookieMaxAge) glog.V(3).Infof("Invalid or no annotation value found in Ingress %v: %v. Ignoring it", ing.Name, annotationAffinityCookieMaxAge)
sm = "" cookie.MaxAge = ""
} }
cookie.MaxAge = sm
sp, err := parser.GetStringAnnotation(annotationAffinityCookiePath, ing) cookie.Path, err = parser.GetStringAnnotation(annotationAffinityCookiePath, ing)
if err != nil || sp == "" { if err != nil {
glog.V(3).Infof("Invalid or no annotation value found in Ingress %v: %v. Ignoring it", ing.Name, annotationAffinityCookieMaxAge) glog.V(3).Infof("Invalid or no annotation value found in Ingress %v: %v. Ignoring it", ing.Name, annotationAffinityCookieMaxAge)
} }
cookie.Path = sp
return cookie return cookie
} }

View file

@ -18,16 +18,16 @@ package store
import ( import (
"k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/cache"
"k8s.io/ingress-nginx/internal/ingress/annotations" "k8s.io/ingress-nginx/internal/ingress"
) )
// IngressAnnotationsLister makes a Store that lists annotations in Ingress rules. // IngressWithAnnotationsLister makes a Store that lists Ingress rules with annotations already parsed
type IngressAnnotationsLister struct { type IngressWithAnnotationsLister struct {
cache.Store cache.Store
} }
// ByKey returns the Ingress annotations matching key in the local Ingress annotations Store. // ByKey returns the Ingress with annotations matching key in the local store or an error
func (il IngressAnnotationsLister) ByKey(key string) (*annotations.Ingress, error) { func (il IngressWithAnnotationsLister) ByKey(key string) (*ingress.Ingress, error) {
i, exists, err := il.GetByKey(key) i, exists, err := il.GetByKey(key)
if err != nil { if err != nil {
return nil, err return nil, err
@ -35,5 +35,5 @@ func (il IngressAnnotationsLister) ByKey(key string) (*annotations.Ingress, erro
if !exists { if !exists {
return nil, NotExistsError(key) return nil, NotExistsError(key)
} }
return i.(*annotations.Ingress), nil return i.(*ingress.Ingress), nil
} }

View file

@ -73,9 +73,6 @@ type Storer interface {
// GetServiceEndpoints returns the Endpoints of a Service matching key. // GetServiceEndpoints returns the Endpoints of a Service matching key.
GetServiceEndpoints(key string) (*corev1.Endpoints, error) GetServiceEndpoints(key string) (*corev1.Endpoints, error)
// GetIngress returns the Ingress matching key.
GetIngress(key string) (*extensions.Ingress, error)
// ListIngresses returns a list of all Ingresses in the store. // ListIngresses returns a list of all Ingresses in the store.
ListIngresses() []*ingress.Ingress ListIngresses() []*ingress.Ingress
@ -132,13 +129,13 @@ type Informer struct {
// Lister contains object listers (stores). // Lister contains object listers (stores).
type Lister struct { type Lister struct {
Ingress IngressLister Ingress IngressLister
Service ServiceLister Service ServiceLister
Endpoint EndpointLister Endpoint EndpointLister
Secret SecretLister Secret SecretLister
ConfigMap ConfigMapLister ConfigMap ConfigMapLister
IngressAnnotation IngressAnnotationsLister IngressWithAnnotation IngressWithAnnotationsLister
Pod PodLister Pod PodLister
} }
// NotExistsError is returned when an object does not exist in a local store. // NotExistsError is returned when an object does not exist in a local store.
@ -261,7 +258,7 @@ func New(checkOCSP bool,
// k8sStore fulfills resolver.Resolver interface // k8sStore fulfills resolver.Resolver interface
store.annotations = annotations.NewAnnotationExtractor(store) store.annotations = annotations.NewAnnotationExtractor(store)
store.listers.IngressAnnotation.Store = cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc) store.listers.IngressWithAnnotation.Store = cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc)
// create informers factory, enable and assign required informers // create informers factory, enable and assign required informers
infFactory := informers.NewSharedInformerFactoryWithOptions(client, resyncPeriod, infFactory := informers.NewSharedInformerFactoryWithOptions(client, resyncPeriod,
@ -313,7 +310,7 @@ func New(checkOCSP bool,
} }
recorder.Eventf(ing, corev1.EventTypeNormal, "CREATE", fmt.Sprintf("Ingress %s/%s", ing.Namespace, ing.Name)) recorder.Eventf(ing, corev1.EventTypeNormal, "CREATE", fmt.Sprintf("Ingress %s/%s", ing.Namespace, ing.Name))
store.extractAnnotations(ing) store.syncIngress(ing)
store.updateSecretIngressMap(ing) store.updateSecretIngressMap(ing)
store.syncSecrets(ing) store.syncSecrets(ing)
@ -343,7 +340,7 @@ func New(checkOCSP bool,
} }
recorder.Eventf(ing, corev1.EventTypeNormal, "DELETE", fmt.Sprintf("Ingress %s/%s", ing.Namespace, ing.Name)) recorder.Eventf(ing, corev1.EventTypeNormal, "DELETE", fmt.Sprintf("Ingress %s/%s", ing.Namespace, ing.Name))
store.listers.IngressAnnotation.Delete(ing) store.listers.IngressWithAnnotation.Delete(ing)
key := k8s.MetaNamespaceKey(ing) key := k8s.MetaNamespaceKey(ing)
store.secretIngressMap.Delete(key) store.secretIngressMap.Delete(key)
@ -368,7 +365,7 @@ func New(checkOCSP bool,
recorder.Eventf(curIng, corev1.EventTypeNormal, "UPDATE", fmt.Sprintf("Ingress %s/%s", curIng.Namespace, curIng.Name)) recorder.Eventf(curIng, corev1.EventTypeNormal, "UPDATE", fmt.Sprintf("Ingress %s/%s", curIng.Namespace, curIng.Name))
} }
store.extractAnnotations(curIng) store.syncIngress(curIng)
store.updateSecretIngressMap(curIng) store.updateSecretIngressMap(curIng)
store.syncSecrets(curIng) store.syncSecrets(curIng)
@ -392,12 +389,12 @@ func New(checkOCSP bool,
if ings := store.secretIngressMap.Reference(key); len(ings) > 0 { if ings := store.secretIngressMap.Reference(key); len(ings) > 0 {
glog.Infof("secret %v was added and it is used in ingress annotations. Parsing...", key) glog.Infof("secret %v was added and it is used in ingress annotations. Parsing...", key)
for _, ingKey := range ings { for _, ingKey := range ings {
ing, err := store.GetIngress(ingKey) ing, err := store.getIngress(ingKey)
if err != nil { if err != nil {
glog.Errorf("could not find Ingress %v in local store", ingKey) glog.Errorf("could not find Ingress %v in local store", ingKey)
continue continue
} }
store.extractAnnotations(ing) store.syncIngress(ing)
store.syncSecrets(ing) store.syncSecrets(ing)
} }
updateCh.In() <- Event{ updateCh.In() <- Event{
@ -419,12 +416,12 @@ func New(checkOCSP bool,
if ings := store.secretIngressMap.Reference(key); len(ings) > 0 { if ings := store.secretIngressMap.Reference(key); len(ings) > 0 {
glog.Infof("secret %v was updated and it is used in ingress annotations. Parsing...", key) glog.Infof("secret %v was updated and it is used in ingress annotations. Parsing...", key)
for _, ingKey := range ings { for _, ingKey := range ings {
ing, err := store.GetIngress(ingKey) ing, err := store.getIngress(ingKey)
if err != nil { if err != nil {
glog.Errorf("could not find Ingress %v in local store", ingKey) glog.Errorf("could not find Ingress %v in local store", ingKey)
continue continue
} }
store.extractAnnotations(ing) store.syncIngress(ing)
store.syncSecrets(ing) store.syncSecrets(ing)
} }
updateCh.In() <- Event{ updateCh.In() <- Event{
@ -458,12 +455,12 @@ func New(checkOCSP bool,
if ings := store.secretIngressMap.Reference(key); len(ings) > 0 { if ings := store.secretIngressMap.Reference(key); len(ings) > 0 {
glog.Infof("secret %v was deleted and it is used in ingress annotations. Parsing...", key) glog.Infof("secret %v was deleted and it is used in ingress annotations. Parsing...", key)
for _, ingKey := range ings { for _, ingKey := range ings {
ing, err := store.GetIngress(ingKey) ing, err := store.getIngress(ingKey)
if err != nil { if err != nil {
glog.Errorf("could not find Ingress %v in local store", ingKey) glog.Errorf("could not find Ingress %v in local store", ingKey)
continue continue
} }
store.extractAnnotations(ing) store.syncIngress(ing)
} }
updateCh.In() <- Event{ updateCh.In() <- Event{
Type: DeleteEvent, Type: DeleteEvent,
@ -525,15 +522,15 @@ func New(checkOCSP bool,
store.setConfig(cm) store.setConfig(cm)
} }
ings := store.listers.IngressAnnotation.List() ings := store.listers.IngressWithAnnotation.List()
for _, ingKey := range ings { for _, ingKey := range ings {
key := k8s.MetaNamespaceKey(ingKey) key := k8s.MetaNamespaceKey(ingKey)
ing, err := store.GetIngress(key) ing, err := store.getIngress(key)
if err != nil { if err != nil {
glog.Errorf("could not find Ingress %v in local store: %v", key, err) glog.Errorf("could not find Ingress %v in local store: %v", key, err)
continue continue
} }
store.extractAnnotations(ing) store.syncIngress(ing)
} }
updateCh.In() <- Event{ updateCh.In() <- Event{
@ -591,15 +588,32 @@ func New(checkOCSP bool,
return store return store
} }
// extractAnnotations parses ingress annotations converting the value of the // syncIngress parses ingress annotations converting the value of the
// annotation to a go struct and also information about the referenced secrets // annotation to a go struct
func (s *k8sStore) extractAnnotations(ing *extensions.Ingress) { func (s *k8sStore) syncIngress(ing *extensions.Ingress) {
key := k8s.MetaNamespaceKey(ing) key := k8s.MetaNamespaceKey(ing)
glog.V(3).Infof("updating annotations information for ingress %v", key) glog.V(3).Infof("updating annotations information for ingress %v", key)
anns := s.annotations.Extract(ing) copyIng := &extensions.Ingress{}
ing.ObjectMeta.DeepCopyInto(&copyIng.ObjectMeta)
ing.Spec.DeepCopyInto(&copyIng.Spec)
err := s.listers.IngressAnnotation.Update(anns) for ri, rule := range copyIng.Spec.Rules {
if rule.HTTP == nil {
continue
}
for pi, path := range rule.HTTP.Paths {
if path.Path == "" {
copyIng.Spec.Rules[ri].HTTP.Paths[pi].Path = "/"
}
}
}
err := s.listers.IngressWithAnnotation.Update(&ingress.Ingress{
Ingress: *copyIng,
ParsedAnnotations: s.annotations.Extract(ing),
})
if err != nil { if err != nil {
glog.Error(err) glog.Error(err)
} }
@ -651,7 +665,7 @@ func (s *k8sStore) updateSecretIngressMap(ing *extensions.Ingress) {
// 'namespace/name' key from the given annotation name. // 'namespace/name' key from the given annotation name.
func objectRefAnnotationNsKey(ann string, ing *extensions.Ingress) (string, error) { func objectRefAnnotationNsKey(ann string, ing *extensions.Ingress) (string, error) {
annValue, err := parser.GetStringAnnotation(ann, ing) annValue, err := parser.GetStringAnnotation(ann, ing)
if annValue == "" { if err != nil {
return "", err return "", err
} }
@ -697,59 +711,28 @@ func (s k8sStore) GetService(key string) (*corev1.Service, error) {
return s.listers.Service.ByKey(key) return s.listers.Service.ByKey(key)
} }
// GetIngress returns the Ingress matching key. // getIngress returns the Ingress matching key.
func (s k8sStore) GetIngress(key string) (*extensions.Ingress, error) { func (s k8sStore) getIngress(key string) (*extensions.Ingress, error) {
return s.listers.Ingress.ByKey(key) ing, err := s.listers.IngressWithAnnotation.ByKey(key)
if err != nil {
return nil, err
}
return &ing.Ingress, nil
} }
// ListIngresses returns the list of Ingresses // ListIngresses returns the list of Ingresses
func (s k8sStore) ListIngresses() []*ingress.Ingress { func (s k8sStore) ListIngresses() []*ingress.Ingress {
// filter ingress rules // filter ingress rules
var ingresses []*ingress.Ingress ingresses := make([]*ingress.Ingress, 0)
for _, item := range s.listers.Ingress.List() { for _, item := range s.listers.IngressWithAnnotation.List() {
ing := item.(*extensions.Ingress) ing := item.(*ingress.Ingress)
if !class.IsValid(ing) { ingresses = append(ingresses, ing)
continue
}
ingKey := k8s.MetaNamespaceKey(ing)
anns, err := s.getIngressAnnotations(ingKey)
if err != nil {
glog.Errorf("Error getting Ingress annotations %q: %v", ingKey, err)
}
for ri, rule := range ing.Spec.Rules {
if rule.HTTP == nil {
continue
}
for pi, path := range rule.HTTP.Paths {
if path.Path == "" {
ing.Spec.Rules[ri].HTTP.Paths[pi].Path = "/"
}
}
}
ingresses = append(ingresses, &ingress.Ingress{
Ingress: *ing,
ParsedAnnotations: anns,
})
} }
return ingresses return ingresses
} }
// getIngressAnnotations returns the parsed annotations of an Ingress matching key.
func (s k8sStore) getIngressAnnotations(key string) (*annotations.Ingress, error) {
ia, err := s.listers.IngressAnnotation.ByKey(key)
if err != nil {
return &annotations.Ingress{}, err
}
return ia, nil
}
// GetLocalSSLCert returns the local copy of a SSLCert // GetLocalSSLCert returns the local copy of a SSLCert
func (s k8sStore) GetLocalSSLCert(key string) (*ingress.SSLCert, error) { func (s k8sStore) GetLocalSSLCert(key string) (*ingress.SSLCert, error) {
return s.sslStore.ByKey(key) return s.sslStore.ByKey(key)

View file

@ -38,6 +38,7 @@ import (
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/fake"
"k8s.io/ingress-nginx/internal/file" "k8s.io/ingress-nginx/internal/file"
"k8s.io/ingress-nginx/internal/ingress"
"k8s.io/ingress-nginx/internal/ingress/annotations/parser" "k8s.io/ingress-nginx/internal/ingress/annotations/parser"
"k8s.io/ingress-nginx/internal/k8s" "k8s.io/ingress-nginx/internal/k8s"
"k8s.io/ingress-nginx/test/e2e/framework" "k8s.io/ingress-nginx/test/e2e/framework"
@ -86,14 +87,6 @@ func TestStore(t *testing.T) {
storer.Run(stopCh) storer.Run(stopCh)
key := fmt.Sprintf("%v/anything", ns) key := fmt.Sprintf("%v/anything", ns)
ing, err := storer.GetIngress(key)
if err == nil {
t.Errorf("expected an error but none returned")
}
if ing != nil {
t.Errorf("expected an Ingres but none returned")
}
ls, err := storer.GetLocalSSLCert(key) ls, err := storer.GetLocalSSLCert(key)
if err == nil { if err == nil {
t.Errorf("expected an error but none returned") t.Errorf("expected an error but none returned")
@ -753,9 +746,9 @@ func newStore(t *testing.T) *k8sStore {
return &k8sStore{ return &k8sStore{
listers: &Lister{ listers: &Lister{
// add more listers if needed // add more listers if needed
Ingress: IngressLister{cache.NewStore(cache.MetaNamespaceKeyFunc)}, Ingress: IngressLister{cache.NewStore(cache.MetaNamespaceKeyFunc)},
IngressAnnotation: IngressAnnotationsLister{cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc)}, IngressWithAnnotation: IngressWithAnnotationsLister{cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc)},
Pod: PodLister{cache.NewStore(cache.MetaNamespaceKeyFunc)}, Pod: PodLister{cache.NewStore(cache.MetaNamespaceKeyFunc)},
}, },
sslStore: NewSSLCertTracker(), sslStore: NewSSLCertTracker(),
filesystem: fs, filesystem: fs,
@ -833,58 +826,43 @@ func TestUpdateSecretIngressMap(t *testing.T) {
func TestListIngresses(t *testing.T) { func TestListIngresses(t *testing.T) {
s := newStore(t) s := newStore(t)
ingEmptyClass := &extensions.Ingress{ ingressToIgnore := &ingress.Ingress{
ObjectMeta: metav1.ObjectMeta{ Ingress: extensions.Ingress{
Name: "test-1", ObjectMeta: metav1.ObjectMeta{
Namespace: "testns", Name: "test-2",
}, Namespace: "testns",
Spec: extensions.IngressSpec{ Annotations: map[string]string{
Backend: &extensions.IngressBackend{ "kubernetes.io/ingress.class": "something",
ServiceName: "demo", },
ServicePort: intstr.FromInt(80),
}, },
Rules: []extensions.IngressRule{ Spec: extensions.IngressSpec{
{ Backend: &extensions.IngressBackend{
Host: "foo.bar", ServiceName: "demo",
ServicePort: intstr.FromInt(80),
}, },
}, },
}, },
} }
s.listers.Ingress.Add(ingEmptyClass) s.listers.IngressWithAnnotation.Add(ingressToIgnore)
ingressToIgnore := &extensions.Ingress{ ingressWithoutPath := &ingress.Ingress{
ObjectMeta: metav1.ObjectMeta{ Ingress: extensions.Ingress{
Name: "test-2", ObjectMeta: metav1.ObjectMeta{
Namespace: "testns", Name: "test-3",
Annotations: map[string]string{ Namespace: "testns",
"kubernetes.io/ingress.class": "something",
}, },
}, Spec: extensions.IngressSpec{
Spec: extensions.IngressSpec{ Rules: []extensions.IngressRule{
Backend: &extensions.IngressBackend{ {
ServiceName: "demo", Host: "foo.bar",
ServicePort: intstr.FromInt(80), IngressRuleValue: extensions.IngressRuleValue{
}, HTTP: &extensions.HTTPIngressRuleValue{
}, Paths: []extensions.HTTPIngressPath{
} {
s.listers.Ingress.Add(ingressToIgnore) Backend: extensions.IngressBackend{
ServiceName: "demo",
ingressWithoutPath := &extensions.Ingress{ ServicePort: intstr.FromInt(80),
ObjectMeta: metav1.ObjectMeta{ },
Name: "test-3",
Namespace: "testns",
},
Spec: extensions.IngressSpec{
Rules: []extensions.IngressRule{
{
Host: "foo.bar",
IngressRuleValue: extensions.IngressRuleValue{
HTTP: &extensions.HTTPIngressRuleValue{
Paths: []extensions.HTTPIngressPath{
{
Backend: extensions.IngressBackend{
ServiceName: "demo",
ServicePort: intstr.FromInt(80),
}, },
}, },
}, },
@ -894,28 +872,30 @@ func TestListIngresses(t *testing.T) {
}, },
}, },
} }
s.listers.Ingress.Add(ingressWithoutPath) s.listers.IngressWithAnnotation.Add(ingressWithoutPath)
ingressWithNginxClass := &extensions.Ingress{ ingressWithNginxClass := &ingress.Ingress{
ObjectMeta: metav1.ObjectMeta{ Ingress: extensions.Ingress{
Name: "test-4", ObjectMeta: metav1.ObjectMeta{
Namespace: "testns", Name: "test-4",
Annotations: map[string]string{ Namespace: "testns",
"kubernetes.io/ingress.class": "nginx", Annotations: map[string]string{
"kubernetes.io/ingress.class": "nginx",
},
}, },
}, Spec: extensions.IngressSpec{
Spec: extensions.IngressSpec{ Rules: []extensions.IngressRule{
Rules: []extensions.IngressRule{ {
{ Host: "foo.bar",
Host: "foo.bar", IngressRuleValue: extensions.IngressRuleValue{
IngressRuleValue: extensions.IngressRuleValue{ HTTP: &extensions.HTTPIngressRuleValue{
HTTP: &extensions.HTTPIngressRuleValue{ Paths: []extensions.HTTPIngressPath{
Paths: []extensions.HTTPIngressPath{ {
{ Path: "/demo",
Path: "/demo", Backend: extensions.IngressBackend{
Backend: extensions.IngressBackend{ ServiceName: "demo",
ServiceName: "demo", ServicePort: intstr.FromInt(80),
ServicePort: intstr.FromInt(80), },
}, },
}, },
}, },
@ -925,7 +905,7 @@ func TestListIngresses(t *testing.T) {
}, },
}, },
} }
s.listers.Ingress.Add(ingressWithNginxClass) s.listers.IngressWithAnnotation.Add(ingressWithNginxClass)
ingresses := s.ListIngresses() ingresses := s.ListIngresses()
if s := len(ingresses); s != 3 { if s := len(ingresses); s != 3 {