Add prefix nginx to annotations
This commit is contained in:
parent
97577c07a5
commit
8f1ff15a6e
54 changed files with 445 additions and 441 deletions
|
@ -122,6 +122,8 @@ func parseFlags() (bool, *controller.Configuration, error) {
|
|||
sslProxyPort = flags.Int("ssl-passtrough-proxy-port", 442, `Default port to use internally for SSL when SSL Passthgough is enabled`)
|
||||
defServerPort = flags.Int("default-server-port", 8181, `Default port to use for exposing the default server (catch all)`)
|
||||
healthzPort = flags.Int("healthz-port", 10254, "port for healthz endpoint.")
|
||||
|
||||
annotationsPrefix = flags.String("annotations-prefix", "nginx.ingress.kubernetes.io", `Prefix of the ingress annotations.`)
|
||||
)
|
||||
|
||||
flag.Set("logtostderr", "true")
|
||||
|
@ -177,6 +179,7 @@ func parseFlags() (bool, *controller.Configuration, error) {
|
|||
}
|
||||
|
||||
config := &controller.Configuration{
|
||||
AnnotationsPrefix: *annotationsPrefix,
|
||||
APIServerHost: *apiserverHost,
|
||||
KubeConfigFile: *kubeConfigFile,
|
||||
UpdateStatus: *updateStatus,
|
||||
|
|
|
@ -20,22 +20,20 @@ import (
|
|||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
)
|
||||
|
||||
const (
|
||||
annotation = "ingress.kubernetes.io/server-alias"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
type alias struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new Alias annotation parser
|
||||
func NewParser() parser.IngressAnnotation {
|
||||
return alias{}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return alias{r}
|
||||
}
|
||||
|
||||
// Parse parses the annotations contained in the ingress rule
|
||||
// used to add an alias to the provided hosts
|
||||
func (a alias) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
return parser.GetStringAnnotation(annotation, ing)
|
||||
return parser.GetStringAnnotation("server-alias", ing, a.r)
|
||||
}
|
||||
|
|
|
@ -22,10 +22,13 @@ import (
|
|||
api "k8s.io/api/core/v1"
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
const annotation = "nginx/server-alias"
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
ap := NewParser()
|
||||
ap := NewParser(&resolver.Mock{})
|
||||
if ap == nil {
|
||||
t.Fatalf("expected a parser.IngressAnnotation but returned nil")
|
||||
}
|
||||
|
|
|
@ -54,13 +54,6 @@ import (
|
|||
// DeniedKeyName name of the key that contains the reason to deny a location
|
||||
const DeniedKeyName = "Denied"
|
||||
|
||||
type config interface {
|
||||
resolver.AuthCertificate
|
||||
resolver.DefaultBackend
|
||||
resolver.Secret
|
||||
resolver.Service
|
||||
}
|
||||
|
||||
// Ingress defines the valid annotations present in one NGINX Ingress rule
|
||||
type Ingress struct {
|
||||
metav1.ObjectMeta
|
||||
|
@ -91,37 +84,35 @@ type Ingress struct {
|
|||
|
||||
// Extractor defines the annotation parsers to be used in the extraction of annotations
|
||||
type Extractor struct {
|
||||
secretResolver resolver.Secret
|
||||
annotations map[string]parser.IngressAnnotation
|
||||
annotations map[string]parser.IngressAnnotation
|
||||
}
|
||||
|
||||
// NewAnnotationExtractor creates a new annotations extractor
|
||||
func NewAnnotationExtractor(cfg config) Extractor {
|
||||
func NewAnnotationExtractor(cfg resolver.Resolver) Extractor {
|
||||
return Extractor{
|
||||
cfg,
|
||||
map[string]parser.IngressAnnotation{
|
||||
"Alias": alias.NewParser(),
|
||||
"Alias": alias.NewParser(cfg),
|
||||
"BasicDigestAuth": auth.NewParser(auth.AuthDirectory, cfg),
|
||||
"CertificateAuth": authtls.NewParser(cfg),
|
||||
"ClientBodyBufferSize": clientbodybuffersize.NewParser(),
|
||||
"ConfigurationSnippet": snippet.NewParser(),
|
||||
"CorsConfig": cors.NewParser(),
|
||||
"ClientBodyBufferSize": clientbodybuffersize.NewParser(cfg),
|
||||
"ConfigurationSnippet": snippet.NewParser(cfg),
|
||||
"CorsConfig": cors.NewParser(cfg),
|
||||
"DefaultBackend": defaultbackend.NewParser(cfg),
|
||||
"ExternalAuth": authreq.NewParser(),
|
||||
"ExternalAuth": authreq.NewParser(cfg),
|
||||
"HealthCheck": healthcheck.NewParser(cfg),
|
||||
"Proxy": proxy.NewParser(cfg),
|
||||
"RateLimit": ratelimit.NewParser(cfg),
|
||||
"Redirect": redirect.NewParser(),
|
||||
"Redirect": redirect.NewParser(cfg),
|
||||
"Rewrite": rewrite.NewParser(cfg),
|
||||
"SecureUpstream": secureupstream.NewParser(cfg),
|
||||
"ServerSnippet": serversnippet.NewParser(),
|
||||
"ServiceUpstream": serviceupstream.NewParser(),
|
||||
"SessionAffinity": sessionaffinity.NewParser(),
|
||||
"SSLPassthrough": sslpassthrough.NewParser(),
|
||||
"ServerSnippet": serversnippet.NewParser(cfg),
|
||||
"ServiceUpstream": serviceupstream.NewParser(cfg),
|
||||
"SessionAffinity": sessionaffinity.NewParser(cfg),
|
||||
"SSLPassthrough": sslpassthrough.NewParser(cfg),
|
||||
"UsePortInRedirects": portinredirect.NewParser(cfg),
|
||||
"UpstreamHashBy": upstreamhashby.NewParser(),
|
||||
"UpstreamVhost": upstreamvhost.NewParser(),
|
||||
"VtsFilterKey": vtsfilterkey.NewParser(),
|
||||
"UpstreamHashBy": upstreamhashby.NewParser(cfg),
|
||||
"UpstreamVhost": upstreamvhost.NewParser(cfg),
|
||||
"VtsFilterKey": vtsfilterkey.NewParser(cfg),
|
||||
"Whitelist": ipwhitelist.NewParser(cfg),
|
||||
},
|
||||
}
|
||||
|
|
|
@ -29,25 +29,26 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
annotationSecureUpstream = "ingress.kubernetes.io/secure-backends"
|
||||
annotationSecureVerifyCACert = "ingress.kubernetes.io/secure-verify-ca-secret"
|
||||
annotationUpsMaxFails = "ingress.kubernetes.io/upstream-max-fails"
|
||||
annotationUpsFailTimeout = "ingress.kubernetes.io/upstream-fail-timeout"
|
||||
annotationPassthrough = "ingress.kubernetes.io/ssl-passthrough"
|
||||
annotationAffinityType = "ingress.kubernetes.io/affinity"
|
||||
annotationCorsEnabled = "ingress.kubernetes.io/enable-cors"
|
||||
annotationCorsAllowOrigin = "ingress.kubernetes.io/cors-allow-origin"
|
||||
annotationCorsAllowMethods = "ingress.kubernetes.io/cors-allow-methods"
|
||||
annotationCorsAllowHeaders = "ingress.kubernetes.io/cors-allow-headers"
|
||||
annotationCorsAllowCredentials = "ingress.kubernetes.io/cors-allow-credentials"
|
||||
annotationSecureUpstream = "nginx/secure-backends"
|
||||
annotationSecureVerifyCACert = "nginx/secure-verify-ca-secret"
|
||||
annotationUpsMaxFails = "nginx/upstream-max-fails"
|
||||
annotationUpsFailTimeout = "nginx/upstream-fail-timeout"
|
||||
annotationPassthrough = "nginx/ssl-passthrough"
|
||||
annotationAffinityType = "nginx/affinity"
|
||||
annotationCorsEnabled = "nginx/enable-cors"
|
||||
annotationCorsAllowOrigin = "nginx/cors-allow-origin"
|
||||
annotationCorsAllowMethods = "nginx/cors-allow-methods"
|
||||
annotationCorsAllowHeaders = "nginx/cors-allow-headers"
|
||||
annotationCorsAllowCredentials = "nginx/cors-allow-credentials"
|
||||
defaultCorsMethods = "GET, PUT, POST, DELETE, PATCH, OPTIONS"
|
||||
defaultCorsHeaders = "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization"
|
||||
annotationAffinityCookieName = "ingress.kubernetes.io/session-cookie-name"
|
||||
annotationAffinityCookieHash = "ingress.kubernetes.io/session-cookie-hash"
|
||||
annotationUpstreamHashBy = "ingress.kubernetes.io/upstream-hash-by"
|
||||
annotationAffinityCookieName = "nginx/session-cookie-name"
|
||||
annotationAffinityCookieHash = "nginx/session-cookie-hash"
|
||||
annotationUpstreamHashBy = "nginx/upstream-hash-by"
|
||||
)
|
||||
|
||||
type mockCfg struct {
|
||||
resolver.Mock
|
||||
MockSecrets map[string]*apiv1.Secret
|
||||
MockServices map[string]*apiv1.Service
|
||||
}
|
||||
|
|
|
@ -33,12 +33,6 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
const (
|
||||
authType = "ingress.kubernetes.io/auth-type"
|
||||
authSecret = "ingress.kubernetes.io/auth-secret"
|
||||
authRealm = "ingress.kubernetes.io/auth-realm"
|
||||
)
|
||||
|
||||
var (
|
||||
authTypeRegex = regexp.MustCompile(`basic|digest`)
|
||||
// AuthDirectory default directory used to store files
|
||||
|
@ -83,12 +77,12 @@ func (bd1 *Config) Equal(bd2 *Config) bool {
|
|||
}
|
||||
|
||||
type auth struct {
|
||||
secretResolver resolver.Secret
|
||||
authDirectory string
|
||||
r resolver.Resolver
|
||||
authDirectory string
|
||||
}
|
||||
|
||||
// NewParser creates a new authentication annotation parser
|
||||
func NewParser(authDirectory string, sr resolver.Secret) parser.IngressAnnotation {
|
||||
func NewParser(authDirectory string, r resolver.Resolver) parser.IngressAnnotation {
|
||||
os.MkdirAll(authDirectory, 0755)
|
||||
|
||||
currPath := authDirectory
|
||||
|
@ -100,7 +94,7 @@ func NewParser(authDirectory string, sr resolver.Secret) parser.IngressAnnotatio
|
|||
}
|
||||
}
|
||||
|
||||
return auth{sr, authDirectory}
|
||||
return auth{r, authDirectory}
|
||||
}
|
||||
|
||||
// Parse parses the annotations contained in the ingress
|
||||
|
@ -108,7 +102,7 @@ func NewParser(authDirectory string, sr resolver.Secret) parser.IngressAnnotatio
|
|||
// and generated an htpasswd compatible file to be used as source
|
||||
// during the authentication process
|
||||
func (a auth) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
at, err := parser.GetStringAnnotation(authType, ing)
|
||||
at, err := parser.GetStringAnnotation("auth-type", ing, a.r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -117,7 +111,7 @@ func (a auth) Parse(ing *extensions.Ingress) (interface{}, error) {
|
|||
return nil, ing_errors.NewLocationDenied("invalid authentication type")
|
||||
}
|
||||
|
||||
s, err := parser.GetStringAnnotation(authSecret, ing)
|
||||
s, err := parser.GetStringAnnotation("auth-secret", ing, a.r)
|
||||
if err != nil {
|
||||
return nil, ing_errors.LocationDenied{
|
||||
Reason: errors.Wrap(err, "error reading secret name from annotation"),
|
||||
|
@ -125,14 +119,14 @@ func (a auth) Parse(ing *extensions.Ingress) (interface{}, error) {
|
|||
}
|
||||
|
||||
name := fmt.Sprintf("%v/%v", ing.Namespace, s)
|
||||
secret, err := a.secretResolver.GetSecret(name)
|
||||
secret, err := a.r.GetSecret(name)
|
||||
if err != nil {
|
||||
return nil, ing_errors.LocationDenied{
|
||||
Reason: errors.Wrapf(err, "unexpected error reading secret %v", name),
|
||||
}
|
||||
}
|
||||
|
||||
realm, _ := parser.GetStringAnnotation(authRealm, ing)
|
||||
realm, _ := parser.GetStringAnnotation("auth-realm", ing, a.r)
|
||||
|
||||
passFile := fmt.Sprintf("%v/%v-%v.passwd", a.authDirectory, ing.GetNamespace(), ing.GetName())
|
||||
err = dumpSecret(passFile, secret)
|
||||
|
|
|
@ -29,6 +29,7 @@ import (
|
|||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func buildIngress() *extensions.Ingress {
|
||||
|
@ -67,6 +68,7 @@ func buildIngress() *extensions.Ingress {
|
|||
}
|
||||
|
||||
type mockSecret struct {
|
||||
resolver.Mock
|
||||
}
|
||||
|
||||
func (m mockSecret) GetSecret(name string) (*api.Secret, error) {
|
||||
|
@ -87,7 +89,7 @@ func TestIngressWithoutAuth(t *testing.T) {
|
|||
ing := buildIngress()
|
||||
_, dir, _ := dummySecretContent(t)
|
||||
defer os.RemoveAll(dir)
|
||||
_, err := NewParser(dir, mockSecret{}).Parse(ing)
|
||||
_, err := NewParser(dir, &mockSecret{}).Parse(ing)
|
||||
if err == nil {
|
||||
t.Error("Expected error with ingress without annotations")
|
||||
}
|
||||
|
@ -97,15 +99,15 @@ func TestIngressAuth(t *testing.T) {
|
|||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[authType] = "basic"
|
||||
data[authSecret] = "demo-secret"
|
||||
data[authRealm] = "-realm-"
|
||||
data["nginx/auth-type"] = "basic"
|
||||
data["nginx/auth-secret"] = "demo-secret"
|
||||
data["nginx/auth-realm"] = "-realm-"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
_, dir, _ := dummySecretContent(t)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
i, err := NewParser(dir, mockSecret{}).Parse(ing)
|
||||
i, err := NewParser(dir, &mockSecret{}).Parse(ing)
|
||||
if err != nil {
|
||||
t.Errorf("Uxpected error with ingress: %v", err)
|
||||
}
|
||||
|
@ -128,9 +130,9 @@ func TestIngressAuthWithoutSecret(t *testing.T) {
|
|||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[authType] = "basic"
|
||||
data[authSecret] = "invalid-secret"
|
||||
data[authRealm] = "-realm-"
|
||||
data["nginx/auth-type"] = "basic"
|
||||
data["nginx/auth-secret"] = "invalid-secret"
|
||||
data["nginx/auth-realm"] = "-realm-"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
_, dir, _ := dummySecretContent(t)
|
||||
|
|
|
@ -25,17 +25,10 @@ import (
|
|||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
ing_errors "k8s.io/ingress-nginx/internal/ingress/errors"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
const (
|
||||
// external URL that provides the authentication
|
||||
authURL = "ingress.kubernetes.io/auth-url"
|
||||
authSigninURL = "ingress.kubernetes.io/auth-signin"
|
||||
authMethod = "ingress.kubernetes.io/auth-method"
|
||||
authHeaders = "ingress.kubernetes.io/auth-response-headers"
|
||||
)
|
||||
|
||||
// External returns external authentication configuration for an Ingress rule
|
||||
// Config returns external authentication configuration for an Ingress rule
|
||||
type Config struct {
|
||||
URL string `json:"url"`
|
||||
// Host contains the hostname defined in the URL
|
||||
|
@ -108,17 +101,18 @@ func validHeader(header string) bool {
|
|||
}
|
||||
|
||||
type authReq struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new authentication request annotation parser
|
||||
func NewParser() parser.IngressAnnotation {
|
||||
return authReq{}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return authReq{r}
|
||||
}
|
||||
|
||||
// ParseAnnotations parses the annotations contained in the ingress
|
||||
// rule used to use an Config URL as source for authentication
|
||||
func (a authReq) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
str, err := parser.GetStringAnnotation(authURL, ing)
|
||||
str, err := parser.GetStringAnnotation("auth-url", ing, a.r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -127,7 +121,7 @@ func (a authReq) Parse(ing *extensions.Ingress) (interface{}, error) {
|
|||
return nil, ing_errors.NewLocationDenied("an empty string is not a valid URL")
|
||||
}
|
||||
|
||||
signin, _ := parser.GetStringAnnotation(authSigninURL, ing)
|
||||
signin, _ := parser.GetStringAnnotation("auth-signin", ing, a.r)
|
||||
|
||||
ur, err := url.Parse(str)
|
||||
if err != nil {
|
||||
|
@ -144,13 +138,13 @@ func (a authReq) Parse(ing *extensions.Ingress) (interface{}, error) {
|
|||
return nil, ing_errors.NewLocationDenied("invalid url host")
|
||||
}
|
||||
|
||||
m, _ := parser.GetStringAnnotation(authMethod, ing)
|
||||
m, _ := parser.GetStringAnnotation("auth-method", ing, a.r)
|
||||
if len(m) != 0 && !validMethod(m) {
|
||||
return nil, ing_errors.NewLocationDenied("invalid HTTP method")
|
||||
}
|
||||
|
||||
h := []string{}
|
||||
hstr, _ := parser.GetStringAnnotation(authHeaders, ing)
|
||||
hstr, _ := parser.GetStringAnnotation("auth-response-headers", ing, a.r)
|
||||
if len(hstr) != 0 {
|
||||
|
||||
harr := strings.Split(hstr, ",")
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
api "k8s.io/api/core/v1"
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
@ -86,11 +87,11 @@ func TestAnnotations(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, test := range tests {
|
||||
data[authURL] = test.url
|
||||
data[authSigninURL] = test.signinURL
|
||||
data[authMethod] = fmt.Sprintf("%v", test.method)
|
||||
data["nginx/auth-url"] = test.url
|
||||
data["nginx/auth-signin"] = test.signinURL
|
||||
data["nginx/auth-method"] = fmt.Sprintf("%v", test.method)
|
||||
|
||||
i, err := NewParser().Parse(ing)
|
||||
i, err := NewParser(&resolver.Mock{}).Parse(ing)
|
||||
if test.expErr {
|
||||
if err == nil {
|
||||
t.Errorf("%v: expected error but retuned nil", test.title)
|
||||
|
@ -136,11 +137,11 @@ func TestHeaderAnnotations(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, test := range tests {
|
||||
data[authURL] = test.url
|
||||
data[authHeaders] = test.headers
|
||||
data[authMethod] = "GET"
|
||||
data["nginx/auth-url"] = test.url
|
||||
data["nginx/auth-response-headers"] = test.headers
|
||||
data["nginx/auth-method"] = "GET"
|
||||
|
||||
i, err := NewParser().Parse(ing)
|
||||
i, err := NewParser(&resolver.Mock{}).Parse(ing)
|
||||
if test.expErr {
|
||||
if err == nil {
|
||||
t.Errorf("%v: expected error but retuned nil", err.Error())
|
||||
|
|
|
@ -29,13 +29,8 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
// name of the secret
|
||||
annotationAuthTLSSecret = "ingress.kubernetes.io/auth-tls-secret"
|
||||
annotationAuthVerifyClient = "ingress.kubernetes.io/auth-tls-verify-client"
|
||||
annotationAuthTLSDepth = "ingress.kubernetes.io/auth-tls-verify-depth"
|
||||
annotationAuthTLSErrorPage = "ingress.kubernetes.io/auth-tls-error-page"
|
||||
defaultAuthTLSDepth = 1
|
||||
defaultAuthVerifyClient = "on"
|
||||
defaultAuthTLSDepth = 1
|
||||
defaultAuthVerifyClient = "on"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -75,19 +70,19 @@ func (assl1 *Config) Equal(assl2 *Config) bool {
|
|||
}
|
||||
|
||||
// NewParser creates a new TLS authentication annotation parser
|
||||
func NewParser(resolver resolver.AuthCertificate) parser.IngressAnnotation {
|
||||
func NewParser(resolver resolver.Resolver) parser.IngressAnnotation {
|
||||
return authTLS{resolver}
|
||||
}
|
||||
|
||||
type authTLS struct {
|
||||
certResolver resolver.AuthCertificate
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// Parse parses the annotations contained in the ingress
|
||||
// rule used to use a Certificate as authentication method
|
||||
func (a authTLS) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
|
||||
tlsauthsecret, err := parser.GetStringAnnotation(annotationAuthTLSSecret, ing)
|
||||
tlsauthsecret, err := parser.GetStringAnnotation(a.r.GetAnnotationWithPrefix("auth-tls-secret"), ing, a.r)
|
||||
if err != nil {
|
||||
return &Config{}, err
|
||||
}
|
||||
|
@ -101,24 +96,24 @@ func (a authTLS) Parse(ing *extensions.Ingress) (interface{}, error) {
|
|||
return &Config{}, ing_errors.NewLocationDenied(err.Error())
|
||||
}
|
||||
|
||||
tlsVerifyClient, err := parser.GetStringAnnotation(annotationAuthVerifyClient, ing)
|
||||
tlsVerifyClient, err := parser.GetStringAnnotation("auth-tls-verify-client", ing, a.r)
|
||||
if err != nil || !authVerifyClientRegex.MatchString(tlsVerifyClient) {
|
||||
tlsVerifyClient = defaultAuthVerifyClient
|
||||
}
|
||||
|
||||
tlsdepth, err := parser.GetIntAnnotation(annotationAuthTLSDepth, ing)
|
||||
tlsdepth, err := parser.GetIntAnnotation("auth-tls-verify-depth", ing, a.r)
|
||||
if err != nil || tlsdepth == 0 {
|
||||
tlsdepth = defaultAuthTLSDepth
|
||||
}
|
||||
|
||||
authCert, err := a.certResolver.GetAuthCertificate(tlsauthsecret)
|
||||
authCert, err := a.r.GetAuthCertificate(tlsauthsecret)
|
||||
if err != nil {
|
||||
return &Config{}, ing_errors.LocationDenied{
|
||||
Reason: errors.Wrap(err, "error obtaining certificate"),
|
||||
}
|
||||
}
|
||||
|
||||
errorpage, err := parser.GetStringAnnotation(annotationAuthTLSErrorPage, ing)
|
||||
errorpage, err := parser.GetStringAnnotation("auth-tls-error-page", ing, a.r)
|
||||
if err != nil || errorpage == "" {
|
||||
errorpage = ""
|
||||
}
|
||||
|
|
|
@ -19,9 +19,6 @@ package class
|
|||
import (
|
||||
"github.com/golang/glog"
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
"k8s.io/ingress-nginx/internal/ingress/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -35,9 +32,9 @@ const (
|
|||
// the ingress.class annotation, or it's set to the configured in the
|
||||
// ingress controller.
|
||||
func IsValid(ing *extensions.Ingress, controller, defClass string) bool {
|
||||
ingress, err := parser.GetStringAnnotation(IngressKey, ing)
|
||||
if err != nil && !errors.IsMissingAnnotations(err) {
|
||||
glog.Warningf("unexpected error reading ingress annotation: %v", err)
|
||||
ingress, ok := ing.GetAnnotations()[IngressKey]
|
||||
if !ok {
|
||||
glog.V(3).Infof("annotation %v is not present in ingress %v/%v", IngressKey, ing.Namespace, ing.Name)
|
||||
}
|
||||
|
||||
// we have 2 valid combinations
|
||||
|
|
|
@ -20,22 +20,20 @@ import (
|
|||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
)
|
||||
|
||||
const (
|
||||
annotation = "ingress.kubernetes.io/client-body-buffer-size"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
type clientBodyBufferSize struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new clientBodyBufferSize annotation parser
|
||||
func NewParser() parser.IngressAnnotation {
|
||||
return clientBodyBufferSize{}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return clientBodyBufferSize{r}
|
||||
}
|
||||
|
||||
// Parse parses the annotations contained in the ingress rule
|
||||
// used to add an client-body-buffer-size to the provided locations
|
||||
func (a clientBodyBufferSize) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
return parser.GetStringAnnotation(annotation, ing)
|
||||
func (cbbs clientBodyBufferSize) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
return parser.GetStringAnnotation("client-body-buffer-size", ing, cbbs.r)
|
||||
}
|
||||
|
|
|
@ -22,10 +22,12 @@ import (
|
|||
api "k8s.io/api/core/v1"
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
ap := NewParser()
|
||||
annotation := "nginx/client-body-buffer-size"
|
||||
ap := NewParser(&resolver.Mock{})
|
||||
if ap == nil {
|
||||
t.Fatalf("expected a parser.IngressAnnotation but returned nil")
|
||||
}
|
||||
|
|
|
@ -22,14 +22,10 @@ import (
|
|||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
const (
|
||||
annotationCorsEnabled = "ingress.kubernetes.io/enable-cors"
|
||||
annotationCorsAllowOrigin = "ingress.kubernetes.io/cors-allow-origin"
|
||||
annotationCorsAllowMethods = "ingress.kubernetes.io/cors-allow-methods"
|
||||
annotationCorsAllowHeaders = "ingress.kubernetes.io/cors-allow-headers"
|
||||
annotationCorsAllowCredentials = "ingress.kubernetes.io/cors-allow-credentials"
|
||||
// Default values
|
||||
defaultCorsMethods = "GET, PUT, POST, DELETE, PATCH, OPTIONS"
|
||||
defaultCorsHeaders = "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization"
|
||||
|
@ -49,6 +45,7 @@ var (
|
|||
)
|
||||
|
||||
type cors struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// Config contains the Cors configuration to be used in the Ingress
|
||||
|
@ -61,8 +58,8 @@ type Config struct {
|
|||
}
|
||||
|
||||
// NewParser creates a new CORS annotation parser
|
||||
func NewParser() parser.IngressAnnotation {
|
||||
return cors{}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return cors{r}
|
||||
}
|
||||
|
||||
// Equal tests for equality between two External types
|
||||
|
@ -94,28 +91,28 @@ func (c1 *Config) Equal(c2 *Config) bool {
|
|||
|
||||
// Parse parses the annotations contained in the ingress
|
||||
// rule used to indicate if the location/s should allows CORS
|
||||
func (a cors) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
corsenabled, err := parser.GetBoolAnnotation(annotationCorsEnabled, ing)
|
||||
func (c cors) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
corsenabled, err := parser.GetBoolAnnotation("enable-cors", ing, c.r)
|
||||
if err != nil {
|
||||
corsenabled = false
|
||||
}
|
||||
|
||||
corsalloworigin, err := parser.GetStringAnnotation(annotationCorsAllowOrigin, ing)
|
||||
corsalloworigin, err := parser.GetStringAnnotation("cors-allow-origin", ing, c.r)
|
||||
if err != nil || corsalloworigin == "" || !corsOriginRegex.MatchString(corsalloworigin) {
|
||||
corsalloworigin = "*"
|
||||
}
|
||||
|
||||
corsallowheaders, err := parser.GetStringAnnotation(annotationCorsAllowHeaders, ing)
|
||||
corsallowheaders, err := parser.GetStringAnnotation("cors-allow-headers", ing, c.r)
|
||||
if err != nil || corsallowheaders == "" || !corsHeadersRegex.MatchString(corsallowheaders) {
|
||||
corsallowheaders = defaultCorsHeaders
|
||||
}
|
||||
|
||||
corsallowmethods, err := parser.GetStringAnnotation(annotationCorsAllowMethods, ing)
|
||||
corsallowmethods, err := parser.GetStringAnnotation("cors-allow-methods", ing, c.r)
|
||||
if err != nil || corsallowmethods == "" || !corsMethodsRegex.MatchString(corsallowmethods) {
|
||||
corsallowmethods = defaultCorsMethods
|
||||
}
|
||||
|
||||
corsallowcredentials, err := parser.GetBoolAnnotation(annotationCorsAllowCredentials, ing)
|
||||
corsallowcredentials, err := parser.GetBoolAnnotation("cors-allow-credentials", ing, c.r)
|
||||
if err != nil {
|
||||
corsallowcredentials = true
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func buildIngress() *extensions.Ingress {
|
||||
|
@ -64,14 +65,14 @@ func TestIngressCorsConfig(t *testing.T) {
|
|||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[annotationCorsEnabled] = "true"
|
||||
data[annotationCorsAllowHeaders] = "DNT,X-CustomHeader, Keep-Alive,User-Agent"
|
||||
data[annotationCorsAllowCredentials] = "false"
|
||||
data[annotationCorsAllowMethods] = "PUT, GET,OPTIONS, PATCH, $nginx_version"
|
||||
data[annotationCorsAllowOrigin] = "https://origin123.test.com:4443"
|
||||
data["nginx/enable-cors"] = "true"
|
||||
data["nginx/cors-allow-headers"] = "DNT,X-CustomHeader, Keep-Alive,User-Agent"
|
||||
data["nginx/cors-allow-credentials"] = "false"
|
||||
data["nginx/cors-allow-methods"] = "PUT, GET,OPTIONS, PATCH, $nginx_version"
|
||||
data["nginx/cors-allow-origin"] = "https://origin123.test.com:4443"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
corst, _ := NewParser().Parse(ing)
|
||||
corst, _ := NewParser(&resolver.Mock{}).Parse(ing)
|
||||
nginxCors, ok := corst.(*Config)
|
||||
if !ok {
|
||||
t.Errorf("expected a Config type")
|
||||
|
|
|
@ -26,29 +26,25 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultBackend = "ingress.kubernetes.io/default-backend"
|
||||
)
|
||||
|
||||
type backend struct {
|
||||
serviceResolver resolver.Service
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new default backend annotation parser
|
||||
func NewParser(sr resolver.Service) parser.IngressAnnotation {
|
||||
return backend{sr}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return backend{r}
|
||||
}
|
||||
|
||||
// Parse parses the annotations contained in the ingress to use
|
||||
// a custom default backend
|
||||
func (db backend) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
s, err := parser.GetStringAnnotation(defaultBackend, ing)
|
||||
s, err := parser.GetStringAnnotation("default-backend", ing, db.r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
name := fmt.Sprintf("%v/%v", ing.Namespace, s)
|
||||
svc, err := db.serviceResolver.GetService(name)
|
||||
svc, err := db.r.GetService(name)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unexpected error reading service %v", name)
|
||||
}
|
||||
|
|
|
@ -23,11 +23,6 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
const (
|
||||
upsMaxFails = "ingress.kubernetes.io/upstream-max-fails"
|
||||
upsFailTimeout = "ingress.kubernetes.io/upstream-fail-timeout"
|
||||
)
|
||||
|
||||
// Config returns the URL and method to use check the status of
|
||||
// the upstream server/s
|
||||
type Config struct {
|
||||
|
@ -36,28 +31,28 @@ type Config struct {
|
|||
}
|
||||
|
||||
type healthCheck struct {
|
||||
backendResolver resolver.DefaultBackend
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new health check annotation parser
|
||||
func NewParser(br resolver.DefaultBackend) parser.IngressAnnotation {
|
||||
return healthCheck{br}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return healthCheck{r}
|
||||
}
|
||||
|
||||
// ParseAnnotations parses the annotations contained in the ingress
|
||||
// rule used to configure upstream check parameters
|
||||
func (a healthCheck) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
defBackend := a.backendResolver.GetDefaultBackend()
|
||||
func (hc healthCheck) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
defBackend := hc.r.GetDefaultBackend()
|
||||
if ing.GetAnnotations() == nil {
|
||||
return &Config{defBackend.UpstreamMaxFails, defBackend.UpstreamFailTimeout}, nil
|
||||
}
|
||||
|
||||
mf, err := parser.GetIntAnnotation(upsMaxFails, ing)
|
||||
mf, err := parser.GetIntAnnotation("upstream-max-fails", ing, hc.r)
|
||||
if err != nil {
|
||||
mf = defBackend.UpstreamMaxFails
|
||||
}
|
||||
|
||||
ft, err := parser.GetIntAnnotation(upsFailTimeout, ing)
|
||||
ft, err := parser.GetIntAnnotation("upstream-fail-timeout", ing, hc.r)
|
||||
if err != nil {
|
||||
ft = defBackend.UpstreamFailTimeout
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/defaults"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func buildIngress() *extensions.Ingress {
|
||||
|
@ -63,6 +64,7 @@ func buildIngress() *extensions.Ingress {
|
|||
}
|
||||
|
||||
type mockBackend struct {
|
||||
resolver.Mock
|
||||
}
|
||||
|
||||
func (m mockBackend) GetDefaultBackend() defaults.Backend {
|
||||
|
@ -73,7 +75,7 @@ func TestIngressHealthCheck(t *testing.T) {
|
|||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[upsMaxFails] = "2"
|
||||
data["nginx/upstream-max-fails"] = "2"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
hzi, _ := NewParser(mockBackend{}).Parse(ing)
|
||||
|
|
|
@ -30,10 +30,6 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
const (
|
||||
whitelist = "ingress.kubernetes.io/whitelist-source-range"
|
||||
)
|
||||
|
||||
// SourceRange returns the CIDR
|
||||
type SourceRange struct {
|
||||
CIDR []string `json:"cidr,omitEmpty"`
|
||||
|
@ -69,12 +65,12 @@ func (sr1 *SourceRange) Equal(sr2 *SourceRange) bool {
|
|||
}
|
||||
|
||||
type ipwhitelist struct {
|
||||
backendResolver resolver.DefaultBackend
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new whitelist annotation parser
|
||||
func NewParser(br resolver.DefaultBackend) parser.IngressAnnotation {
|
||||
return ipwhitelist{br}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return ipwhitelist{r}
|
||||
}
|
||||
|
||||
// ParseAnnotations parses the annotations contained in the ingress
|
||||
|
@ -82,10 +78,10 @@ func NewParser(br resolver.DefaultBackend) parser.IngressAnnotation {
|
|||
// Multiple ranges can specified using commas as separator
|
||||
// e.g. `18.0.0.0/8,56.0.0.0/8`
|
||||
func (a ipwhitelist) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
defBackend := a.backendResolver.GetDefaultBackend()
|
||||
defBackend := a.r.GetDefaultBackend()
|
||||
sort.Strings(defBackend.WhitelistSourceRange)
|
||||
|
||||
val, err := parser.GetStringAnnotation(whitelist, ing)
|
||||
val, err := parser.GetStringAnnotation("whitelist-source-range", ing, a.r)
|
||||
// A missing annotation is not a problem, just use the default
|
||||
if err == ing_errors.ErrMissingAnnotations {
|
||||
return &SourceRange{CIDR: defBackend.WhitelistSourceRange}, nil
|
||||
|
|
|
@ -23,8 +23,8 @@ import (
|
|||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/defaults"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func buildIngress() *extensions.Ingress {
|
||||
|
@ -62,14 +62,6 @@ func buildIngress() *extensions.Ingress {
|
|||
}
|
||||
}
|
||||
|
||||
type mockBackend struct {
|
||||
defaults.Backend
|
||||
}
|
||||
|
||||
func (m mockBackend) GetDefaultBackend() defaults.Backend {
|
||||
return m.Backend
|
||||
}
|
||||
|
||||
func TestParseAnnotations(t *testing.T) {
|
||||
ing := buildIngress()
|
||||
tests := map[string]struct {
|
||||
|
@ -102,9 +94,9 @@ func TestParseAnnotations(t *testing.T) {
|
|||
|
||||
for testName, test := range tests {
|
||||
data := map[string]string{}
|
||||
data[whitelist] = test.net
|
||||
data["nginx/whitelist-source-range"] = test.net
|
||||
ing.SetAnnotations(data)
|
||||
p := NewParser(mockBackend{})
|
||||
p := NewParser(&resolver.Mock{})
|
||||
i, err := p.Parse(ing)
|
||||
if err != nil && !test.expectErr {
|
||||
t.Errorf("%v:unexpected error: %v", testName, err)
|
||||
|
@ -126,12 +118,24 @@ func TestParseAnnotations(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
type mockBackend struct {
|
||||
resolver.Mock
|
||||
}
|
||||
|
||||
// GetDefaultBackend returns the backend that must be used as default
|
||||
func (m mockBackend) GetDefaultBackend() defaults.Backend {
|
||||
return defaults.Backend{
|
||||
WhitelistSourceRange: []string{"4.4.4.0/24", "1.2.3.4/32"},
|
||||
}
|
||||
}
|
||||
|
||||
// Test that when we have a whitelist set on the Backend that is used when we
|
||||
// don't have the annotation
|
||||
func TestParseAnnotationsWithDefaultConfig(t *testing.T) {
|
||||
ing := buildIngress()
|
||||
|
||||
mockBackend := mockBackend{}
|
||||
mockBackend.Backend.WhitelistSourceRange = []string{"4.4.4.0/24", "1.2.3.4/32"}
|
||||
|
||||
tests := map[string]struct {
|
||||
net string
|
||||
expectCidr []string
|
||||
|
@ -162,7 +166,7 @@ func TestParseAnnotationsWithDefaultConfig(t *testing.T) {
|
|||
|
||||
for testName, test := range tests {
|
||||
data := map[string]string{}
|
||||
data[whitelist] = test.net
|
||||
data["nginx/whitelist-source-range"] = test.net
|
||||
ing.SetAnnotations(data)
|
||||
p := NewParser(mockBackend)
|
||||
i, err := p.Parse(ing)
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/errors"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
// IngressAnnotation has a method to parse annotations located in Ingress
|
||||
|
@ -75,28 +76,31 @@ func checkAnnotation(name string, ing *extensions.Ingress) error {
|
|||
}
|
||||
|
||||
// GetBoolAnnotation extracts a boolean from an Ingress annotation
|
||||
func GetBoolAnnotation(name string, ing *extensions.Ingress) (bool, error) {
|
||||
err := checkAnnotation(name, ing)
|
||||
func GetBoolAnnotation(name string, ing *extensions.Ingress, r resolver.Resolver) (bool, error) {
|
||||
v := r.GetAnnotationWithPrefix(name)
|
||||
err := checkAnnotation(v, ing)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return ingAnnotations(ing.GetAnnotations()).parseBool(name)
|
||||
return ingAnnotations(ing.GetAnnotations()).parseBool(v)
|
||||
}
|
||||
|
||||
// GetStringAnnotation extracts a string from an Ingress annotation
|
||||
func GetStringAnnotation(name string, ing *extensions.Ingress) (string, error) {
|
||||
err := checkAnnotation(name, ing)
|
||||
func GetStringAnnotation(name string, ing *extensions.Ingress, r resolver.Resolver) (string, error) {
|
||||
v := r.GetAnnotationWithPrefix(name)
|
||||
err := checkAnnotation(v, ing)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ingAnnotations(ing.GetAnnotations()).parseString(name)
|
||||
return ingAnnotations(ing.GetAnnotations()).parseString(v)
|
||||
}
|
||||
|
||||
// GetIntAnnotation extracts an int from an Ingress annotation
|
||||
func GetIntAnnotation(name string, ing *extensions.Ingress) (int, error) {
|
||||
err := checkAnnotation(name, ing)
|
||||
func GetIntAnnotation(name string, ing *extensions.Ingress, r resolver.Resolver) (int, error) {
|
||||
v := r.GetAnnotationWithPrefix(name)
|
||||
err := checkAnnotation(v, ing)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return ingAnnotations(ing.GetAnnotations()).parseInt(name)
|
||||
return ingAnnotations(ing.GetAnnotations()).parseInt(v)
|
||||
}
|
||||
|
|
|
@ -17,11 +17,13 @@ limitations under the License.
|
|||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
api "k8s.io/api/core/v1"
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func buildIngress() *extensions.Ingress {
|
||||
|
@ -35,9 +37,11 @@ func buildIngress() *extensions.Ingress {
|
|||
}
|
||||
|
||||
func TestGetBoolAnnotation(t *testing.T) {
|
||||
r := &resolver.Mock{}
|
||||
|
||||
ing := buildIngress()
|
||||
|
||||
_, err := GetBoolAnnotation("", nil)
|
||||
_, err := GetBoolAnnotation("", nil, r)
|
||||
if err == nil {
|
||||
t.Errorf("expected error but retuned nil")
|
||||
}
|
||||
|
@ -49,8 +53,6 @@ func TestGetBoolAnnotation(t *testing.T) {
|
|||
exp bool
|
||||
expErr bool
|
||||
}{
|
||||
{"empty - false", "", "false", false, true},
|
||||
{"empty - true", "", "true", false, true},
|
||||
{"valid - false", "bool", "false", false, false},
|
||||
{"valid - true", "bool", "true", true, false},
|
||||
}
|
||||
|
@ -59,9 +61,9 @@ func TestGetBoolAnnotation(t *testing.T) {
|
|||
ing.SetAnnotations(data)
|
||||
|
||||
for _, test := range tests {
|
||||
data[test.field] = test.value
|
||||
data[fmt.Sprintf("nginx/%v", test.field)] = test.value
|
||||
|
||||
u, err := GetBoolAnnotation(test.field, ing)
|
||||
u, err := GetBoolAnnotation(test.field, ing, r)
|
||||
if test.expErr {
|
||||
if err == nil {
|
||||
t.Errorf("%v: expected error but retuned nil", test.name)
|
||||
|
@ -77,9 +79,11 @@ func TestGetBoolAnnotation(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetStringAnnotation(t *testing.T) {
|
||||
r := &resolver.Mock{}
|
||||
|
||||
ing := buildIngress()
|
||||
|
||||
_, err := GetStringAnnotation("", nil)
|
||||
_, err := GetStringAnnotation("", nil, r)
|
||||
if err == nil {
|
||||
t.Errorf("expected error but retuned nil")
|
||||
}
|
||||
|
@ -91,8 +95,6 @@ func TestGetStringAnnotation(t *testing.T) {
|
|||
exp string
|
||||
expErr bool
|
||||
}{
|
||||
{"empty - A", "", "A", "", true},
|
||||
{"empty - B", "", "B", "", true},
|
||||
{"valid - A", "string", "A", "A", false},
|
||||
{"valid - B", "string", "B", "B", false},
|
||||
}
|
||||
|
@ -101,9 +103,9 @@ func TestGetStringAnnotation(t *testing.T) {
|
|||
ing.SetAnnotations(data)
|
||||
|
||||
for _, test := range tests {
|
||||
data[test.field] = test.value
|
||||
data[fmt.Sprintf("nginx/%v", test.field)] = test.value
|
||||
|
||||
s, err := GetStringAnnotation(test.field, ing)
|
||||
s, err := GetStringAnnotation(test.field, ing, r)
|
||||
if test.expErr {
|
||||
if err == nil {
|
||||
t.Errorf("%v: expected error but retuned nil", test.name)
|
||||
|
@ -119,9 +121,11 @@ func TestGetStringAnnotation(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetIntAnnotation(t *testing.T) {
|
||||
r := &resolver.Mock{}
|
||||
|
||||
ing := buildIngress()
|
||||
|
||||
_, err := GetIntAnnotation("", nil)
|
||||
_, err := GetIntAnnotation("", nil, r)
|
||||
if err == nil {
|
||||
t.Errorf("expected error but retuned nil")
|
||||
}
|
||||
|
@ -133,8 +137,6 @@ func TestGetIntAnnotation(t *testing.T) {
|
|||
exp int
|
||||
expErr bool
|
||||
}{
|
||||
{"empty - A", "", "1", 0, true},
|
||||
{"empty - B", "", "2", 0, true},
|
||||
{"valid - A", "string", "1", 1, false},
|
||||
{"valid - B", "string", "2", 2, false},
|
||||
}
|
||||
|
@ -143,9 +145,9 @@ func TestGetIntAnnotation(t *testing.T) {
|
|||
ing.SetAnnotations(data)
|
||||
|
||||
for _, test := range tests {
|
||||
data[test.field] = test.value
|
||||
data[fmt.Sprintf("nginx/%v", test.field)] = test.value
|
||||
|
||||
s, err := GetIntAnnotation(test.field, ing)
|
||||
s, err := GetIntAnnotation(test.field, ing, r)
|
||||
if test.expErr {
|
||||
if err == nil {
|
||||
t.Errorf("%v: expected error but retuned nil", test.name)
|
||||
|
|
|
@ -23,25 +23,21 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
const (
|
||||
annotation = "ingress.kubernetes.io/use-port-in-redirects"
|
||||
)
|
||||
|
||||
type portInRedirect struct {
|
||||
backendResolver resolver.DefaultBackend
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new port in redirect annotation parser
|
||||
func NewParser(db resolver.DefaultBackend) parser.IngressAnnotation {
|
||||
return portInRedirect{db}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return portInRedirect{r}
|
||||
}
|
||||
|
||||
// Parse parses the annotations contained in the ingress
|
||||
// rule used to indicate if the redirects must
|
||||
func (a portInRedirect) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
up, err := parser.GetBoolAnnotation(annotation, ing)
|
||||
up, err := parser.GetBoolAnnotation("use-port-in-redirects", ing, a.r)
|
||||
if err != nil {
|
||||
return a.backendResolver.GetDefaultBackend().UsePortInRedirects, nil
|
||||
return a.r.GetDefaultBackend().UsePortInRedirects, nil
|
||||
}
|
||||
|
||||
return up, nil
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/defaults"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func buildIngress() *extensions.Ingress {
|
||||
|
@ -64,6 +65,7 @@ func buildIngress() *extensions.Ingress {
|
|||
}
|
||||
|
||||
type mockBackend struct {
|
||||
resolver.Mock
|
||||
usePortInRedirects bool
|
||||
}
|
||||
|
||||
|
@ -90,11 +92,11 @@ func TestPortInRedirect(t *testing.T) {
|
|||
|
||||
data := map[string]string{}
|
||||
if test.usePort != nil {
|
||||
data[annotation] = fmt.Sprintf("%v", *test.usePort)
|
||||
data["nginx/use-port-in-redirects"] = fmt.Sprintf("%v", *test.usePort)
|
||||
}
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, err := NewParser(mockBackend{test.def}).Parse(ing)
|
||||
i, err := NewParser(mockBackend{usePortInRedirects: test.def}).Parse(ing)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error parsing a valid")
|
||||
}
|
||||
|
|
|
@ -23,19 +23,6 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
const (
|
||||
bodySize = "ingress.kubernetes.io/proxy-body-size"
|
||||
connect = "ingress.kubernetes.io/proxy-connect-timeout"
|
||||
send = "ingress.kubernetes.io/proxy-send-timeout"
|
||||
read = "ingress.kubernetes.io/proxy-read-timeout"
|
||||
bufferSize = "ingress.kubernetes.io/proxy-buffer-size"
|
||||
cookiePath = "ingress.kubernetes.io/proxy-cookie-path"
|
||||
cookieDomain = "ingress.kubernetes.io/proxy-cookie-domain"
|
||||
nextUpstream = "ingress.kubernetes.io/proxy-next-upstream"
|
||||
passParams = "ingress.kubernetes.io/proxy-pass-params"
|
||||
requestBuffering = "ingress.kubernetes.io/proxy-request-buffering"
|
||||
)
|
||||
|
||||
// Config returns the proxy timeout to use in the upstream server/s
|
||||
type Config struct {
|
||||
BodySize string `json:"bodySize"`
|
||||
|
@ -94,64 +81,64 @@ func (l1 *Config) Equal(l2 *Config) bool {
|
|||
}
|
||||
|
||||
type proxy struct {
|
||||
backendResolver resolver.DefaultBackend
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new reverse proxy configuration annotation parser
|
||||
func NewParser(br resolver.DefaultBackend) parser.IngressAnnotation {
|
||||
return proxy{br}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return proxy{r}
|
||||
}
|
||||
|
||||
// ParseAnnotations parses the annotations contained in the ingress
|
||||
// rule used to configure upstream check parameters
|
||||
func (a proxy) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
defBackend := a.backendResolver.GetDefaultBackend()
|
||||
ct, err := parser.GetIntAnnotation(connect, ing)
|
||||
defBackend := a.r.GetDefaultBackend()
|
||||
ct, err := parser.GetIntAnnotation("proxy-connect-timeout", ing, a.r)
|
||||
if err != nil {
|
||||
ct = defBackend.ProxyConnectTimeout
|
||||
}
|
||||
|
||||
st, err := parser.GetIntAnnotation(send, ing)
|
||||
st, err := parser.GetIntAnnotation("proxy-send-timeout", ing, a.r)
|
||||
if err != nil {
|
||||
st = defBackend.ProxySendTimeout
|
||||
}
|
||||
|
||||
rt, err := parser.GetIntAnnotation(read, ing)
|
||||
rt, err := parser.GetIntAnnotation("proxy-read-timeout", ing, a.r)
|
||||
if err != nil {
|
||||
rt = defBackend.ProxyReadTimeout
|
||||
}
|
||||
|
||||
bufs, err := parser.GetStringAnnotation(bufferSize, ing)
|
||||
bufs, err := parser.GetStringAnnotation("proxy-buffer-size", ing, a.r)
|
||||
if err != nil || bufs == "" {
|
||||
bufs = defBackend.ProxyBufferSize
|
||||
}
|
||||
|
||||
cp, err := parser.GetStringAnnotation(cookiePath, ing)
|
||||
cp, err := parser.GetStringAnnotation("proxy-cookie-path", ing, a.r)
|
||||
if err != nil || cp == "" {
|
||||
cp = defBackend.ProxyCookiePath
|
||||
}
|
||||
|
||||
cd, err := parser.GetStringAnnotation(cookieDomain, ing)
|
||||
cd, err := parser.GetStringAnnotation("proxy-cookie-domain", ing, a.r)
|
||||
if err != nil || cd == "" {
|
||||
cd = defBackend.ProxyCookieDomain
|
||||
}
|
||||
|
||||
bs, err := parser.GetStringAnnotation(bodySize, ing)
|
||||
bs, err := parser.GetStringAnnotation("proxy-body-size", ing, a.r)
|
||||
if err != nil || bs == "" {
|
||||
bs = defBackend.ProxyBodySize
|
||||
}
|
||||
|
||||
nu, err := parser.GetStringAnnotation(nextUpstream, ing)
|
||||
nu, err := parser.GetStringAnnotation("proxy-next-upstream", ing, a.r)
|
||||
if err != nil || nu == "" {
|
||||
nu = defBackend.ProxyNextUpstream
|
||||
}
|
||||
|
||||
pp, err := parser.GetStringAnnotation(passParams, ing)
|
||||
pp, err := parser.GetStringAnnotation("proxy-pass-params", ing, a.r)
|
||||
if err != nil || pp == "" {
|
||||
pp = defBackend.ProxyPassParams
|
||||
}
|
||||
|
||||
rb, err := parser.GetStringAnnotation(requestBuffering, ing)
|
||||
rb, err := parser.GetStringAnnotation("proxy-request-buffering", ing, a.r)
|
||||
if err != nil || rb == "" {
|
||||
rb = defBackend.ProxyRequestBuffering
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/defaults"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func buildIngress() *extensions.Ingress {
|
||||
|
@ -63,6 +64,7 @@ func buildIngress() *extensions.Ingress {
|
|||
}
|
||||
|
||||
type mockBackend struct {
|
||||
resolver.Mock
|
||||
}
|
||||
|
||||
func (m mockBackend) GetDefaultBackend() defaults.Backend {
|
||||
|
@ -83,14 +85,14 @@ func TestProxy(t *testing.T) {
|
|||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[connect] = "1"
|
||||
data[send] = "2"
|
||||
data[read] = "3"
|
||||
data[bufferSize] = "1k"
|
||||
data[bodySize] = "2k"
|
||||
data[nextUpstream] = "off"
|
||||
data[passParams] = "smax=5 max=10"
|
||||
data[requestBuffering] = "off"
|
||||
data["nginx/proxy-connect-timeout"] = "1"
|
||||
data["nginx/proxy-send-timeout"] = "2"
|
||||
data["nginx/proxy-read-timeout"] = "3"
|
||||
data["nginx/proxy-buffer-size"] = "1k"
|
||||
data["nginx/proxy-body-size"] = "2k"
|
||||
data["nginx/proxy-next-upstream"] = "off"
|
||||
data["nginx/proxy-pass-params"] = "smax=5 max=10"
|
||||
data["nginx/proxy-request-buffering"] = "off"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, err := NewParser(mockBackend{}).Parse(ing)
|
||||
|
|
|
@ -30,13 +30,6 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
limitIP = "ingress.kubernetes.io/limit-connections"
|
||||
limitRPS = "ingress.kubernetes.io/limit-rps"
|
||||
limitRPM = "ingress.kubernetes.io/limit-rpm"
|
||||
limitRATE = "ingress.kubernetes.io/limit-rate"
|
||||
limitRATEAFTER = "ingress.kubernetes.io/limit-rate-after"
|
||||
limitWhitelist = "ingress.kubernetes.io/limit-whitelist"
|
||||
|
||||
// allow 5 times the specified limit as burst
|
||||
defBurst = 5
|
||||
|
||||
|
@ -152,32 +145,32 @@ func (z1 *Zone) Equal(z2 *Zone) bool {
|
|||
}
|
||||
|
||||
type ratelimit struct {
|
||||
backendResolver resolver.DefaultBackend
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new ratelimit annotation parser
|
||||
func NewParser(br resolver.DefaultBackend) parser.IngressAnnotation {
|
||||
return ratelimit{br}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return ratelimit{r}
|
||||
}
|
||||
|
||||
// ParseAnnotations parses the annotations contained in the ingress
|
||||
// rule used to rewrite the defined paths
|
||||
func (a ratelimit) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
defBackend := a.backendResolver.GetDefaultBackend()
|
||||
lr, err := parser.GetIntAnnotation(limitRATE, ing)
|
||||
defBackend := a.r.GetDefaultBackend()
|
||||
lr, err := parser.GetIntAnnotation("limit-rate", ing, a.r)
|
||||
if err != nil {
|
||||
lr = defBackend.LimitRate
|
||||
}
|
||||
lra, err := parser.GetIntAnnotation(limitRATEAFTER, ing)
|
||||
lra, err := parser.GetIntAnnotation("limit-rate-after", ing, a.r)
|
||||
if err != nil {
|
||||
lra = defBackend.LimitRateAfter
|
||||
}
|
||||
|
||||
rpm, _ := parser.GetIntAnnotation(limitRPM, ing)
|
||||
rps, _ := parser.GetIntAnnotation(limitRPS, ing)
|
||||
conn, _ := parser.GetIntAnnotation(limitIP, ing)
|
||||
rpm, _ := parser.GetIntAnnotation("limit-rpm", ing, a.r)
|
||||
rps, _ := parser.GetIntAnnotation("limit-rps", ing, a.r)
|
||||
conn, _ := parser.GetIntAnnotation("limit-connections", ing, a.r)
|
||||
|
||||
val, _ := parser.GetStringAnnotation(limitWhitelist, ing)
|
||||
val, _ := parser.GetStringAnnotation("limit-whitelist", ing, a.r)
|
||||
|
||||
cidrs, err := parseCIDRs(val)
|
||||
if err != nil {
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/ingress-nginx/internal/ingress/defaults"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func buildIngress() *extensions.Ingress {
|
||||
|
@ -63,6 +64,7 @@ func buildIngress() *extensions.Ingress {
|
|||
}
|
||||
|
||||
type mockBackend struct {
|
||||
resolver.Mock
|
||||
}
|
||||
|
||||
func (m mockBackend) GetDefaultBackend() defaults.Backend {
|
||||
|
@ -84,9 +86,9 @@ func TestBadRateLimiting(t *testing.T) {
|
|||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[limitIP] = "0"
|
||||
data[limitRPS] = "0"
|
||||
data[limitRPM] = "0"
|
||||
data["nginx/limit-connections"] = "0"
|
||||
data["nginx/limit-rps"] = "0"
|
||||
data["nginx/limit-rpm"] = "0"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
_, err := NewParser(mockBackend{}).Parse(ing)
|
||||
|
@ -95,11 +97,11 @@ func TestBadRateLimiting(t *testing.T) {
|
|||
}
|
||||
|
||||
data = map[string]string{}
|
||||
data[limitIP] = "5"
|
||||
data[limitRPS] = "100"
|
||||
data[limitRPM] = "10"
|
||||
data[limitRATEAFTER] = "100"
|
||||
data[limitRATE] = "10"
|
||||
data["nginx/limit-connections"] = "5"
|
||||
data["nginx/limit-rps"] = "100"
|
||||
data["nginx/limit-rpm"] = "10"
|
||||
data["nginx/limit-rate-after"] = "100"
|
||||
data["nginx/limit-rate"] = "10"
|
||||
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
|
|
|
@ -25,12 +25,7 @@ import (
|
|||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
"k8s.io/ingress-nginx/internal/ingress/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
permanent = "ingress.kubernetes.io/permanent-redirect"
|
||||
temporal = "ingress.kubernetes.io/temporal-redirect"
|
||||
www = "ingress.kubernetes.io/from-to-www-redirect"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
// Config returns the redirect configuration for an Ingress rule
|
||||
|
@ -40,11 +35,13 @@ type Config struct {
|
|||
FromToWWW bool `json:"fromToWWW"`
|
||||
}
|
||||
|
||||
type redirect struct{}
|
||||
type redirect struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new redirect annotation parser
|
||||
func NewParser() parser.IngressAnnotation {
|
||||
return redirect{}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return redirect{r}
|
||||
}
|
||||
|
||||
// Parse parses the annotations contained in the ingress
|
||||
|
@ -52,9 +49,9 @@ func NewParser() parser.IngressAnnotation {
|
|||
// If the Ingress contains both annotations the execution order is
|
||||
// temporal and then permanent
|
||||
func (a redirect) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
r3w, _ := parser.GetBoolAnnotation(www, ing)
|
||||
r3w, _ := parser.GetBoolAnnotation("from-to-www-redirect", ing, a.r)
|
||||
|
||||
tr, err := parser.GetStringAnnotation(temporal, ing)
|
||||
tr, err := parser.GetStringAnnotation("temporal-redirect", ing, a.r)
|
||||
if err != nil && !errors.IsMissingAnnotations(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -71,7 +68,7 @@ func (a redirect) Parse(ing *extensions.Ingress) (interface{}, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
pr, err := parser.GetStringAnnotation(permanent, ing)
|
||||
pr, err := parser.GetStringAnnotation("permanent-redirect", ing, a.r)
|
||||
if err != nil && !errors.IsMissingAnnotations(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -23,15 +23,6 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
const (
|
||||
rewriteTo = "ingress.kubernetes.io/rewrite-target"
|
||||
addBaseURL = "ingress.kubernetes.io/add-base-url"
|
||||
baseURLScheme = "ingress.kubernetes.io/base-url-scheme"
|
||||
sslRedirect = "ingress.kubernetes.io/ssl-redirect"
|
||||
forceSSLRedirect = "ingress.kubernetes.io/force-ssl-redirect"
|
||||
appRoot = "ingress.kubernetes.io/app-root"
|
||||
)
|
||||
|
||||
// Config describes the per location redirect config
|
||||
type Config struct {
|
||||
// Target URI where the traffic must be redirected
|
||||
|
@ -80,29 +71,30 @@ func (r1 *Config) Equal(r2 *Config) bool {
|
|||
}
|
||||
|
||||
type rewrite struct {
|
||||
backendResolver resolver.DefaultBackend
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new reqrite annotation parser
|
||||
func NewParser(br resolver.DefaultBackend) parser.IngressAnnotation {
|
||||
return rewrite{br}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return rewrite{r}
|
||||
}
|
||||
|
||||
// ParseAnnotations parses the annotations contained in the ingress
|
||||
// rule used to rewrite the defined paths
|
||||
func (a rewrite) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
rt, _ := parser.GetStringAnnotation(rewriteTo, ing)
|
||||
sslRe, err := parser.GetBoolAnnotation(sslRedirect, ing)
|
||||
rt, _ := parser.GetStringAnnotation("rewrite-target", ing, a.r)
|
||||
sslRe, err := parser.GetBoolAnnotation("ssl-redirect", ing, a.r)
|
||||
if err != nil {
|
||||
sslRe = a.backendResolver.GetDefaultBackend().SSLRedirect
|
||||
sslRe = a.r.GetDefaultBackend().SSLRedirect
|
||||
}
|
||||
fSslRe, err := parser.GetBoolAnnotation(forceSSLRedirect, ing)
|
||||
fSslRe, err := parser.GetBoolAnnotation("force-ssl-redirect", ing, a.r)
|
||||
if err != nil {
|
||||
fSslRe = a.backendResolver.GetDefaultBackend().ForceSSLRedirect
|
||||
fSslRe = a.r.GetDefaultBackend().ForceSSLRedirect
|
||||
}
|
||||
abu, _ := parser.GetBoolAnnotation(addBaseURL, ing)
|
||||
bus, _ := parser.GetStringAnnotation(baseURLScheme, ing)
|
||||
ar, _ := parser.GetStringAnnotation(appRoot, ing)
|
||||
abu, _ := parser.GetBoolAnnotation("add-base-url", ing, a.r)
|
||||
bus, _ := parser.GetStringAnnotation("base-url-scheme", ing, a.r)
|
||||
ar, _ := parser.GetStringAnnotation("app-root", ing, a.r)
|
||||
|
||||
return &Config{
|
||||
Target: rt,
|
||||
AddBaseURL: abu,
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/defaults"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -67,6 +68,7 @@ func buildIngress() *extensions.Ingress {
|
|||
}
|
||||
|
||||
type mockBackend struct {
|
||||
resolver.Mock
|
||||
redirect bool
|
||||
}
|
||||
|
||||
|
@ -86,7 +88,7 @@ func TestRedirect(t *testing.T) {
|
|||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[rewriteTo] = defRoute
|
||||
data["nginx/rewrite-target"] = defRoute
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, err := NewParser(mockBackend{}).Parse(ing)
|
||||
|
@ -106,10 +108,10 @@ func TestSSLRedirect(t *testing.T) {
|
|||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[rewriteTo] = defRoute
|
||||
data["nginx/rewrite-target"] = defRoute
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, _ := NewParser(mockBackend{true}).Parse(ing)
|
||||
i, _ := NewParser(mockBackend{redirect: true}).Parse(ing)
|
||||
redirect, ok := i.(*Config)
|
||||
if !ok {
|
||||
t.Errorf("expected a Redirect type")
|
||||
|
@ -118,10 +120,10 @@ func TestSSLRedirect(t *testing.T) {
|
|||
t.Errorf("Expected true but returned false")
|
||||
}
|
||||
|
||||
data[sslRedirect] = "false"
|
||||
data["nginx/ssl-redirect"] = "false"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, _ = NewParser(mockBackend{false}).Parse(ing)
|
||||
i, _ = NewParser(mockBackend{redirect: false}).Parse(ing)
|
||||
redirect, ok = i.(*Config)
|
||||
if !ok {
|
||||
t.Errorf("expected a Redirect type")
|
||||
|
@ -135,10 +137,10 @@ func TestForceSSLRedirect(t *testing.T) {
|
|||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[rewriteTo] = defRoute
|
||||
data["nginx/rewrite-target"] = defRoute
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, _ := NewParser(mockBackend{true}).Parse(ing)
|
||||
i, _ := NewParser(mockBackend{redirect: true}).Parse(ing)
|
||||
redirect, ok := i.(*Config)
|
||||
if !ok {
|
||||
t.Errorf("expected a Redirect type")
|
||||
|
@ -147,10 +149,10 @@ func TestForceSSLRedirect(t *testing.T) {
|
|||
t.Errorf("Expected false but returned true")
|
||||
}
|
||||
|
||||
data[forceSSLRedirect] = "true"
|
||||
data["nginx/force-ssl-redirect"] = "true"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, _ = NewParser(mockBackend{false}).Parse(ing)
|
||||
i, _ = NewParser(mockBackend{redirect: false}).Parse(ing)
|
||||
redirect, ok = i.(*Config)
|
||||
if !ok {
|
||||
t.Errorf("expected a Redirect type")
|
||||
|
@ -163,10 +165,10 @@ func TestAppRoot(t *testing.T) {
|
|||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[appRoot] = "/app1"
|
||||
data["nginx/app-root"] = "/app1"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
i, _ := NewParser(mockBackend{true}).Parse(ing)
|
||||
i, _ := NewParser(mockBackend{redirect: true}).Parse(ing)
|
||||
redirect, ok := i.(*Config)
|
||||
if !ok {
|
||||
t.Errorf("expected a App Context")
|
||||
|
|
|
@ -26,11 +26,6 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
const (
|
||||
secureUpstream = "ingress.kubernetes.io/secure-backends"
|
||||
secureVerifyCASecret = "ingress.kubernetes.io/secure-verify-ca-secret"
|
||||
)
|
||||
|
||||
// Config describes SSL backend configuration
|
||||
type Config struct {
|
||||
Secure bool `json:"secure"`
|
||||
|
@ -38,21 +33,19 @@ type Config struct {
|
|||
}
|
||||
|
||||
type su struct {
|
||||
certResolver resolver.AuthCertificate
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new secure upstream annotation parser
|
||||
func NewParser(resolver resolver.AuthCertificate) parser.IngressAnnotation {
|
||||
return su{
|
||||
certResolver: resolver,
|
||||
}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return su{r}
|
||||
}
|
||||
|
||||
// Parse parses the annotations contained in the ingress
|
||||
// rule used to indicate if the upstream servers should use SSL
|
||||
func (a su) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
s, _ := parser.GetBoolAnnotation(secureUpstream, ing)
|
||||
ca, _ := parser.GetStringAnnotation(secureVerifyCASecret, ing)
|
||||
s, _ := parser.GetBoolAnnotation("secure-backends", ing, a.r)
|
||||
ca, _ := parser.GetStringAnnotation("secure-verify-ca-secret", ing, a.r)
|
||||
secure := &Config{
|
||||
Secure: s,
|
||||
CACert: resolver.AuthSSLCert{},
|
||||
|
@ -64,7 +57,7 @@ func (a su) Parse(ing *extensions.Ingress) (interface{}, error) {
|
|||
if ca == "" {
|
||||
return secure, nil
|
||||
}
|
||||
caCert, err := a.certResolver.GetAuthCertificate(fmt.Sprintf("%v/%v", ing.Namespace, ca))
|
||||
caCert, err := a.r.GetAuthCertificate(fmt.Sprintf("%v/%v", ing.Namespace, ca))
|
||||
if err != nil {
|
||||
return secure, errors.Wrap(err, "error obtaining certificate")
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ func buildIngress() *extensions.Ingress {
|
|||
}
|
||||
|
||||
type mockCfg struct {
|
||||
resolver.Mock
|
||||
certs map[string]resolver.AuthSSLCert
|
||||
}
|
||||
|
||||
|
@ -77,8 +78,8 @@ func (cfg mockCfg) GetAuthCertificate(secret string) (*resolver.AuthSSLCert, err
|
|||
func TestAnnotations(t *testing.T) {
|
||||
ing := buildIngress()
|
||||
data := map[string]string{}
|
||||
data[secureUpstream] = "true"
|
||||
data[secureVerifyCASecret] = "secure-verify-ca"
|
||||
data["nginx/secure-backends"] = "true"
|
||||
data["nginx/secure-verify-ca-secret"] = "secure-verify-ca"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
_, err := NewParser(mockCfg{
|
||||
|
@ -94,8 +95,8 @@ func TestAnnotations(t *testing.T) {
|
|||
func TestSecretNotFound(t *testing.T) {
|
||||
ing := buildIngress()
|
||||
data := map[string]string{}
|
||||
data[secureUpstream] = "true"
|
||||
data[secureVerifyCASecret] = "secure-verify-ca"
|
||||
data["nginx/secure-backends"] = "true"
|
||||
data["nginx/secure-verify-ca-secret"] = "secure-verify-ca"
|
||||
ing.SetAnnotations(data)
|
||||
_, err := NewParser(mockCfg{}).Parse(ing)
|
||||
if err == nil {
|
||||
|
@ -106,8 +107,8 @@ func TestSecretNotFound(t *testing.T) {
|
|||
func TestSecretOnNonSecure(t *testing.T) {
|
||||
ing := buildIngress()
|
||||
data := map[string]string{}
|
||||
data[secureUpstream] = "false"
|
||||
data[secureVerifyCASecret] = "secure-verify-ca"
|
||||
data["nginx/secure-backends"] = "false"
|
||||
data["nginx/secure-verify-ca-secret"] = "secure-verify-ca"
|
||||
ing.SetAnnotations(data)
|
||||
_, err := NewParser(mockCfg{
|
||||
certs: map[string]resolver.AuthSSLCert{
|
||||
|
|
|
@ -20,23 +20,21 @@ import (
|
|||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
)
|
||||
|
||||
const (
|
||||
annotation = "ingress.kubernetes.io/server-snippet"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
type serverSnippet struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new server snippet annotation parser
|
||||
func NewParser() parser.IngressAnnotation {
|
||||
return serverSnippet{}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return serverSnippet{r}
|
||||
}
|
||||
|
||||
// Parse parses the annotations contained in the ingress rule
|
||||
// used to indicate if the location/s contains a fragment of
|
||||
// configuration to be included inside the paths of the rules
|
||||
func (a serverSnippet) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
return parser.GetStringAnnotation(annotation, ing)
|
||||
return parser.GetStringAnnotation("server-snippet", ing, a.r)
|
||||
}
|
||||
|
|
|
@ -22,10 +22,13 @@ import (
|
|||
api "k8s.io/api/core/v1"
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
ap := NewParser()
|
||||
annotation := "nginx/server-snippet"
|
||||
|
||||
ap := NewParser(&resolver.Mock{})
|
||||
if ap == nil {
|
||||
t.Fatalf("expected a parser.IngressAnnotation but returned nil")
|
||||
}
|
||||
|
|
|
@ -18,21 +18,20 @@ package serviceupstream
|
|||
|
||||
import (
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
)
|
||||
|
||||
const (
|
||||
annotationServiceUpstream = "ingress.kubernetes.io/service-upstream"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
type serviceUpstream struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new serviceUpstream annotation parser
|
||||
func NewParser() parser.IngressAnnotation {
|
||||
return serviceUpstream{}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return serviceUpstream{r}
|
||||
}
|
||||
|
||||
func (s serviceUpstream) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
return parser.GetBoolAnnotation(annotationServiceUpstream, ing)
|
||||
return parser.GetBoolAnnotation("service-upstream", ing, s.r)
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func buildIngress() *extensions.Ingress {
|
||||
|
@ -64,10 +65,10 @@ func TestIngressAnnotationServiceUpstreamEnabled(t *testing.T) {
|
|||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[annotationServiceUpstream] = "true"
|
||||
data["nginx/service-upstream"] = "true"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
val, _ := NewParser().Parse(ing)
|
||||
val, _ := NewParser(&resolver.Mock{}).Parse(ing)
|
||||
enabled, ok := val.(bool)
|
||||
if !ok {
|
||||
t.Errorf("expected a bool type")
|
||||
|
@ -83,10 +84,10 @@ func TestIngressAnnotationServiceUpstreamSetFalse(t *testing.T) {
|
|||
|
||||
// Test with explicitly set to false
|
||||
data := map[string]string{}
|
||||
data[annotationServiceUpstream] = "false"
|
||||
data["nginx/service-upstream"] = "false"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
val, _ := NewParser().Parse(ing)
|
||||
val, _ := NewParser(&resolver.Mock{}).Parse(ing)
|
||||
enabled, ok := val.(bool)
|
||||
if !ok {
|
||||
t.Errorf("expected a bool type")
|
||||
|
@ -100,7 +101,7 @@ func TestIngressAnnotationServiceUpstreamSetFalse(t *testing.T) {
|
|||
data = map[string]string{}
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
val, _ = NewParser().Parse(ing)
|
||||
val, _ = NewParser(&resolver.Mock{}).Parse(ing)
|
||||
enabled, ok = val.(bool)
|
||||
if !ok {
|
||||
t.Errorf("expected a bool type")
|
||||
|
|
|
@ -24,17 +24,20 @@ import (
|
|||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
const (
|
||||
annotationAffinityType = "ingress.kubernetes.io/affinity"
|
||||
annotationAffinityType = "affinity"
|
||||
// If a cookie with this name exists,
|
||||
// its value is used as an index into the list of available backends.
|
||||
annotationAffinityCookieName = "ingress.kubernetes.io/session-cookie-name"
|
||||
defaultAffinityCookieName = "INGRESSCOOKIE"
|
||||
annotationAffinityCookieName = "session-cookie-name"
|
||||
|
||||
defaultAffinityCookieName = "INGRESSCOOKIE"
|
||||
|
||||
// This is the algorithm used by nginx to generate a value for the session cookie, if
|
||||
// one isn't supplied and affinity is set to "cookie".
|
||||
annotationAffinityCookieHash = "ingress.kubernetes.io/session-cookie-hash"
|
||||
annotationAffinityCookieHash = "session-cookie-hash"
|
||||
defaultAffinityCookieHash = "md5"
|
||||
)
|
||||
|
||||
|
@ -59,16 +62,15 @@ type Cookie struct {
|
|||
|
||||
// cookieAffinityParse gets the annotation values related to Cookie Affinity
|
||||
// It also sets default values when no value or incorrect value is found
|
||||
func cookieAffinityParse(ing *extensions.Ingress) *Cookie {
|
||||
|
||||
sn, err := parser.GetStringAnnotation(annotationAffinityCookieName, ing)
|
||||
func (a affinity) cookieAffinityParse(ing *extensions.Ingress) *Cookie {
|
||||
sn, err := parser.GetStringAnnotation(annotationAffinityCookieName, ing, a.r)
|
||||
|
||||
if err != nil || sn == "" {
|
||||
glog.V(3).Infof("Ingress %v: No value found in annotation %v. Using the default %v", ing.Name, annotationAffinityCookieName, defaultAffinityCookieName)
|
||||
sn = defaultAffinityCookieName
|
||||
}
|
||||
|
||||
sh, err := parser.GetStringAnnotation(annotationAffinityCookieHash, ing)
|
||||
sh, err := parser.GetStringAnnotation(annotationAffinityCookieHash, ing, a.r)
|
||||
|
||||
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)
|
||||
|
@ -82,11 +84,12 @@ func cookieAffinityParse(ing *extensions.Ingress) *Cookie {
|
|||
}
|
||||
|
||||
// NewParser creates a new Affinity annotation parser
|
||||
func NewParser() parser.IngressAnnotation {
|
||||
return affinity{}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return affinity{r}
|
||||
}
|
||||
|
||||
type affinity struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// ParseAnnotations parses the annotations contained in the ingress
|
||||
|
@ -94,14 +97,14 @@ type affinity struct {
|
|||
func (a affinity) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
cookie := &Cookie{}
|
||||
// Check the type of affinity that will be used
|
||||
at, err := parser.GetStringAnnotation(annotationAffinityType, ing)
|
||||
at, err := parser.GetStringAnnotation(annotationAffinityType, ing, a.r)
|
||||
if err != nil {
|
||||
at = ""
|
||||
}
|
||||
|
||||
switch at {
|
||||
case "cookie":
|
||||
cookie = cookieAffinityParse(ing)
|
||||
cookie = a.cookieAffinityParse(ing)
|
||||
default:
|
||||
glog.V(3).Infof("No default affinity was found for Ingress %v", ing.Name)
|
||||
|
||||
|
|
|
@ -17,12 +17,14 @@ limitations under the License.
|
|||
package sessionaffinity
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
api "k8s.io/api/core/v1"
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func buildIngress() *extensions.Ingress {
|
||||
|
@ -64,12 +66,12 @@ func TestIngressAffinityCookieConfig(t *testing.T) {
|
|||
ing := buildIngress()
|
||||
|
||||
data := map[string]string{}
|
||||
data[annotationAffinityType] = "cookie"
|
||||
data[annotationAffinityCookieHash] = "sha123"
|
||||
data[annotationAffinityCookieName] = "INGRESSCOOKIE"
|
||||
data[fmt.Sprintf("nginx/%v", annotationAffinityType)] = "cookie"
|
||||
data[fmt.Sprintf("nginx/%v", annotationAffinityCookieHash)] = "sha123"
|
||||
data[fmt.Sprintf("nginx/%v", annotationAffinityCookieName)] = "INGRESSCOOKIE"
|
||||
ing.SetAnnotations(data)
|
||||
|
||||
affin, _ := NewParser().Parse(ing)
|
||||
affin, _ := NewParser(&resolver.Mock{}).Parse(ing)
|
||||
nginxAffinity, ok := affin.(*Config)
|
||||
if !ok {
|
||||
t.Errorf("expected a Config type")
|
||||
|
|
|
@ -20,23 +20,21 @@ import (
|
|||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
)
|
||||
|
||||
const (
|
||||
annotation = "ingress.kubernetes.io/configuration-snippet"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
type snippet struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new CORS annotation parser
|
||||
func NewParser() parser.IngressAnnotation {
|
||||
return snippet{}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return snippet{r}
|
||||
}
|
||||
|
||||
// Parse parses the annotations contained in the ingress rule
|
||||
// used to indicate if the location/s contains a fragment of
|
||||
// configuration to be included inside the paths of the rules
|
||||
func (a snippet) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
return parser.GetStringAnnotation(annotation, ing)
|
||||
return parser.GetStringAnnotation("configuration-snippet", ing, a.r)
|
||||
}
|
||||
|
|
|
@ -22,10 +22,13 @@ import (
|
|||
api "k8s.io/api/core/v1"
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
ap := NewParser()
|
||||
annotation := "nginx/configuration-snippet"
|
||||
|
||||
ap := NewParser(&resolver.Mock{})
|
||||
if ap == nil {
|
||||
t.Fatalf("expected a parser.IngressAnnotation but returned nil")
|
||||
}
|
||||
|
|
|
@ -21,18 +21,16 @@ import (
|
|||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
ing_errors "k8s.io/ingress-nginx/internal/ingress/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
passthrough = "ingress.kubernetes.io/ssl-passthrough"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
type sslpt struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new SSL passthrough annotation parser
|
||||
func NewParser() parser.IngressAnnotation {
|
||||
return sslpt{}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return sslpt{r}
|
||||
}
|
||||
|
||||
// ParseAnnotations parses the annotations contained in the ingress
|
||||
|
@ -42,5 +40,5 @@ func (a sslpt) Parse(ing *extensions.Ingress) (interface{}, error) {
|
|||
return false, ing_errors.ErrMissingAnnotations
|
||||
}
|
||||
|
||||
return parser.GetBoolAnnotation(passthrough, ing)
|
||||
return parser.GetBoolAnnotation("ssl-passthrough", ing, a.r)
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
api "k8s.io/api/core/v1"
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
@ -44,16 +45,16 @@ func buildIngress() *extensions.Ingress {
|
|||
func TestParseAnnotations(t *testing.T) {
|
||||
ing := buildIngress()
|
||||
|
||||
_, err := NewParser().Parse(ing)
|
||||
_, err := NewParser(&resolver.Mock{}).Parse(ing)
|
||||
if err == nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
data := map[string]string{}
|
||||
data[passthrough] = "true"
|
||||
data["nginx/ssl-passthrough"] = "true"
|
||||
ing.SetAnnotations(data)
|
||||
// test ingress using the annotation without a TLS section
|
||||
_, err = NewParser().Parse(ing)
|
||||
_, err = NewParser(&resolver.Mock{}).Parse(ing)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error parsing ingress with sslpassthrough")
|
||||
}
|
||||
|
@ -64,7 +65,7 @@ func TestParseAnnotations(t *testing.T) {
|
|||
Hosts: []string{"foo.bar.com"},
|
||||
},
|
||||
}
|
||||
i, err := NewParser().Parse(ing)
|
||||
i, err := NewParser(&resolver.Mock{}).Parse(ing)
|
||||
if err != nil {
|
||||
t.Errorf("expected error parsing ingress with sslpassthrough")
|
||||
}
|
||||
|
|
|
@ -20,23 +20,21 @@ import (
|
|||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
)
|
||||
|
||||
const (
|
||||
annotation = "ingress.kubernetes.io/upstream-hash-by"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
type upstreamhashby struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new CORS annotation parser
|
||||
func NewParser() parser.IngressAnnotation {
|
||||
return upstreamhashby{}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return upstreamhashby{r}
|
||||
}
|
||||
|
||||
// Parse parses the annotations contained in the ingress rule
|
||||
// used to indicate if the location/s contains a fragment of
|
||||
// configuration to be included inside the paths of the rules
|
||||
func (a upstreamhashby) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
return parser.GetStringAnnotation(annotation, ing)
|
||||
return parser.GetStringAnnotation("upstream-hash-by", ing, a.r)
|
||||
}
|
||||
|
|
|
@ -22,10 +22,13 @@ import (
|
|||
api "k8s.io/api/core/v1"
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
ap := NewParser()
|
||||
annotation := "nginx/upstream-hash-by"
|
||||
|
||||
ap := NewParser(&resolver.Mock{})
|
||||
if ap == nil {
|
||||
t.Fatalf("expected a parser.IngressAnnotation but returned nil")
|
||||
}
|
||||
|
|
|
@ -20,23 +20,21 @@ import (
|
|||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
)
|
||||
|
||||
const (
|
||||
annotation = "ingress.kubernetes.io/upstream-vhost"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
type upstreamVhost struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new upstream VHost annotation parser
|
||||
func NewParser() parser.IngressAnnotation {
|
||||
return upstreamVhost{}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return upstreamVhost{r}
|
||||
}
|
||||
|
||||
// Parse parses the annotations contained in the ingress rule
|
||||
// used to indicate if the location/s contains a fragment of
|
||||
// configuration to be included inside the paths of the rules
|
||||
func (a upstreamVhost) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
return parser.GetStringAnnotation(annotation, ing)
|
||||
return parser.GetStringAnnotation("upstream-vhost", ing, a.r)
|
||||
}
|
||||
|
|
|
@ -20,23 +20,21 @@ import (
|
|||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
)
|
||||
|
||||
const (
|
||||
annotation = "ingress.kubernetes.io/vts-filter-key"
|
||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||
)
|
||||
|
||||
type vtsFilterKey struct {
|
||||
r resolver.Resolver
|
||||
}
|
||||
|
||||
// NewParser creates a new vts filter key annotation parser
|
||||
func NewParser() parser.IngressAnnotation {
|
||||
return vtsFilterKey{}
|
||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||
return vtsFilterKey{r}
|
||||
}
|
||||
|
||||
// Parse parses the annotations contained in the ingress rule
|
||||
// used to indicate if the location/s contains a fragment of
|
||||
// configuration to be included inside the paths of the rules
|
||||
func (a vtsFilterKey) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||
return parser.GetStringAnnotation(annotation, ing)
|
||||
return parser.GetStringAnnotation("vts-filter-key", ing, a.r)
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ func (ic *NGINXController) getPemCertificate(secretName string) (*ingress.SSLCer
|
|||
}
|
||||
|
||||
// If 'ca.crt' is also present, it will allow this secret to be used in the
|
||||
// 'ingress.kubernetes.io/auth-tls-secret' annotation
|
||||
// 'nginx.ingress.kubernetes.io/auth-tls-secret' annotation
|
||||
s, err = ssl.AddOrUpdateCertAndKey(nsSecName, cert, key, ca)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unexpected error creating pem file: %v", err)
|
||||
|
@ -145,7 +145,7 @@ func (ic *NGINXController) checkMissingSecrets() {
|
|||
}
|
||||
}
|
||||
|
||||
key, _ := parser.GetStringAnnotation("ingress.kubernetes.io/auth-tls-secret", ing)
|
||||
key, _ := parser.GetStringAnnotation("auth-tls-secret", ing, ic)
|
||||
if key == "" {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -66,6 +66,8 @@ func init() {
|
|||
|
||||
// Configuration contains all the settings required by an Ingress controller
|
||||
type Configuration struct {
|
||||
AnnotationsPrefix string
|
||||
|
||||
APIServerHost string
|
||||
KubeConfigFile string
|
||||
Client clientset.Interface
|
||||
|
@ -133,6 +135,11 @@ func (n NGINXController) GetService(name string) (*apiv1.Service, error) {
|
|||
return n.listers.Service.GetByName(name)
|
||||
}
|
||||
|
||||
// GetAnnotationWithPrefix returns the prefix of ingress annotations
|
||||
func (n NGINXController) GetAnnotationWithPrefix(suffix string) string {
|
||||
return fmt.Sprintf("%v/%v", n.cfg.AnnotationsPrefix, suffix)
|
||||
}
|
||||
|
||||
// sync collects all the pieces required to assemble the configuration file and
|
||||
// then sends the content to the backend (OnUpdate) receiving the populated
|
||||
// template as response reloading the backend if is required.
|
||||
|
@ -1156,7 +1163,7 @@ func (n *NGINXController) readSecrets(ing *extensions.Ingress) {
|
|||
n.syncSecret(key)
|
||||
}
|
||||
|
||||
key, _ := parser.GetStringAnnotation("ingress.kubernetes.io/auth-tls-secret", ing)
|
||||
key, _ := parser.GetStringAnnotation("auth-tls-secret", ing, n)
|
||||
if key == "" {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ func (n *NGINXController) createListers(stopCh chan struct{}) (*ingress.StoreLis
|
|||
AddFunc: func(obj interface{}) {
|
||||
addIng := obj.(*extensions.Ingress)
|
||||
if !class.IsValid(addIng, n.cfg.IngressClass, defIngressClass) {
|
||||
a, _ := parser.GetStringAnnotation(class.IngressKey, addIng)
|
||||
a, _ := parser.GetStringAnnotation(class.IngressKey, addIng, n)
|
||||
glog.Infof("ignoring add for ingress %v based on annotation %v with value %v", addIng.Name, class.IngressKey, a)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -246,7 +246,7 @@ func (n *NGINXController) Start() {
|
|||
ing := obj.(*extensions.Ingress)
|
||||
|
||||
if !class.IsValid(ing, n.cfg.IngressClass, n.cfg.DefaultIngressClass) {
|
||||
a, _ := parser.GetStringAnnotation(class.IngressKey, ing)
|
||||
a, _ := parser.GetStringAnnotation(class.IngressKey, ing, n)
|
||||
glog.Infof("ignoring add for ingress %v based on annotation %v with value %v", ing.Name, class.IngressKey, a)
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -193,7 +193,7 @@ func buildResolvers(input interface{}) string {
|
|||
}
|
||||
|
||||
// buildLocation produces the location string, if the ingress has redirects
|
||||
// (specified through the ingress.kubernetes.io/rewrite-to annotation)
|
||||
// (specified through the nginx.ingress.kubernetes.io/rewrite-to annotation)
|
||||
func buildLocation(input interface{}) string {
|
||||
location, ok := input.(*ingress.Location)
|
||||
if !ok {
|
||||
|
@ -268,8 +268,8 @@ func buildLogFormatUpstream(input interface{}) string {
|
|||
}
|
||||
|
||||
// buildProxyPass produces the proxy pass string, if the ingress has redirects
|
||||
// (specified through the ingress.kubernetes.io/rewrite-to annotation)
|
||||
// If the annotation ingress.kubernetes.io/add-base-url:"true" is specified it will
|
||||
// (specified through the nginx.ingress.kubernetes.io/rewrite-to annotation)
|
||||
// If the annotation nginx.ingress.kubernetes.io/add-base-url:"true" is specified it will
|
||||
// add a base tag in the head of the response from the service
|
||||
func buildProxyPass(host string, b interface{}, loc interface{}) string {
|
||||
backends, ok := b.([]*ingress.Backend)
|
||||
|
|
|
@ -22,29 +22,24 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/ingress/defaults"
|
||||
)
|
||||
|
||||
// DefaultBackend has a method that returns the backend
|
||||
// that must be used as default
|
||||
type DefaultBackend interface {
|
||||
// Resolver is an interface that knows how to extract information from a controller
|
||||
type Resolver interface {
|
||||
// GetDefaultBackend returns the backend that must be used as default
|
||||
GetDefaultBackend() defaults.Backend
|
||||
}
|
||||
|
||||
// Secret has a method that searches for secrets contenating
|
||||
// the namespace and name using a the character /
|
||||
type Secret interface {
|
||||
// GetSecret searches for secrets contenating the namespace and name using a the character /
|
||||
GetSecret(string) (*apiv1.Secret, error)
|
||||
}
|
||||
|
||||
// AuthCertificate resolves a given secret name into an SSL certificate.
|
||||
// The secret must contain 3 keys named:
|
||||
// ca.crt: contains the certificate chain used for authentication
|
||||
type AuthCertificate interface {
|
||||
// GetAuthCertificate resolves a given secret name into an SSL certificate.
|
||||
// The secret must contain 3 keys named:
|
||||
// ca.crt: contains the certificate chain used for authentication
|
||||
GetAuthCertificate(string) (*AuthSSLCert, error)
|
||||
}
|
||||
|
||||
// Service has a method that searches for services contenating
|
||||
// the namespace and name using a the character /
|
||||
type Service interface {
|
||||
// GetService searches for services contenating the namespace and name using a the character /
|
||||
GetService(string) (*apiv1.Service, error)
|
||||
|
||||
// GetAnnotationWithPrefix returns the prefix of the Ingress annotations
|
||||
GetAnnotationWithPrefix(suffix string) string
|
||||
}
|
||||
|
||||
// AuthSSLCert contains the necessary information to do certificate based
|
||||
|
|
56
internal/ingress/resolver/mock.go
Normal file
56
internal/ingress/resolver/mock.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes 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 resolver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress/defaults"
|
||||
)
|
||||
|
||||
// Mock implements the Resolver interface
|
||||
type Mock struct {
|
||||
}
|
||||
|
||||
// GetDefaultBackend returns the backend that must be used as default
|
||||
func (m Mock) GetDefaultBackend() defaults.Backend {
|
||||
return defaults.Backend{}
|
||||
}
|
||||
|
||||
// GetSecret searches for secrets contenating the namespace and name using a the character /
|
||||
func (m Mock) GetSecret(string) (*apiv1.Secret, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetAuthCertificate resolves a given secret name into an SSL certificate.
|
||||
// The secret must contain 3 keys named:
|
||||
// ca.crt: contains the certificate chain used for authentication
|
||||
func (m Mock) GetAuthCertificate(string) (*AuthSSLCert, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetService searches for services contenating the namespace and name using a the character /
|
||||
func (m Mock) GetService(string) (*apiv1.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetAnnotationWithPrefix returns the prefix of the Ingress annotations
|
||||
func (m Mock) GetAnnotationWithPrefix(name string) string {
|
||||
return fmt.Sprintf("nginx/%v", name)
|
||||
}
|
Loading…
Reference in a new issue