Refactor annotations
This commit is contained in:
parent
f215828b1b
commit
fb33c58d18
33 changed files with 370 additions and 401 deletions
|
@ -14,12 +14,15 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package controller
|
package annotations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
"github.com/imdario/mergo"
|
||||||
|
|
||||||
extensions "k8s.io/api/extensions/v1beta1"
|
extensions "k8s.io/api/extensions/v1beta1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/alias"
|
"k8s.io/ingress-nginx/pkg/ingress/annotations/alias"
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/auth"
|
"k8s.io/ingress-nginx/pkg/ingress/annotations/auth"
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/authreq"
|
"k8s.io/ingress-nginx/pkg/ingress/annotations/authreq"
|
||||||
|
@ -48,51 +51,89 @@ import (
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/resolver"
|
"k8s.io/ingress-nginx/pkg/ingress/resolver"
|
||||||
)
|
)
|
||||||
|
|
||||||
type extractorConfig interface {
|
// DeniedKeyName name of the key that contains the reason to deny a location
|
||||||
|
const DeniedKeyName = "Denied"
|
||||||
|
|
||||||
|
type config interface {
|
||||||
resolver.AuthCertificate
|
resolver.AuthCertificate
|
||||||
resolver.DefaultBackend
|
resolver.DefaultBackend
|
||||||
resolver.Secret
|
resolver.Secret
|
||||||
resolver.Service
|
resolver.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
type annotationExtractor struct {
|
// Ingress defines the valid annotations present in one NGINX Ingress rule
|
||||||
|
type Ingress struct {
|
||||||
|
metav1.ObjectMeta
|
||||||
|
Alias string
|
||||||
|
BasicDigestAuth auth.Config
|
||||||
|
CertificateAuth authtls.Config
|
||||||
|
ClientBodyBufferSize string
|
||||||
|
ConfigurationSnippet string
|
||||||
|
CorsConfig cors.Config
|
||||||
|
DefaultBackend string
|
||||||
|
ExternalAuth authreq.Config
|
||||||
|
HealthCheck healthcheck.Config
|
||||||
|
Proxy proxy.Config
|
||||||
|
RateLimit ratelimit.Config
|
||||||
|
Redirect redirect.Config
|
||||||
|
Rewrite rewrite.Config
|
||||||
|
SecureUpstream secureupstream.Config
|
||||||
|
ServerSnippet string
|
||||||
|
ServiceUpstream bool
|
||||||
|
SessionAffinity sessionaffinity.Config
|
||||||
|
SSLPassthrough bool
|
||||||
|
UsePortInRedirects bool
|
||||||
|
UpstreamHashBy string
|
||||||
|
UpstreamVhost string
|
||||||
|
VtsFilterKey string
|
||||||
|
Whitelist ipwhitelist.SourceRange
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extractor defines the annotation parsers to be used in the extraction of annotations
|
||||||
|
type Extractor struct {
|
||||||
secretResolver resolver.Secret
|
secretResolver resolver.Secret
|
||||||
annotations map[string]parser.IngressAnnotation
|
annotations map[string]parser.IngressAnnotation
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAnnotationExtractor(cfg extractorConfig) annotationExtractor {
|
// NewAnnotationExtractor creates a new annotations extractor
|
||||||
return annotationExtractor{
|
func NewAnnotationExtractor(cfg config) Extractor {
|
||||||
|
return Extractor{
|
||||||
cfg,
|
cfg,
|
||||||
map[string]parser.IngressAnnotation{
|
map[string]parser.IngressAnnotation{
|
||||||
|
"Alias": alias.NewParser(),
|
||||||
"BasicDigestAuth": auth.NewParser(auth.AuthDirectory, cfg),
|
"BasicDigestAuth": auth.NewParser(auth.AuthDirectory, cfg),
|
||||||
"ExternalAuth": authreq.NewParser(),
|
|
||||||
"CertificateAuth": authtls.NewParser(cfg),
|
"CertificateAuth": authtls.NewParser(cfg),
|
||||||
|
"ClientBodyBufferSize": clientbodybuffersize.NewParser(),
|
||||||
|
"ConfigurationSnippet": snippet.NewParser(),
|
||||||
"CorsConfig": cors.NewParser(),
|
"CorsConfig": cors.NewParser(),
|
||||||
|
"DefaultBackend": defaultbackend.NewParser(cfg),
|
||||||
|
"ExternalAuth": authreq.NewParser(),
|
||||||
"HealthCheck": healthcheck.NewParser(cfg),
|
"HealthCheck": healthcheck.NewParser(cfg),
|
||||||
"Whitelist": ipwhitelist.NewParser(cfg),
|
|
||||||
"UsePortInRedirects": portinredirect.NewParser(cfg),
|
|
||||||
"Proxy": proxy.NewParser(cfg),
|
"Proxy": proxy.NewParser(cfg),
|
||||||
"RateLimit": ratelimit.NewParser(cfg),
|
"RateLimit": ratelimit.NewParser(cfg),
|
||||||
"Redirect": redirect.NewParser(),
|
"Redirect": redirect.NewParser(),
|
||||||
"Rewrite": rewrite.NewParser(cfg),
|
"Rewrite": rewrite.NewParser(cfg),
|
||||||
"SecureUpstream": secureupstream.NewParser(cfg),
|
"SecureUpstream": secureupstream.NewParser(cfg),
|
||||||
|
"ServerSnippet": serversnippet.NewParser(),
|
||||||
"ServiceUpstream": serviceupstream.NewParser(),
|
"ServiceUpstream": serviceupstream.NewParser(),
|
||||||
"SessionAffinity": sessionaffinity.NewParser(),
|
"SessionAffinity": sessionaffinity.NewParser(),
|
||||||
"SSLPassthrough": sslpassthrough.NewParser(),
|
"SSLPassthrough": sslpassthrough.NewParser(),
|
||||||
"ConfigurationSnippet": snippet.NewParser(),
|
"UsePortInRedirects": portinredirect.NewParser(cfg),
|
||||||
"Alias": alias.NewParser(),
|
|
||||||
"ClientBodyBufferSize": clientbodybuffersize.NewParser(),
|
|
||||||
"DefaultBackend": defaultbackend.NewParser(cfg),
|
|
||||||
"UpstreamHashBy": upstreamhashby.NewParser(),
|
"UpstreamHashBy": upstreamhashby.NewParser(),
|
||||||
"UpstreamVhost": upstreamvhost.NewParser(),
|
"UpstreamVhost": upstreamvhost.NewParser(),
|
||||||
"VtsFilterKey": vtsfilterkey.NewParser(),
|
"VtsFilterKey": vtsfilterkey.NewParser(),
|
||||||
"ServerSnippet": serversnippet.NewParser(),
|
"Whitelist": ipwhitelist.NewParser(cfg),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *annotationExtractor) Extract(ing *extensions.Ingress) map[string]interface{} {
|
// Extract extracts the annotations from an Ingress
|
||||||
anns := make(map[string]interface{})
|
func (e Extractor) Extract(ing *extensions.Ingress) *Ingress {
|
||||||
|
pia := &Ingress{
|
||||||
|
ObjectMeta: ing.ObjectMeta,
|
||||||
|
}
|
||||||
|
|
||||||
|
data := make(map[string]interface{})
|
||||||
for name, annotationParser := range e.annotations {
|
for name, annotationParser := range e.annotations {
|
||||||
val, err := annotationParser.Parse(ing)
|
val, err := annotationParser.Parse(ing)
|
||||||
glog.V(5).Infof("annotation %v in Ingress %v/%v: %v", name, ing.GetNamespace(), ing.GetName(), val)
|
glog.V(5).Infof("annotation %v in Ingress %v/%v: %v", name, ing.GetNamespace(), ing.GetName(), val)
|
||||||
|
@ -105,9 +146,9 @@ func (e *annotationExtractor) Extract(ing *extensions.Ingress) map[string]interf
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
_, alreadyDenied := anns[DeniedKeyName]
|
_, alreadyDenied := data[DeniedKeyName]
|
||||||
if !alreadyDenied {
|
if !alreadyDenied {
|
||||||
anns[DeniedKeyName] = err
|
data[DeniedKeyName] = err
|
||||||
glog.Errorf("error reading %v annotation in Ingress %v/%v: %v", name, ing.GetNamespace(), ing.GetName(), err)
|
glog.Errorf("error reading %v annotation in Ingress %v/%v: %v", name, ing.GetNamespace(), ing.GetName(), err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -116,90 +157,14 @@ func (e *annotationExtractor) Extract(ing *extensions.Ingress) map[string]interf
|
||||||
}
|
}
|
||||||
|
|
||||||
if val != nil {
|
if val != nil {
|
||||||
anns[name] = val
|
data[name] = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return anns
|
err := mergo.Map(pia, data)
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
secureUpstream = "SecureUpstream"
|
|
||||||
healthCheck = "HealthCheck"
|
|
||||||
sslPassthrough = "SSLPassthrough"
|
|
||||||
sessionAffinity = "SessionAffinity"
|
|
||||||
serviceUpstream = "ServiceUpstream"
|
|
||||||
serverAlias = "Alias"
|
|
||||||
corsConfig = "CorsConfig"
|
|
||||||
clientBodyBufferSize = "ClientBodyBufferSize"
|
|
||||||
certificateAuth = "CertificateAuth"
|
|
||||||
serverSnippet = "ServerSnippet"
|
|
||||||
upstreamHashBy = "UpstreamHashBy"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (e *annotationExtractor) ServiceUpstream(ing *extensions.Ingress) bool {
|
|
||||||
val, _ := e.annotations[serviceUpstream].Parse(ing)
|
|
||||||
return val.(bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *annotationExtractor) SecureUpstream(ing *extensions.Ingress) *secureupstream.Secure {
|
|
||||||
val, err := e.annotations[secureUpstream].Parse(ing)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("error parsing secure upstream: %v", err)
|
glog.Errorf("unexpected error merging extracted annotations: %v", err)
|
||||||
}
|
|
||||||
secure := val.(*secureupstream.Secure)
|
|
||||||
return secure
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *annotationExtractor) HealthCheck(ing *extensions.Ingress) *healthcheck.Upstream {
|
|
||||||
val, _ := e.annotations[healthCheck].Parse(ing)
|
|
||||||
return val.(*healthcheck.Upstream)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *annotationExtractor) SSLPassthrough(ing *extensions.Ingress) bool {
|
|
||||||
val, _ := e.annotations[sslPassthrough].Parse(ing)
|
|
||||||
return val.(bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *annotationExtractor) Alias(ing *extensions.Ingress) string {
|
|
||||||
val, _ := e.annotations[serverAlias].Parse(ing)
|
|
||||||
return val.(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *annotationExtractor) ClientBodyBufferSize(ing *extensions.Ingress) string {
|
|
||||||
val, _ := e.annotations[clientBodyBufferSize].Parse(ing)
|
|
||||||
return val.(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *annotationExtractor) SessionAffinity(ing *extensions.Ingress) *sessionaffinity.AffinityConfig {
|
|
||||||
val, _ := e.annotations[sessionAffinity].Parse(ing)
|
|
||||||
return val.(*sessionaffinity.AffinityConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *annotationExtractor) Cors(ing *extensions.Ingress) *cors.CorsConfig {
|
|
||||||
val, _ := e.annotations[corsConfig].Parse(ing)
|
|
||||||
return val.(*cors.CorsConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *annotationExtractor) CertificateAuth(ing *extensions.Ingress) *authtls.AuthSSLConfig {
|
|
||||||
val, err := e.annotations[certificateAuth].Parse(ing)
|
|
||||||
if errors.IsMissingAnnotations(err) {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
return pia
|
||||||
glog.Errorf("error parsing certificate auth: %v", err)
|
|
||||||
}
|
|
||||||
secure := val.(*authtls.AuthSSLConfig)
|
|
||||||
return secure
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *annotationExtractor) ServerSnippet(ing *extensions.Ingress) string {
|
|
||||||
val, _ := e.annotations[serverSnippet].Parse(ing)
|
|
||||||
return val.(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *annotationExtractor) UpstreamHashBy(ing *extensions.Ingress) string {
|
|
||||||
val, _ := e.annotations[upstreamHashBy].Parse(ing)
|
|
||||||
return val.(string)
|
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package controller
|
package annotations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -75,20 +75,6 @@ func (m mockCfg) GetAuthCertificate(name string) (*resolver.AuthSSLCert, error)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAnnotationExtractor(t *testing.T) {
|
|
||||||
ec := newAnnotationExtractor(mockCfg{})
|
|
||||||
ing := buildIngress()
|
|
||||||
|
|
||||||
m := ec.Extract(ing)
|
|
||||||
// the map at least should contains HealthCheck and Proxy information (defaults)
|
|
||||||
if _, ok := m["HealthCheck"]; !ok {
|
|
||||||
t.Error("expected HealthCheck annotation")
|
|
||||||
}
|
|
||||||
if _, ok := m["Proxy"]; !ok {
|
|
||||||
t.Error("expected Proxy annotation")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildIngress() *extensions.Ingress {
|
func buildIngress() *extensions.Ingress {
|
||||||
defaultBackend := extensions.IngressBackend{
|
defaultBackend := extensions.IngressBackend{
|
||||||
ServiceName: "default-backend",
|
ServiceName: "default-backend",
|
||||||
|
@ -125,7 +111,7 @@ func buildIngress() *extensions.Ingress {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSecureUpstream(t *testing.T) {
|
func TestSecureUpstream(t *testing.T) {
|
||||||
ec := newAnnotationExtractor(mockCfg{})
|
ec := NewAnnotationExtractor(mockCfg{})
|
||||||
ing := buildIngress()
|
ing := buildIngress()
|
||||||
|
|
||||||
fooAnns := []struct {
|
fooAnns := []struct {
|
||||||
|
@ -141,7 +127,7 @@ func TestSecureUpstream(t *testing.T) {
|
||||||
|
|
||||||
for _, foo := range fooAnns {
|
for _, foo := range fooAnns {
|
||||||
ing.SetAnnotations(foo.annotations)
|
ing.SetAnnotations(foo.annotations)
|
||||||
r := ec.SecureUpstream(ing)
|
r := ec.Extract(ing).SecureUpstream
|
||||||
if r.Secure != foo.er {
|
if r.Secure != foo.er {
|
||||||
t.Errorf("Returned %v but expected %v", r, foo.er)
|
t.Errorf("Returned %v but expected %v", r, foo.er)
|
||||||
}
|
}
|
||||||
|
@ -149,7 +135,7 @@ func TestSecureUpstream(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSecureVerifyCACert(t *testing.T) {
|
func TestSecureVerifyCACert(t *testing.T) {
|
||||||
ec := newAnnotationExtractor(mockCfg{
|
ec := NewAnnotationExtractor(mockCfg{
|
||||||
MockSecrets: map[string]*apiv1.Secret{
|
MockSecrets: map[string]*apiv1.Secret{
|
||||||
"default/secure-verify-ca": {
|
"default/secure-verify-ca": {
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
@ -176,15 +162,16 @@ func TestSecureVerifyCACert(t *testing.T) {
|
||||||
for _, ann := range anns {
|
for _, ann := range anns {
|
||||||
ing := buildIngress()
|
ing := buildIngress()
|
||||||
ing.SetAnnotations(ann.annotations)
|
ing.SetAnnotations(ann.annotations)
|
||||||
res := ec.SecureUpstream(ing)
|
res := ec.Extract(ing).SecureUpstream
|
||||||
if (res.CACert.CAFileName != "") != ann.exists {
|
|
||||||
|
if (res != nil && res.CACert.CAFileName != "") != ann.exists {
|
||||||
t.Errorf("Expected exists was %v on iteration %v", ann.exists, ann.it)
|
t.Errorf("Expected exists was %v on iteration %v", ann.exists, ann.it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHealthCheck(t *testing.T) {
|
func TestHealthCheck(t *testing.T) {
|
||||||
ec := newAnnotationExtractor(mockCfg{})
|
ec := NewAnnotationExtractor(mockCfg{})
|
||||||
ing := buildIngress()
|
ing := buildIngress()
|
||||||
|
|
||||||
fooAnns := []struct {
|
fooAnns := []struct {
|
||||||
|
@ -201,7 +188,7 @@ func TestHealthCheck(t *testing.T) {
|
||||||
|
|
||||||
for _, foo := range fooAnns {
|
for _, foo := range fooAnns {
|
||||||
ing.SetAnnotations(foo.annotations)
|
ing.SetAnnotations(foo.annotations)
|
||||||
r := ec.HealthCheck(ing)
|
r := ec.Extract(ing).HealthCheck
|
||||||
if r == nil {
|
if r == nil {
|
||||||
t.Errorf("Returned nil but expected a healthcheck.Upstream")
|
t.Errorf("Returned nil but expected a healthcheck.Upstream")
|
||||||
continue
|
continue
|
||||||
|
@ -218,7 +205,7 @@ func TestHealthCheck(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSSLPassthrough(t *testing.T) {
|
func TestSSLPassthrough(t *testing.T) {
|
||||||
ec := newAnnotationExtractor(mockCfg{})
|
ec := NewAnnotationExtractor(mockCfg{})
|
||||||
ing := buildIngress()
|
ing := buildIngress()
|
||||||
|
|
||||||
fooAnns := []struct {
|
fooAnns := []struct {
|
||||||
|
@ -234,7 +221,7 @@ func TestSSLPassthrough(t *testing.T) {
|
||||||
|
|
||||||
for _, foo := range fooAnns {
|
for _, foo := range fooAnns {
|
||||||
ing.SetAnnotations(foo.annotations)
|
ing.SetAnnotations(foo.annotations)
|
||||||
r := ec.SSLPassthrough(ing)
|
r := ec.Extract(ing).SSLPassthrough
|
||||||
if r != foo.er {
|
if r != foo.er {
|
||||||
t.Errorf("Returned %v but expected %v", r, foo.er)
|
t.Errorf("Returned %v but expected %v", r, foo.er)
|
||||||
}
|
}
|
||||||
|
@ -242,7 +229,7 @@ func TestSSLPassthrough(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpstreamHashBy(t *testing.T) {
|
func TestUpstreamHashBy(t *testing.T) {
|
||||||
ec := newAnnotationExtractor(mockCfg{})
|
ec := NewAnnotationExtractor(mockCfg{})
|
||||||
ing := buildIngress()
|
ing := buildIngress()
|
||||||
|
|
||||||
fooAnns := []struct {
|
fooAnns := []struct {
|
||||||
|
@ -258,7 +245,7 @@ func TestUpstreamHashBy(t *testing.T) {
|
||||||
|
|
||||||
for _, foo := range fooAnns {
|
for _, foo := range fooAnns {
|
||||||
ing.SetAnnotations(foo.annotations)
|
ing.SetAnnotations(foo.annotations)
|
||||||
r := ec.UpstreamHashBy(ing)
|
r := ec.Extract(ing).UpstreamHashBy
|
||||||
if r != foo.er {
|
if r != foo.er {
|
||||||
t.Errorf("Returned %v but expected %v", r, foo.er)
|
t.Errorf("Returned %v but expected %v", r, foo.er)
|
||||||
}
|
}
|
||||||
|
@ -266,7 +253,7 @@ func TestUpstreamHashBy(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAffinitySession(t *testing.T) {
|
func TestAffinitySession(t *testing.T) {
|
||||||
ec := newAnnotationExtractor(mockCfg{})
|
ec := NewAnnotationExtractor(mockCfg{})
|
||||||
ing := buildIngress()
|
ing := buildIngress()
|
||||||
|
|
||||||
fooAnns := []struct {
|
fooAnns := []struct {
|
||||||
|
@ -284,25 +271,25 @@ func TestAffinitySession(t *testing.T) {
|
||||||
|
|
||||||
for _, foo := range fooAnns {
|
for _, foo := range fooAnns {
|
||||||
ing.SetAnnotations(foo.annotations)
|
ing.SetAnnotations(foo.annotations)
|
||||||
r := ec.SessionAffinity(ing)
|
r := ec.Extract(ing).SessionAffinity
|
||||||
t.Logf("Testing pass %v %v %v", foo.affinitytype, foo.hash, foo.name)
|
t.Logf("Testing pass %v %v %v", foo.affinitytype, foo.hash, foo.name)
|
||||||
if r == nil {
|
if r == nil {
|
||||||
t.Errorf("Returned nil but expected a SessionAffinity.AffinityConfig")
|
t.Errorf("Returned nil but expected a SessionAffinity.AffinityConfig")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.CookieConfig.Hash != foo.hash {
|
if r.Cookie.Hash != foo.hash {
|
||||||
t.Errorf("Returned %v but expected %v for Hash", r.CookieConfig.Hash, foo.hash)
|
t.Errorf("Returned %v but expected %v for Hash", r.Cookie.Hash, foo.hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.CookieConfig.Name != foo.name {
|
if r.Cookie.Name != foo.name {
|
||||||
t.Errorf("Returned %v but expected %v for Name", r.CookieConfig.Name, foo.name)
|
t.Errorf("Returned %v but expected %v for Name", r.Cookie.Name, foo.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCors(t *testing.T) {
|
func TestCors(t *testing.T) {
|
||||||
ec := newAnnotationExtractor(mockCfg{})
|
ec := NewAnnotationExtractor(mockCfg{})
|
||||||
ing := buildIngress()
|
ing := buildIngress()
|
||||||
|
|
||||||
fooAnns := []struct {
|
fooAnns := []struct {
|
||||||
|
@ -322,7 +309,7 @@ func TestCors(t *testing.T) {
|
||||||
|
|
||||||
for _, foo := range fooAnns {
|
for _, foo := range fooAnns {
|
||||||
ing.SetAnnotations(foo.annotations)
|
ing.SetAnnotations(foo.annotations)
|
||||||
r := ec.Cors(ing)
|
r := ec.Extract(ing).CorsConfig
|
||||||
t.Logf("Testing pass %v %v %v %v %v", foo.corsenabled, foo.methods, foo.headers, foo.origin, foo.credentials)
|
t.Logf("Testing pass %v %v %v %v %v", foo.corsenabled, foo.methods, foo.headers, foo.origin, foo.credentials)
|
||||||
if r == nil {
|
if r == nil {
|
||||||
t.Errorf("Returned nil but expected a Cors.CorsConfig")
|
t.Errorf("Returned nil but expected a Cors.CorsConfig")
|
||||||
|
@ -351,3 +338,48 @@ func TestCors(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func TestMergeLocationAnnotations(t *testing.T) {
|
||||||
|
// initial parameters
|
||||||
|
keys := []string{"BasicDigestAuth", "CorsConfig", "ExternalAuth", "RateLimit", "Redirect", "Rewrite", "Whitelist", "Proxy", "UsePortInRedirects"}
|
||||||
|
|
||||||
|
loc := ingress.Location{}
|
||||||
|
annotations := &Ingress{
|
||||||
|
BasicDigestAuth: &auth.Config{},
|
||||||
|
CorsConfig: &cors.Config{},
|
||||||
|
ExternalAuth: &authreq.Config{},
|
||||||
|
RateLimit: &ratelimit.Config{},
|
||||||
|
Redirect: &redirect.Config{},
|
||||||
|
Rewrite: &rewrite.Config{},
|
||||||
|
Whitelist: &ipwhitelist.SourceRange{},
|
||||||
|
Proxy: &proxy.Config{},
|
||||||
|
UsePortInRedirects: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// create test table
|
||||||
|
type fooMergeLocationAnnotationsStruct struct {
|
||||||
|
fName string
|
||||||
|
er interface{}
|
||||||
|
}
|
||||||
|
fooTests := []fooMergeLocationAnnotationsStruct{}
|
||||||
|
for name, value := range keys {
|
||||||
|
fva := fooMergeLocationAnnotationsStruct{name, value}
|
||||||
|
fooTests = append(fooTests, fva)
|
||||||
|
}
|
||||||
|
|
||||||
|
// execute test
|
||||||
|
MergeWithLocation(&loc, annotations)
|
||||||
|
|
||||||
|
// check result
|
||||||
|
for _, foo := range fooTests {
|
||||||
|
fv := reflect.ValueOf(loc).FieldByName(foo.fName).Interface()
|
||||||
|
if !reflect.DeepEqual(fv, foo.er) {
|
||||||
|
t.Errorf("Returned %v but expected %v for the field %s", fv, foo.er, foo.fName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, ok := annotations[DeniedKeyName]; ok {
|
||||||
|
t.Errorf("%s should be removed after mergeLocationAnnotations", DeniedKeyName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
|
@ -46,8 +46,8 @@ var (
|
||||||
AuthDirectory = "/etc/ingress-controller/auth"
|
AuthDirectory = "/etc/ingress-controller/auth"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BasicDigest returns authentication configuration for an Ingress rule
|
// Config returns authentication configuration for an Ingress rule
|
||||||
type BasicDigest struct {
|
type Config struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Realm string `json:"realm"`
|
Realm string `json:"realm"`
|
||||||
File string `json:"file"`
|
File string `json:"file"`
|
||||||
|
@ -55,8 +55,8 @@ type BasicDigest struct {
|
||||||
FileSHA string `json:"fileSha"`
|
FileSHA string `json:"fileSha"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal tests for equality between two BasicDigest types
|
// Equal tests for equality between two Config types
|
||||||
func (bd1 *BasicDigest) Equal(bd2 *BasicDigest) bool {
|
func (bd1 *Config) Equal(bd2 *Config) bool {
|
||||||
if bd1 == bd2 {
|
if bd1 == bd2 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ func (a auth) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &BasicDigest{
|
return &Config{
|
||||||
Type: at,
|
Type: at,
|
||||||
Realm: realm,
|
Realm: realm,
|
||||||
File: passFile,
|
File: passFile,
|
||||||
|
|
|
@ -109,7 +109,7 @@ func TestIngressAuth(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Uxpected error with ingress: %v", err)
|
t.Errorf("Uxpected error with ingress: %v", err)
|
||||||
}
|
}
|
||||||
auth, ok := i.(*BasicDigest)
|
auth, ok := i.(*Config)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected a BasicDigest type")
|
t.Errorf("expected a BasicDigest type")
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// External returns external authentication configuration for an Ingress rule
|
// External returns external authentication configuration for an Ingress rule
|
||||||
type External struct {
|
type Config struct {
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
// Host contains the hostname defined in the URL
|
// Host contains the hostname defined in the URL
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
|
@ -45,8 +45,8 @@ type External struct {
|
||||||
ResponseHeaders []string `json:"responseHeaders,omitEmpty"`
|
ResponseHeaders []string `json:"responseHeaders,omitEmpty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal tests for equality between two External types
|
// Equal tests for equality between two Config types
|
||||||
func (e1 *External) Equal(e2 *External) bool {
|
func (e1 *Config) Equal(e2 *Config) bool {
|
||||||
if e1 == e2 {
|
if e1 == e2 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ func NewParser() parser.IngressAnnotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseAnnotations parses the annotations contained in the ingress
|
// ParseAnnotations parses the annotations contained in the ingress
|
||||||
// rule used to use an external URL as source for authentication
|
// rule used to use an Config URL as source for authentication
|
||||||
func (a authReq) Parse(ing *extensions.Ingress) (interface{}, error) {
|
func (a authReq) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
str, err := parser.GetStringAnnotation(authURL, ing)
|
str, err := parser.GetStringAnnotation(authURL, ing)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -165,7 +165,7 @@ func (a authReq) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &External{
|
return &Config{
|
||||||
URL: str,
|
URL: str,
|
||||||
Host: ur.Hostname(),
|
Host: ur.Hostname(),
|
||||||
SigninURL: signin,
|
SigninURL: signin,
|
||||||
|
|
|
@ -97,7 +97,7 @@ func TestAnnotations(t *testing.T) {
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
u, ok := i.(*External)
|
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)
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ func TestHeaderAnnotations(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Log(i)
|
t.Log(i)
|
||||||
u, ok := i.(*External)
|
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)
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -20,11 +20,12 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
extensions "k8s.io/api/extensions/v1beta1"
|
extensions "k8s.io/api/extensions/v1beta1"
|
||||||
|
|
||||||
|
"regexp"
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/parser"
|
"k8s.io/ingress-nginx/pkg/ingress/annotations/parser"
|
||||||
ing_errors "k8s.io/ingress-nginx/pkg/ingress/errors"
|
ing_errors "k8s.io/ingress-nginx/pkg/ingress/errors"
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/resolver"
|
"k8s.io/ingress-nginx/pkg/ingress/resolver"
|
||||||
"k8s.io/ingress-nginx/pkg/k8s"
|
"k8s.io/ingress-nginx/pkg/k8s"
|
||||||
"regexp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -41,17 +42,17 @@ var (
|
||||||
authVerifyClientRegex = regexp.MustCompile(`on|off|optional|optional_no_ca`)
|
authVerifyClientRegex = regexp.MustCompile(`on|off|optional|optional_no_ca`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// AuthSSLConfig contains the AuthSSLCert used for muthual autentication
|
// Config contains the AuthSSLCert used for muthual autentication
|
||||||
// and the configured ValidationDepth
|
// and the configured ValidationDepth
|
||||||
type AuthSSLConfig struct {
|
type Config struct {
|
||||||
resolver.AuthSSLCert
|
resolver.AuthSSLCert
|
||||||
VerifyClient string `json:"verify_client"`
|
VerifyClient string `json:"verify_client"`
|
||||||
ValidationDepth int `json:"validationDepth"`
|
ValidationDepth int `json:"validationDepth"`
|
||||||
ErrorPage string `json:"errorPage"`
|
ErrorPage string `json:"errorPage"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal tests for equality between two AuthSSLConfig types
|
// Equal tests for equality between two Config types
|
||||||
func (assl1 *AuthSSLConfig) Equal(assl2 *AuthSSLConfig) bool {
|
func (assl1 *Config) Equal(assl2 *Config) bool {
|
||||||
if assl1 == assl2 {
|
if assl1 == assl2 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -88,16 +89,16 @@ func (a authTLS) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
|
|
||||||
tlsauthsecret, err := parser.GetStringAnnotation(annotationAuthTLSSecret, ing)
|
tlsauthsecret, err := parser.GetStringAnnotation(annotationAuthTLSSecret, ing)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &AuthSSLConfig{}, err
|
return &Config{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if tlsauthsecret == "" {
|
if tlsauthsecret == "" {
|
||||||
return &AuthSSLConfig{}, ing_errors.NewLocationDenied("an empty string is not a valid secret name")
|
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 &AuthSSLConfig{}, ing_errors.NewLocationDenied(err.Error())
|
return &Config{}, ing_errors.NewLocationDenied(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsVerifyClient, err := parser.GetStringAnnotation(annotationAuthVerifyClient, ing)
|
tlsVerifyClient, err := parser.GetStringAnnotation(annotationAuthVerifyClient, ing)
|
||||||
|
@ -112,7 +113,7 @@ func (a authTLS) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
|
|
||||||
authCert, err := a.certResolver.GetAuthCertificate(tlsauthsecret)
|
authCert, err := a.certResolver.GetAuthCertificate(tlsauthsecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &AuthSSLConfig{}, ing_errors.LocationDenied{
|
return &Config{}, ing_errors.LocationDenied{
|
||||||
Reason: errors.Wrap(err, "error obtaining certificate"),
|
Reason: errors.Wrap(err, "error obtaining certificate"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,7 +123,7 @@ func (a authTLS) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
errorpage = ""
|
errorpage = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return &AuthSSLConfig{
|
return &Config{
|
||||||
AuthSSLCert: *authCert,
|
AuthSSLCert: *authCert,
|
||||||
VerifyClient: tlsVerifyClient,
|
VerifyClient: tlsVerifyClient,
|
||||||
ValidationDepth: tlsdepth,
|
ValidationDepth: tlsdepth,
|
||||||
|
|
|
@ -51,8 +51,8 @@ var (
|
||||||
type cors struct {
|
type cors struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CorsConfig contains the Cors configuration to be used in the Ingress
|
// Config contains the Cors configuration to be used in the Ingress
|
||||||
type CorsConfig struct {
|
type Config struct {
|
||||||
CorsEnabled bool `json:"corsEnabled"`
|
CorsEnabled bool `json:"corsEnabled"`
|
||||||
CorsAllowOrigin string `json:"corsAllowOrigin"`
|
CorsAllowOrigin string `json:"corsAllowOrigin"`
|
||||||
CorsAllowMethods string `json:"corsAllowMethods"`
|
CorsAllowMethods string `json:"corsAllowMethods"`
|
||||||
|
@ -66,7 +66,7 @@ func NewParser() parser.IngressAnnotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal tests for equality between two External types
|
// Equal tests for equality between two External types
|
||||||
func (c1 *CorsConfig) Equal(c2 *CorsConfig) bool {
|
func (c1 *Config) Equal(c2 *Config) bool {
|
||||||
if c1 == c2 {
|
if c1 == c2 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ func (a cors) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
corsallowcredentials = true
|
corsallowcredentials = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return &CorsConfig{
|
return &Config{
|
||||||
CorsEnabled: corsenabled,
|
CorsEnabled: corsenabled,
|
||||||
CorsAllowOrigin: corsalloworigin,
|
CorsAllowOrigin: corsalloworigin,
|
||||||
CorsAllowHeaders: corsallowheaders,
|
CorsAllowHeaders: corsallowheaders,
|
||||||
|
|
|
@ -72,7 +72,7 @@ func TestIngressCorsConfig(t *testing.T) {
|
||||||
ing.SetAnnotations(data)
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
corst, _ := NewParser().Parse(ing)
|
corst, _ := NewParser().Parse(ing)
|
||||||
nginxCors, ok := corst.(*CorsConfig)
|
nginxCors, ok := corst.(*Config)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected a Config type")
|
t.Errorf("expected a Config type")
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,9 @@ const (
|
||||||
upsFailTimeout = "ingress.kubernetes.io/upstream-fail-timeout"
|
upsFailTimeout = "ingress.kubernetes.io/upstream-fail-timeout"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Upstream returns the URL and method to use check the status of
|
// Config returns the URL and method to use check the status of
|
||||||
// the upstream server/s
|
// the upstream server/s
|
||||||
type Upstream struct {
|
type Config struct {
|
||||||
MaxFails int `json:"maxFails"`
|
MaxFails int `json:"maxFails"`
|
||||||
FailTimeout int `json:"failTimeout"`
|
FailTimeout int `json:"failTimeout"`
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ func NewParser(br resolver.DefaultBackend) parser.IngressAnnotation {
|
||||||
func (a healthCheck) Parse(ing *extensions.Ingress) (interface{}, error) {
|
func (a healthCheck) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
defBackend := a.backendResolver.GetDefaultBackend()
|
defBackend := a.backendResolver.GetDefaultBackend()
|
||||||
if ing.GetAnnotations() == nil {
|
if ing.GetAnnotations() == nil {
|
||||||
return &Upstream{defBackend.UpstreamMaxFails, defBackend.UpstreamFailTimeout}, nil
|
return &Config{defBackend.UpstreamMaxFails, defBackend.UpstreamFailTimeout}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mf, err := parser.GetIntAnnotation(upsMaxFails, ing)
|
mf, err := parser.GetIntAnnotation(upsMaxFails, ing)
|
||||||
|
@ -62,5 +62,5 @@ func (a healthCheck) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
ft = defBackend.UpstreamFailTimeout
|
ft = defBackend.UpstreamFailTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Upstream{mf, ft}, nil
|
return &Config{mf, ft}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ func TestIngressHealthCheck(t *testing.T) {
|
||||||
ing.SetAnnotations(data)
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
hzi, _ := NewParser(mockBackend{}).Parse(ing)
|
hzi, _ := NewParser(mockBackend{}).Parse(ing)
|
||||||
nginxHz, ok := hzi.(*Upstream)
|
nginxHz, ok := hzi.(*Config)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected a Upstream type")
|
t.Errorf("expected a Upstream type")
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package portinredirect
|
package portinredirect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
api "k8s.io/api/core/v1"
|
api "k8s.io/api/core/v1"
|
||||||
|
@ -24,8 +25,6 @@ import (
|
||||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/defaults"
|
"k8s.io/ingress-nginx/pkg/ingress/defaults"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,8 @@ const (
|
||||||
requestBuffering = "ingress.kubernetes.io/proxy-request-buffering"
|
requestBuffering = "ingress.kubernetes.io/proxy-request-buffering"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Configuration returns the proxy timeout to use in the upstream server/s
|
// Config returns the proxy timeout to use in the upstream server/s
|
||||||
type Configuration struct {
|
type Config struct {
|
||||||
BodySize string `json:"bodySize"`
|
BodySize string `json:"bodySize"`
|
||||||
ConnectTimeout int `json:"connectTimeout"`
|
ConnectTimeout int `json:"connectTimeout"`
|
||||||
SendTimeout int `json:"sendTimeout"`
|
SendTimeout int `json:"sendTimeout"`
|
||||||
|
@ -51,7 +51,7 @@ type Configuration struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal tests for equality between two Configuration types
|
// Equal tests for equality between two Configuration types
|
||||||
func (l1 *Configuration) Equal(l2 *Configuration) bool {
|
func (l1 *Config) Equal(l2 *Config) bool {
|
||||||
if l1 == l2 {
|
if l1 == l2 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -156,5 +156,5 @@ func (a proxy) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
rb = defBackend.ProxyRequestBuffering
|
rb = defBackend.ProxyRequestBuffering
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Configuration{bs, ct, st, rt, bufs, cd, cp, nu, pp, rb}, nil
|
return &Config{bs, ct, st, rt, bufs, cd, cp, nu, pp, rb}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,9 +97,9 @@ func TestProxy(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error parsing a valid")
|
t.Fatalf("unexpected error parsing a valid")
|
||||||
}
|
}
|
||||||
p, ok := i.(*Configuration)
|
p, ok := i.(*Config)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("expected a Configuration type")
|
t.Fatalf("expected a Config type")
|
||||||
}
|
}
|
||||||
if p.ConnectTimeout != 1 {
|
if p.ConnectTimeout != 1 {
|
||||||
t.Errorf("expected 1 as connect-timeout but returned %v", p.ConnectTimeout)
|
t.Errorf("expected 1 as connect-timeout but returned %v", p.ConnectTimeout)
|
||||||
|
@ -137,9 +137,9 @@ func TestProxyWithNoAnnotation(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error parsing a valid")
|
t.Fatalf("unexpected error parsing a valid")
|
||||||
}
|
}
|
||||||
p, ok := i.(*Configuration)
|
p, ok := i.(*Config)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("expected a Configuration type")
|
t.Fatalf("expected a Config type")
|
||||||
}
|
}
|
||||||
if p.ConnectTimeout != 10 {
|
if p.ConnectTimeout != 10 {
|
||||||
t.Errorf("expected 10 as connect-timeout but returned %v", p.ConnectTimeout)
|
t.Errorf("expected 10 as connect-timeout but returned %v", p.ConnectTimeout)
|
||||||
|
|
|
@ -45,11 +45,11 @@ const (
|
||||||
defSharedSize = 5
|
defSharedSize = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
// RateLimit returns rate limit configuration for an Ingress rule limiting the
|
// Config returns rate limit configuration for an Ingress rule limiting the
|
||||||
// number of connections per IP address and/or connections per second.
|
// number of connections per IP address and/or connections per second.
|
||||||
// If you both annotations are specified in a single Ingress rule, RPS limits
|
// If you both annotations are specified in a single Ingress rule, RPS limits
|
||||||
// takes precedence
|
// takes precedence
|
||||||
type RateLimit struct {
|
type Config struct {
|
||||||
// Connections indicates a limit with the number of connections per IP address
|
// Connections indicates a limit with the number of connections per IP address
|
||||||
Connections Zone `json:"connections"`
|
Connections Zone `json:"connections"`
|
||||||
// RPS indicates a limit with the number of connections per second
|
// RPS indicates a limit with the number of connections per second
|
||||||
|
@ -69,7 +69,7 @@ type RateLimit struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal tests for equality between two RateLimit types
|
// Equal tests for equality between two RateLimit types
|
||||||
func (rt1 *RateLimit) Equal(rt2 *RateLimit) bool {
|
func (rt1 *Config) Equal(rt2 *Config) bool {
|
||||||
if rt1 == rt2 {
|
if rt1 == rt2 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ func (a ratelimit) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if rpm == 0 && rps == 0 && conn == 0 {
|
if rpm == 0 && rps == 0 && conn == 0 {
|
||||||
return &RateLimit{
|
return &Config{
|
||||||
Connections: Zone{},
|
Connections: Zone{},
|
||||||
RPS: Zone{},
|
RPS: Zone{},
|
||||||
RPM: Zone{},
|
RPM: Zone{},
|
||||||
|
@ -196,7 +196,7 @@ func (a ratelimit) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
|
|
||||||
zoneName := fmt.Sprintf("%v_%v", ing.GetNamespace(), ing.GetName())
|
zoneName := fmt.Sprintf("%v_%v", ing.GetNamespace(), ing.GetName())
|
||||||
|
|
||||||
return &RateLimit{
|
return &Config{
|
||||||
Connections: Zone{
|
Connections: Zone{
|
||||||
Name: fmt.Sprintf("%v_conn", zoneName),
|
Name: fmt.Sprintf("%v_conn", zoneName),
|
||||||
Limit: conn,
|
Limit: conn,
|
||||||
|
|
|
@ -107,7 +107,7 @@ func TestBadRateLimiting(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
rateLimit, ok := i.(*RateLimit)
|
rateLimit, ok := i.(*Config)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected a RateLimit type")
|
t.Errorf("expected a RateLimit type")
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,8 @@ const (
|
||||||
www = "ingress.kubernetes.io/from-to-www-redirect"
|
www = "ingress.kubernetes.io/from-to-www-redirect"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Redirect returns the redirect configuration for an Ingress rule
|
// Config returns the redirect configuration for an Ingress rule
|
||||||
type Redirect struct {
|
type Config struct {
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
Code int `json:"code"`
|
Code int `json:"code"`
|
||||||
FromToWWW bool `json:"fromToWWW"`
|
FromToWWW bool `json:"fromToWWW"`
|
||||||
|
@ -64,7 +64,7 @@ func (a redirect) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Redirect{
|
return &Config{
|
||||||
URL: tr,
|
URL: tr,
|
||||||
Code: http.StatusFound,
|
Code: http.StatusFound,
|
||||||
FromToWWW: r3w,
|
FromToWWW: r3w,
|
||||||
|
@ -81,7 +81,7 @@ func (a redirect) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Redirect{
|
return &Config{
|
||||||
URL: pr,
|
URL: pr,
|
||||||
Code: http.StatusMovedPermanently,
|
Code: http.StatusMovedPermanently,
|
||||||
FromToWWW: r3w,
|
FromToWWW: r3w,
|
||||||
|
@ -89,7 +89,7 @@ func (a redirect) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if r3w {
|
if r3w {
|
||||||
return &Redirect{
|
return &Config{
|
||||||
FromToWWW: r3w,
|
FromToWWW: r3w,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ func (a redirect) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal tests for equality between two Redirect types
|
// Equal tests for equality between two Redirect types
|
||||||
func (r1 *Redirect) Equal(r2 *Redirect) bool {
|
func (r1 *Config) Equal(r2 *Config) bool {
|
||||||
if r1 == r2 {
|
if r1 == r2 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,8 @@ const (
|
||||||
appRoot = "ingress.kubernetes.io/app-root"
|
appRoot = "ingress.kubernetes.io/app-root"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Redirect describes the per location redirect config
|
// Config describes the per location redirect config
|
||||||
type Redirect struct {
|
type Config struct {
|
||||||
// Target URI where the traffic must be redirected
|
// Target URI where the traffic must be redirected
|
||||||
Target string `json:"target"`
|
Target string `json:"target"`
|
||||||
// AddBaseURL indicates if is required to add a base tag in the head
|
// AddBaseURL indicates if is required to add a base tag in the head
|
||||||
|
@ -50,7 +50,7 @@ type Redirect struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal tests for equality between two Redirect types
|
// Equal tests for equality between two Redirect types
|
||||||
func (r1 *Redirect) Equal(r2 *Redirect) bool {
|
func (r1 *Config) Equal(r2 *Config) bool {
|
||||||
if r1 == r2 {
|
if r1 == r2 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ func (a rewrite) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
abu, _ := parser.GetBoolAnnotation(addBaseURL, ing)
|
abu, _ := parser.GetBoolAnnotation(addBaseURL, ing)
|
||||||
bus, _ := parser.GetStringAnnotation(baseURLScheme, ing)
|
bus, _ := parser.GetStringAnnotation(baseURLScheme, ing)
|
||||||
ar, _ := parser.GetStringAnnotation(appRoot, ing)
|
ar, _ := parser.GetStringAnnotation(appRoot, ing)
|
||||||
return &Redirect{
|
return &Config{
|
||||||
Target: rt,
|
Target: rt,
|
||||||
AddBaseURL: abu,
|
AddBaseURL: abu,
|
||||||
BaseURLScheme: bus,
|
BaseURLScheme: bus,
|
||||||
|
|
|
@ -93,7 +93,7 @@ func TestRedirect(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error with ingress: %v", err)
|
t.Errorf("Unexpected error with ingress: %v", err)
|
||||||
}
|
}
|
||||||
redirect, ok := i.(*Redirect)
|
redirect, ok := i.(*Config)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected a Redirect type")
|
t.Errorf("expected a Redirect type")
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ func TestSSLRedirect(t *testing.T) {
|
||||||
ing.SetAnnotations(data)
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
i, _ := NewParser(mockBackend{true}).Parse(ing)
|
i, _ := NewParser(mockBackend{true}).Parse(ing)
|
||||||
redirect, ok := i.(*Redirect)
|
redirect, ok := i.(*Config)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected a Redirect type")
|
t.Errorf("expected a Redirect type")
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ func TestSSLRedirect(t *testing.T) {
|
||||||
ing.SetAnnotations(data)
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
i, _ = NewParser(mockBackend{false}).Parse(ing)
|
i, _ = NewParser(mockBackend{false}).Parse(ing)
|
||||||
redirect, ok = i.(*Redirect)
|
redirect, ok = i.(*Config)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected a Redirect type")
|
t.Errorf("expected a Redirect type")
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ func TestForceSSLRedirect(t *testing.T) {
|
||||||
ing.SetAnnotations(data)
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
i, _ := NewParser(mockBackend{true}).Parse(ing)
|
i, _ := NewParser(mockBackend{true}).Parse(ing)
|
||||||
redirect, ok := i.(*Redirect)
|
redirect, ok := i.(*Config)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected a Redirect type")
|
t.Errorf("expected a Redirect type")
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ func TestForceSSLRedirect(t *testing.T) {
|
||||||
ing.SetAnnotations(data)
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
i, _ = NewParser(mockBackend{false}).Parse(ing)
|
i, _ = NewParser(mockBackend{false}).Parse(ing)
|
||||||
redirect, ok = i.(*Redirect)
|
redirect, ok = i.(*Config)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected a Redirect type")
|
t.Errorf("expected a Redirect type")
|
||||||
}
|
}
|
||||||
|
@ -167,12 +167,11 @@ func TestAppRoot(t *testing.T) {
|
||||||
ing.SetAnnotations(data)
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
i, _ := NewParser(mockBackend{true}).Parse(ing)
|
i, _ := NewParser(mockBackend{true}).Parse(ing)
|
||||||
redirect, ok := i.(*Redirect)
|
redirect, ok := i.(*Config)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected a App Context")
|
t.Errorf("expected a App Context")
|
||||||
}
|
}
|
||||||
if redirect.AppRoot != "/app1" {
|
if redirect.AppRoot != "/app1" {
|
||||||
t.Errorf("Unexpected value got in AppRoot")
|
t.Errorf("Unexpected value got in AppRoot")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,8 @@ const (
|
||||||
secureVerifyCASecret = "ingress.kubernetes.io/secure-verify-ca-secret"
|
secureVerifyCASecret = "ingress.kubernetes.io/secure-verify-ca-secret"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Secure describes SSL backend configuration
|
// Config describes SSL backend configuration
|
||||||
type Secure struct {
|
type Config struct {
|
||||||
Secure bool `json:"secure"`
|
Secure bool `json:"secure"`
|
||||||
CACert resolver.AuthSSLCert `json:"caCert"`
|
CACert resolver.AuthSSLCert `json:"caCert"`
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ func NewParser(resolver resolver.AuthCertificate) parser.IngressAnnotation {
|
||||||
func (a su) Parse(ing *extensions.Ingress) (interface{}, error) {
|
func (a su) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
s, _ := parser.GetBoolAnnotation(secureUpstream, ing)
|
s, _ := parser.GetBoolAnnotation(secureUpstream, ing)
|
||||||
ca, _ := parser.GetStringAnnotation(secureVerifyCASecret, ing)
|
ca, _ := parser.GetStringAnnotation(secureVerifyCASecret, ing)
|
||||||
secure := &Secure{
|
secure := &Config{
|
||||||
Secure: s,
|
Secure: s,
|
||||||
CACert: resolver.AuthSSLCert{},
|
CACert: resolver.AuthSSLCert{},
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ func (a su) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
if caCert == nil {
|
if caCert == nil {
|
||||||
return secure, nil
|
return secure, nil
|
||||||
}
|
}
|
||||||
return &Secure{
|
return &Config{
|
||||||
Secure: s,
|
Secure: s,
|
||||||
CACert: *caCert,
|
CACert: *caCert,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
|
@ -17,14 +17,13 @@ limitations under the License.
|
||||||
package secureupstream
|
package secureupstream
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
api "k8s.io/api/core/v1"
|
api "k8s.io/api/core/v1"
|
||||||
extensions "k8s.io/api/extensions/v1beta1"
|
extensions "k8s.io/api/extensions/v1beta1"
|
||||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/resolver"
|
"k8s.io/ingress-nginx/pkg/ingress/resolver"
|
||||||
)
|
)
|
||||||
|
|
|
@ -42,24 +42,24 @@ var (
|
||||||
affinityCookieHashRegex = regexp.MustCompile(`^(index|md5|sha1)$`)
|
affinityCookieHashRegex = regexp.MustCompile(`^(index|md5|sha1)$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// AffinityConfig describes the per ingress session affinity config
|
// Config describes the per ingress session affinity config
|
||||||
type AffinityConfig struct {
|
type Config struct {
|
||||||
// The type of affinity that will be used
|
// The type of affinity that will be used
|
||||||
AffinityType string `json:"type"`
|
Type string `json:"type"`
|
||||||
CookieConfig
|
Cookie
|
||||||
}
|
}
|
||||||
|
|
||||||
// CookieConfig describes the Config of cookie type affinity
|
// Cookie describes the Config of cookie type affinity
|
||||||
type CookieConfig struct {
|
type Cookie struct {
|
||||||
// The name of the cookie that will be used in case of cookie affinity type.
|
// The name of the cookie that will be used in case of cookie affinity type.
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// The hash that will be used to encode the cookie in case of cookie affinity type
|
// The hash that will be used to encode the cookie in case of cookie affinity type
|
||||||
Hash string `json:"hash"`
|
Hash string `json:"hash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 CookieAffinityParse(ing *extensions.Ingress) *CookieConfig {
|
func cookieAffinityParse(ing *extensions.Ingress) *Cookie {
|
||||||
|
|
||||||
sn, err := parser.GetStringAnnotation(annotationAffinityCookieName, ing)
|
sn, err := parser.GetStringAnnotation(annotationAffinityCookieName, ing)
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ func CookieAffinityParse(ing *extensions.Ingress) *CookieConfig {
|
||||||
sh = defaultAffinityCookieHash
|
sh = defaultAffinityCookieHash
|
||||||
}
|
}
|
||||||
|
|
||||||
return &CookieConfig{
|
return &Cookie{
|
||||||
Name: sn,
|
Name: sn,
|
||||||
Hash: sh,
|
Hash: sh,
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ type affinity struct {
|
||||||
// ParseAnnotations parses the annotations contained in the ingress
|
// ParseAnnotations parses the annotations contained in the ingress
|
||||||
// rule used to configure the affinity directives
|
// rule used to configure the affinity directives
|
||||||
func (a affinity) Parse(ing *extensions.Ingress) (interface{}, error) {
|
func (a affinity) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
cookieAffinityConfig := &CookieConfig{}
|
cookie := &Cookie{}
|
||||||
// Check the type of affinity that will be used
|
// Check the type of affinity that will be used
|
||||||
at, err := parser.GetStringAnnotation(annotationAffinityType, ing)
|
at, err := parser.GetStringAnnotation(annotationAffinityType, ing)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -101,15 +101,14 @@ func (a affinity) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
|
|
||||||
switch at {
|
switch at {
|
||||||
case "cookie":
|
case "cookie":
|
||||||
cookieAffinityConfig = CookieAffinityParse(ing)
|
cookie = cookieAffinityParse(ing)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
glog.V(3).Infof("No default affinity was found for Ingress %v", ing.Name)
|
glog.V(3).Infof("No default affinity was found for Ingress %v", ing.Name)
|
||||||
|
|
||||||
}
|
}
|
||||||
return &AffinityConfig{
|
|
||||||
AffinityType: at,
|
|
||||||
CookieConfig: *cookieAffinityConfig,
|
|
||||||
}, nil
|
|
||||||
|
|
||||||
|
return &Config{
|
||||||
|
Type: at,
|
||||||
|
Cookie: *cookie,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,20 +70,20 @@ func TestIngressAffinityCookieConfig(t *testing.T) {
|
||||||
ing.SetAnnotations(data)
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
affin, _ := NewParser().Parse(ing)
|
affin, _ := NewParser().Parse(ing)
|
||||||
nginxAffinity, ok := affin.(*AffinityConfig)
|
nginxAffinity, ok := affin.(*Config)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected a Config type")
|
t.Errorf("expected a Config type")
|
||||||
}
|
}
|
||||||
|
|
||||||
if nginxAffinity.AffinityType != "cookie" {
|
if nginxAffinity.Type != "cookie" {
|
||||||
t.Errorf("expected cookie as sticky-type but returned %v", nginxAffinity.AffinityType)
|
t.Errorf("expected cookie as sticky-type but returned %v", nginxAffinity.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
if nginxAffinity.CookieConfig.Hash != "md5" {
|
if nginxAffinity.Cookie.Hash != "md5" {
|
||||||
t.Errorf("expected md5 as sticky-hash but returned %v", nginxAffinity.CookieConfig.Hash)
|
t.Errorf("expected md5 as sticky-hash but returned %v", nginxAffinity.Cookie.Hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
if nginxAffinity.CookieConfig.Name != "INGRESSCOOKIE" {
|
if nginxAffinity.Cookie.Name != "INGRESSCOOKIE" {
|
||||||
t.Errorf("expected route as sticky-name but returned %v", nginxAffinity.CookieConfig.Name)
|
t.Errorf("expected route as sticky-name but returned %v", nginxAffinity.Cookie.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ import (
|
||||||
|
|
||||||
apiv1 "k8s.io/api/core/v1"
|
apiv1 "k8s.io/api/core/v1"
|
||||||
extensions "k8s.io/api/extensions/v1beta1"
|
extensions "k8s.io/api/extensions/v1beta1"
|
||||||
"k8s.io/client-go/tools/cache"
|
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress"
|
"k8s.io/ingress-nginx/pkg/ingress"
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/class"
|
"k8s.io/ingress-nginx/pkg/ingress/annotations/class"
|
||||||
|
@ -156,18 +155,3 @@ func (ic *NGINXController) checkMissingSecrets() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sslCertTracker holds a store of referenced Secrets in Ingress rules
|
|
||||||
type sslCertTracker struct {
|
|
||||||
cache.ThreadSafeStore
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSSLCertTracker() *sslCertTracker {
|
|
||||||
return &sslCertTracker{
|
|
||||||
cache.NewThreadSafeStore(cache.Indexers{}, cache.Indices{}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *sslCertTracker) DeleteAll(key string) {
|
|
||||||
s.Delete(key)
|
|
||||||
}
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ import (
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress"
|
"k8s.io/ingress-nginx/pkg/ingress"
|
||||||
|
"k8s.io/ingress-nginx/pkg/ingress/annotations"
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/class"
|
"k8s.io/ingress-nginx/pkg/ingress/annotations/class"
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/healthcheck"
|
"k8s.io/ingress-nginx/pkg/ingress/annotations/healthcheck"
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/parser"
|
"k8s.io/ingress-nginx/pkg/ingress/annotations/parser"
|
||||||
|
@ -316,7 +317,7 @@ func (n *NGINXController) getStreamServices(configmapName string, proto apiv1.Pr
|
||||||
for _, sp := range svc.Spec.Ports {
|
for _, sp := range svc.Spec.Ports {
|
||||||
if sp.Name == svcPort {
|
if sp.Name == svcPort {
|
||||||
if sp.Protocol == proto {
|
if sp.Protocol == proto {
|
||||||
endps = n.getEndpoints(svc, &sp, proto, &healthcheck.Upstream{})
|
endps = n.getEndpoints(svc, &sp, proto, &healthcheck.Config{})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,7 +328,7 @@ func (n *NGINXController) getStreamServices(configmapName string, proto apiv1.Pr
|
||||||
for _, sp := range svc.Spec.Ports {
|
for _, sp := range svc.Spec.Ports {
|
||||||
if sp.Port == int32(targetPort) {
|
if sp.Port == int32(targetPort) {
|
||||||
if sp.Protocol == proto {
|
if sp.Protocol == proto {
|
||||||
endps = n.getEndpoints(svc, &sp, proto, &healthcheck.Upstream{})
|
endps = n.getEndpoints(svc, &sp, proto, &healthcheck.Config{})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,7 +380,7 @@ func (n *NGINXController) getDefaultUpstream() *ingress.Backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
svc := svcObj.(*apiv1.Service)
|
svc := svcObj.(*apiv1.Service)
|
||||||
endps := n.getEndpoints(svc, &svc.Spec.Ports[0], apiv1.ProtocolTCP, &healthcheck.Upstream{})
|
endps := n.getEndpoints(svc, &svc.Spec.Ports[0], apiv1.ProtocolTCP, &healthcheck.Config{})
|
||||||
if len(endps) == 0 {
|
if len(endps) == 0 {
|
||||||
glog.Warningf("service %v does not have any active endpoints", svcKey)
|
glog.Warningf("service %v does not have any active endpoints", svcKey)
|
||||||
endps = []ingress.Endpoint{n.DefaultEndpoint()}
|
endps = []ingress.Endpoint{n.DefaultEndpoint()}
|
||||||
|
@ -398,8 +399,7 @@ func (n *NGINXController) getBackendServers(ingresses []*extensions.Ingress) ([]
|
||||||
servers := n.createServers(ingresses, upstreams, du)
|
servers := n.createServers(ingresses, upstreams, du)
|
||||||
|
|
||||||
for _, ing := range ingresses {
|
for _, ing := range ingresses {
|
||||||
affinity := n.annotations.SessionAffinity(ing)
|
anns := n.getIngressAnnotations(ing)
|
||||||
anns := n.annotations.Extract(ing)
|
|
||||||
|
|
||||||
for _, rule := range ing.Spec.Rules {
|
for _, rule := range ing.Spec.Rules {
|
||||||
host := rule.Host
|
host := rule.Host
|
||||||
|
@ -418,13 +418,11 @@ func (n *NGINXController) getBackendServers(ingresses []*extensions.Ingress) ([]
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.CertificateAuth.CAFileName == "" {
|
if server.CertificateAuth.CAFileName == "" {
|
||||||
ca := n.annotations.CertificateAuth(ing)
|
server.CertificateAuth = anns.CertificateAuth
|
||||||
if ca != nil {
|
// It is possible that no CAFileName is found in the secret
|
||||||
server.CertificateAuth = *ca
|
if server.CertificateAuth.CAFileName == "" {
|
||||||
// It is possible that no CAFileName is found in the secret
|
glog.V(3).Infof("secret %v does not contain 'ca.crt', mutual authentication not enabled - ingress rule %v/%v.", server.CertificateAuth.Secret, ing.Namespace, ing.Name)
|
||||||
if server.CertificateAuth.CAFileName == "" {
|
|
||||||
glog.V(3).Infof("secret %v does not contain 'ca.crt', mutual authentication not enabled - ingress rule %v/%v.", server.CertificateAuth.Secret, ing.Namespace, ing.Name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
glog.V(3).Infof("server %v already contains a mutual authentication configuration - ingress rule %v/%v", server.Hostname, ing.Namespace, ing.Name)
|
glog.V(3).Infof("server %v already contains a mutual authentication configuration - ingress rule %v/%v", server.Hostname, ing.Namespace, ing.Name)
|
||||||
|
@ -461,7 +459,19 @@ func (n *NGINXController) getBackendServers(ingresses []*extensions.Ingress) ([]
|
||||||
loc.Port = ups.Port
|
loc.Port = ups.Port
|
||||||
loc.Service = ups.Service
|
loc.Service = ups.Service
|
||||||
loc.Ingress = ing
|
loc.Ingress = ing
|
||||||
mergeLocationAnnotations(loc, anns)
|
loc.BasicDigestAuth = anns.BasicDigestAuth
|
||||||
|
loc.ClientBodyBufferSize = anns.ClientBodyBufferSize
|
||||||
|
loc.ConfigurationSnippet = anns.ConfigurationSnippet
|
||||||
|
loc.CorsConfig = anns.CorsConfig
|
||||||
|
loc.ExternalAuth = anns.ExternalAuth
|
||||||
|
loc.Proxy = anns.Proxy
|
||||||
|
loc.RateLimit = anns.RateLimit
|
||||||
|
loc.Redirect = anns.Redirect
|
||||||
|
loc.Rewrite = anns.Rewrite
|
||||||
|
loc.UpstreamVhost = anns.UpstreamVhost
|
||||||
|
loc.VtsFilterKey = anns.VtsFilterKey
|
||||||
|
loc.Whitelist = anns.Whitelist
|
||||||
|
|
||||||
if loc.Redirect.FromToWWW {
|
if loc.Redirect.FromToWWW {
|
||||||
server.RedirectFromToWWW = true
|
server.RedirectFromToWWW = true
|
||||||
}
|
}
|
||||||
|
@ -472,14 +482,26 @@ func (n *NGINXController) getBackendServers(ingresses []*extensions.Ingress) ([]
|
||||||
if addLoc {
|
if addLoc {
|
||||||
glog.V(3).Infof("adding location %v in ingress rule %v/%v upstream %v", nginxPath, ing.Namespace, ing.Name, ups.Name)
|
glog.V(3).Infof("adding location %v in ingress rule %v/%v upstream %v", nginxPath, ing.Namespace, ing.Name, ups.Name)
|
||||||
loc := &ingress.Location{
|
loc := &ingress.Location{
|
||||||
Path: nginxPath,
|
Path: nginxPath,
|
||||||
Backend: ups.Name,
|
Backend: ups.Name,
|
||||||
IsDefBackend: false,
|
IsDefBackend: false,
|
||||||
Service: ups.Service,
|
Service: ups.Service,
|
||||||
Port: ups.Port,
|
Port: ups.Port,
|
||||||
Ingress: ing,
|
Ingress: ing,
|
||||||
|
BasicDigestAuth: anns.BasicDigestAuth,
|
||||||
|
ClientBodyBufferSize: anns.ClientBodyBufferSize,
|
||||||
|
ConfigurationSnippet: anns.ConfigurationSnippet,
|
||||||
|
CorsConfig: anns.CorsConfig,
|
||||||
|
ExternalAuth: anns.ExternalAuth,
|
||||||
|
Proxy: anns.Proxy,
|
||||||
|
RateLimit: anns.RateLimit,
|
||||||
|
Redirect: anns.Redirect,
|
||||||
|
Rewrite: anns.Rewrite,
|
||||||
|
UpstreamVhost: anns.UpstreamVhost,
|
||||||
|
VtsFilterKey: anns.VtsFilterKey,
|
||||||
|
Whitelist: anns.Whitelist,
|
||||||
}
|
}
|
||||||
mergeLocationAnnotations(loc, anns)
|
|
||||||
if loc.Redirect.FromToWWW {
|
if loc.Redirect.FromToWWW {
|
||||||
server.RedirectFromToWWW = true
|
server.RedirectFromToWWW = true
|
||||||
}
|
}
|
||||||
|
@ -487,12 +509,12 @@ func (n *NGINXController) getBackendServers(ingresses []*extensions.Ingress) ([]
|
||||||
}
|
}
|
||||||
|
|
||||||
if ups.SessionAffinity.AffinityType == "" {
|
if ups.SessionAffinity.AffinityType == "" {
|
||||||
ups.SessionAffinity.AffinityType = affinity.AffinityType
|
ups.SessionAffinity.AffinityType = anns.SessionAffinity.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
if affinity.AffinityType == "cookie" {
|
if anns.SessionAffinity.Type == "cookie" {
|
||||||
ups.SessionAffinity.CookieSessionAffinity.Name = affinity.CookieConfig.Name
|
ups.SessionAffinity.CookieSessionAffinity.Name = anns.SessionAffinity.Cookie.Name
|
||||||
ups.SessionAffinity.CookieSessionAffinity.Hash = affinity.CookieConfig.Hash
|
ups.SessionAffinity.CookieSessionAffinity.Hash = anns.SessionAffinity.Cookie.Hash
|
||||||
|
|
||||||
locs := ups.SessionAffinity.CookieSessionAffinity.Locations
|
locs := ups.SessionAffinity.CookieSessionAffinity.Locations
|
||||||
if _, ok := locs[host]; !ok {
|
if _, ok := locs[host]; !ok {
|
||||||
|
@ -519,7 +541,7 @@ func (n *NGINXController) getBackendServers(ingresses []*extensions.Ingress) ([]
|
||||||
// check if the location contains endpoints and a custom default backend
|
// check if the location contains endpoints and a custom default backend
|
||||||
if location.DefaultBackend != nil {
|
if location.DefaultBackend != nil {
|
||||||
sp := location.DefaultBackend.Spec.Ports[0]
|
sp := location.DefaultBackend.Spec.Ports[0]
|
||||||
endps := n.getEndpoints(location.DefaultBackend, &sp, apiv1.ProtocolTCP, &healthcheck.Upstream{})
|
endps := n.getEndpoints(location.DefaultBackend, &sp, apiv1.ProtocolTCP, &healthcheck.Config{})
|
||||||
if len(endps) > 0 {
|
if len(endps) > 0 {
|
||||||
glog.V(3).Infof("using custom default backend in server %v location %v (service %v/%v)",
|
glog.V(3).Infof("using custom default backend in server %v location %v (service %v/%v)",
|
||||||
server.Hostname, location.Path, location.DefaultBackend.Namespace, location.DefaultBackend.Name)
|
server.Hostname, location.Path, location.DefaultBackend.Namespace, location.DefaultBackend.Name)
|
||||||
|
@ -617,10 +639,7 @@ func (n *NGINXController) createUpstreams(data []*extensions.Ingress, du *ingres
|
||||||
upstreams[defUpstreamName] = du
|
upstreams[defUpstreamName] = du
|
||||||
|
|
||||||
for _, ing := range data {
|
for _, ing := range data {
|
||||||
secUpstream := n.annotations.SecureUpstream(ing)
|
anns := n.getIngressAnnotations(ing)
|
||||||
hz := n.annotations.HealthCheck(ing)
|
|
||||||
serviceUpstream := n.annotations.ServiceUpstream(ing)
|
|
||||||
upstreamHashBy := n.annotations.UpstreamHashBy(ing)
|
|
||||||
|
|
||||||
var defBackend string
|
var defBackend string
|
||||||
if ing.Spec.Backend != nil {
|
if ing.Spec.Backend != nil {
|
||||||
|
@ -635,7 +654,7 @@ func (n *NGINXController) createUpstreams(data []*extensions.Ingress, du *ingres
|
||||||
|
|
||||||
// Add the service cluster endpoint as the upstream instead of individual endpoints
|
// Add the service cluster endpoint as the upstream instead of individual endpoints
|
||||||
// if the serviceUpstream annotation is enabled
|
// if the serviceUpstream annotation is enabled
|
||||||
if serviceUpstream {
|
if anns.ServiceUpstream {
|
||||||
endpoint, err := n.getServiceClusterEndpoint(svcKey, ing.Spec.Backend)
|
endpoint, err := n.getServiceClusterEndpoint(svcKey, ing.Spec.Backend)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to get service cluster endpoint for service %s: %v", svcKey, err)
|
glog.Errorf("Failed to get service cluster endpoint for service %s: %v", svcKey, err)
|
||||||
|
@ -645,7 +664,7 @@ func (n *NGINXController) createUpstreams(data []*extensions.Ingress, du *ingres
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(upstreams[defBackend].Endpoints) == 0 {
|
if len(upstreams[defBackend].Endpoints) == 0 {
|
||||||
endps, err := n.serviceEndpoints(svcKey, ing.Spec.Backend.ServicePort.String(), hz)
|
endps, err := n.serviceEndpoints(svcKey, ing.Spec.Backend.ServicePort.String(), &anns.HealthCheck)
|
||||||
upstreams[defBackend].Endpoints = append(upstreams[defBackend].Endpoints, endps...)
|
upstreams[defBackend].Endpoints = append(upstreams[defBackend].Endpoints, endps...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Warningf("error creating upstream %v: %v", defBackend, err)
|
glog.Warningf("error creating upstream %v: %v", defBackend, err)
|
||||||
|
@ -674,22 +693,22 @@ func (n *NGINXController) createUpstreams(data []*extensions.Ingress, du *ingres
|
||||||
upstreams[name].Port = path.Backend.ServicePort
|
upstreams[name].Port = path.Backend.ServicePort
|
||||||
|
|
||||||
if !upstreams[name].Secure {
|
if !upstreams[name].Secure {
|
||||||
upstreams[name].Secure = secUpstream.Secure
|
upstreams[name].Secure = anns.SecureUpstream.Secure
|
||||||
}
|
}
|
||||||
|
|
||||||
if upstreams[name].SecureCACert.Secret == "" {
|
if upstreams[name].SecureCACert.Secret == "" {
|
||||||
upstreams[name].SecureCACert = secUpstream.CACert
|
upstreams[name].SecureCACert = anns.SecureUpstream.CACert
|
||||||
}
|
}
|
||||||
|
|
||||||
if upstreams[name].UpstreamHashBy == "" {
|
if upstreams[name].UpstreamHashBy == "" {
|
||||||
upstreams[name].UpstreamHashBy = upstreamHashBy
|
upstreams[name].UpstreamHashBy = anns.UpstreamHashBy
|
||||||
}
|
}
|
||||||
|
|
||||||
svcKey := fmt.Sprintf("%v/%v", ing.GetNamespace(), path.Backend.ServiceName)
|
svcKey := fmt.Sprintf("%v/%v", ing.GetNamespace(), path.Backend.ServiceName)
|
||||||
|
|
||||||
// Add the service cluster endpoint as the upstream instead of individual endpoints
|
// Add the service cluster endpoint as the upstream instead of individual endpoints
|
||||||
// if the serviceUpstream annotation is enabled
|
// if the serviceUpstream annotation is enabled
|
||||||
if serviceUpstream {
|
if anns.ServiceUpstream {
|
||||||
endpoint, err := n.getServiceClusterEndpoint(svcKey, &path.Backend)
|
endpoint, err := n.getServiceClusterEndpoint(svcKey, &path.Backend)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("failed to get service cluster endpoint for service %s: %v", svcKey, err)
|
glog.Errorf("failed to get service cluster endpoint for service %s: %v", svcKey, err)
|
||||||
|
@ -699,7 +718,7 @@ func (n *NGINXController) createUpstreams(data []*extensions.Ingress, du *ingres
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(upstreams[name].Endpoints) == 0 {
|
if len(upstreams[name].Endpoints) == 0 {
|
||||||
endp, err := n.serviceEndpoints(svcKey, path.Backend.ServicePort.String(), hz)
|
endp, err := n.serviceEndpoints(svcKey, path.Backend.ServicePort.String(), &anns.HealthCheck)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Warningf("error obtaining service endpoints: %v", err)
|
glog.Warningf("error obtaining service endpoints: %v", err)
|
||||||
continue
|
continue
|
||||||
|
@ -759,7 +778,7 @@ func (n *NGINXController) getServiceClusterEndpoint(svcKey string, backend *exte
|
||||||
// serviceEndpoints returns the upstream servers (endpoints) associated
|
// serviceEndpoints returns the upstream servers (endpoints) associated
|
||||||
// to a service.
|
// to a service.
|
||||||
func (n *NGINXController) serviceEndpoints(svcKey, backendPort string,
|
func (n *NGINXController) serviceEndpoints(svcKey, backendPort string,
|
||||||
hz *healthcheck.Upstream) ([]ingress.Endpoint, error) {
|
hz *healthcheck.Config) ([]ingress.Endpoint, error) {
|
||||||
svc, err := n.listers.Service.GetByName(svcKey)
|
svc, err := n.listers.Service.GetByName(svcKey)
|
||||||
|
|
||||||
var upstreams []ingress.Endpoint
|
var upstreams []ingress.Endpoint
|
||||||
|
@ -843,7 +862,7 @@ func (n *NGINXController) createServers(data []*extensions.Ingress,
|
||||||
aliases := make(map[string]string, len(data))
|
aliases := make(map[string]string, len(data))
|
||||||
|
|
||||||
bdef := n.GetDefaultBackend()
|
bdef := n.GetDefaultBackend()
|
||||||
ngxProxy := proxy.Configuration{
|
ngxProxy := proxy.Config{
|
||||||
BodySize: bdef.ProxyBodySize,
|
BodySize: bdef.ProxyBodySize,
|
||||||
ConnectTimeout: bdef.ProxyConnectTimeout,
|
ConnectTimeout: bdef.ProxyConnectTimeout,
|
||||||
SendTimeout: bdef.ProxySendTimeout,
|
SendTimeout: bdef.ProxySendTimeout,
|
||||||
|
@ -884,9 +903,7 @@ func (n *NGINXController) createServers(data []*extensions.Ingress,
|
||||||
|
|
||||||
// initialize all the servers
|
// initialize all the servers
|
||||||
for _, ing := range data {
|
for _, ing := range data {
|
||||||
|
anns := n.getIngressAnnotations(ing)
|
||||||
// check if ssl passthrough is configured
|
|
||||||
sslpt := n.annotations.SSLPassthrough(ing)
|
|
||||||
|
|
||||||
// default upstream server
|
// default upstream server
|
||||||
un := du.Name
|
un := du.Name
|
||||||
|
@ -930,16 +947,14 @@ func (n *NGINXController) createServers(data []*extensions.Ingress,
|
||||||
Service: &apiv1.Service{},
|
Service: &apiv1.Service{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
SSLPassthrough: sslpt,
|
SSLPassthrough: anns.SSLPassthrough,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// configure default location, alias, and SSL
|
// configure default location, alias, and SSL
|
||||||
for _, ing := range data {
|
for _, ing := range data {
|
||||||
// setup server-alias based on annotations
|
anns := n.getIngressAnnotations(ing)
|
||||||
aliasAnnotation := n.annotations.Alias(ing)
|
|
||||||
srvsnippet := n.annotations.ServerSnippet(ing)
|
|
||||||
|
|
||||||
for _, rule := range ing.Spec.Rules {
|
for _, rule := range ing.Spec.Rules {
|
||||||
host := rule.Host
|
host := rule.Host
|
||||||
|
@ -948,11 +963,11 @@ func (n *NGINXController) createServers(data []*extensions.Ingress,
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup server aliases
|
// setup server aliases
|
||||||
if aliasAnnotation != "" {
|
if anns.Alias != "" {
|
||||||
if servers[host].Alias == "" {
|
if servers[host].Alias == "" {
|
||||||
servers[host].Alias = aliasAnnotation
|
servers[host].Alias = anns.Alias
|
||||||
if _, ok := aliases[aliasAnnotation]; !ok {
|
if _, ok := aliases["Alias"]; !ok {
|
||||||
aliases[aliasAnnotation] = host
|
aliases["Alias"] = host
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
glog.Warningf("ingress %v/%v for host %v contains an Alias but one has already been configured.",
|
glog.Warningf("ingress %v/%v for host %v contains an Alias but one has already been configured.",
|
||||||
|
@ -961,14 +976,14 @@ func (n *NGINXController) createServers(data []*extensions.Ingress,
|
||||||
}
|
}
|
||||||
|
|
||||||
//notifying the user that it has already been configured.
|
//notifying the user that it has already been configured.
|
||||||
if servers[host].ServerSnippet != "" && srvsnippet != "" {
|
if servers[host].ServerSnippet != "" && anns.ServerSnippet != "" {
|
||||||
glog.Warningf("ingress %v/%v for host %v contains a Server Snippet section that it has already been configured.",
|
glog.Warningf("ingress %v/%v for host %v contains a Server Snippet section that it has already been configured.",
|
||||||
ing.Namespace, ing.Name, host)
|
ing.Namespace, ing.Name, host)
|
||||||
}
|
}
|
||||||
|
|
||||||
// only add a server snippet if the server does not have one previously configured
|
// only add a server snippet if the server does not have one previously configured
|
||||||
if servers[host].ServerSnippet == "" && srvsnippet != "" {
|
if servers[host].ServerSnippet == "" && anns.ServerSnippet != "" {
|
||||||
servers[host].ServerSnippet = srvsnippet
|
servers[host].ServerSnippet = anns.ServerSnippet
|
||||||
}
|
}
|
||||||
|
|
||||||
// only add a certificate if the server does not have one previously configured
|
// only add a certificate if the server does not have one previously configured
|
||||||
|
@ -1044,7 +1059,7 @@ func (n *NGINXController) getEndpoints(
|
||||||
s *apiv1.Service,
|
s *apiv1.Service,
|
||||||
servicePort *apiv1.ServicePort,
|
servicePort *apiv1.ServicePort,
|
||||||
proto apiv1.Protocol,
|
proto apiv1.Protocol,
|
||||||
hz *healthcheck.Upstream) []ingress.Endpoint {
|
hz *healthcheck.Config) []ingress.Endpoint {
|
||||||
|
|
||||||
upsServers := []ingress.Endpoint{}
|
upsServers := []ingress.Endpoint{}
|
||||||
|
|
||||||
|
@ -1152,6 +1167,7 @@ func (n *NGINXController) isForceReload() bool {
|
||||||
return atomic.LoadInt32(&n.forceReload) != 0
|
return atomic.LoadInt32(&n.forceReload) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetForceReload sets if the ingress controller should be reloaded or not
|
||||||
func (n *NGINXController) SetForceReload(shouldReload bool) {
|
func (n *NGINXController) SetForceReload(shouldReload bool) {
|
||||||
if shouldReload {
|
if shouldReload {
|
||||||
atomic.StoreInt32(&n.forceReload, 1)
|
atomic.StoreInt32(&n.forceReload, 1)
|
||||||
|
@ -1160,3 +1176,24 @@ func (n *NGINXController) SetForceReload(shouldReload bool) {
|
||||||
atomic.StoreInt32(&n.forceReload, 0)
|
atomic.StoreInt32(&n.forceReload, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *NGINXController) extractAnnotations(ing *extensions.Ingress) {
|
||||||
|
anns := n.annotations.Extract(ing)
|
||||||
|
glog.V(3).Infof("updating annotations information for ingres %v/%v", anns.Namespace, anns.Name)
|
||||||
|
n.listers.IngressAnnotation.Update(anns)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getByIngress returns the parsed annotations from an Ingress
|
||||||
|
func (n *NGINXController) getIngressAnnotations(ing *extensions.Ingress) *annotations.Ingress {
|
||||||
|
key := fmt.Sprintf("%v/%v", ing.Namespace, ing.Name)
|
||||||
|
item, exists, err := n.listers.IngressAnnotation.GetByKey(key)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("unexpected error getting ingress annotation %v: %v", key, err)
|
||||||
|
return &annotations.Ingress{}
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
glog.Errorf("ingress annotation %v was not found", key)
|
||||||
|
return &annotations.Ingress{}
|
||||||
|
}
|
||||||
|
return item.(*annotations.Ingress)
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
"k8s.io/apimachinery/pkg/util/runtime"
|
"k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
|
cache_client "k8s.io/client-go/tools/cache"
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress"
|
"k8s.io/ingress-nginx/pkg/ingress"
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/class"
|
"k8s.io/ingress-nginx/pkg/ingress/annotations/class"
|
||||||
|
@ -60,7 +61,7 @@ func (c *cacheController) Run(stopCh chan struct{}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *NGINXController) createListers(stopCh chan struct{}) *ingress.StoreLister {
|
func (n *NGINXController) createListers(stopCh chan struct{}) (*ingress.StoreLister, *cacheController) {
|
||||||
// from here to the end of the method all the code is just boilerplate
|
// from here to the end of the method all the code is just boilerplate
|
||||||
// required to watch Ingress, Secrets, ConfigMaps and Endoints.
|
// required to watch Ingress, Secrets, ConfigMaps and Endoints.
|
||||||
// This is used to detect new content, updates or removals and act accordingly
|
// This is used to detect new content, updates or removals and act accordingly
|
||||||
|
@ -73,6 +74,7 @@ func (n *NGINXController) createListers(stopCh chan struct{}) *ingress.StoreList
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n.extractAnnotations(addIng)
|
||||||
n.recorder.Eventf(addIng, apiv1.EventTypeNormal, "CREATE", fmt.Sprintf("Ingress %s/%s", addIng.Namespace, addIng.Name))
|
n.recorder.Eventf(addIng, apiv1.EventTypeNormal, "CREATE", fmt.Sprintf("Ingress %s/%s", addIng.Namespace, addIng.Name))
|
||||||
n.syncQueue.Enqueue(obj)
|
n.syncQueue.Enqueue(obj)
|
||||||
},
|
},
|
||||||
|
@ -113,6 +115,7 @@ func (n *NGINXController) createListers(stopCh chan struct{}) *ingress.StoreList
|
||||||
n.recorder.Eventf(curIng, apiv1.EventTypeNormal, "UPDATE", fmt.Sprintf("Ingress %s/%s", curIng.Namespace, curIng.Name))
|
n.recorder.Eventf(curIng, apiv1.EventTypeNormal, "UPDATE", fmt.Sprintf("Ingress %s/%s", curIng.Namespace, curIng.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n.extractAnnotations(curIng)
|
||||||
n.syncQueue.Enqueue(cur)
|
n.syncQueue.Enqueue(cur)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -141,7 +144,7 @@ func (n *NGINXController) createListers(stopCh chan struct{}) *ingress.StoreList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
key := fmt.Sprintf("%v/%v", sec.Namespace, sec.Name)
|
key := fmt.Sprintf("%v/%v", sec.Namespace, sec.Name)
|
||||||
n.sslCertTracker.DeleteAll(key)
|
n.sslCertTracker.Delete(key)
|
||||||
n.syncQueue.Enqueue(key)
|
n.syncQueue.Enqueue(key)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -196,6 +199,7 @@ func (n *NGINXController) createListers(stopCh chan struct{}) *ingress.StoreList
|
||||||
}
|
}
|
||||||
|
|
||||||
lister := &ingress.StoreLister{}
|
lister := &ingress.StoreLister{}
|
||||||
|
lister.IngressAnnotation.Store = cache_client.NewStore(cache_client.DeletionHandlingMetaNamespaceKeyFunc)
|
||||||
|
|
||||||
controller := &cacheController{}
|
controller := &cacheController{}
|
||||||
|
|
||||||
|
@ -219,7 +223,5 @@ func (n *NGINXController) createListers(stopCh chan struct{}) *ingress.StoreList
|
||||||
cache.NewListWatchFromClient(n.cfg.Client.CoreV1().RESTClient(), "services", n.cfg.Namespace, fields.Everything()),
|
cache.NewListWatchFromClient(n.cfg.Client.CoreV1().RESTClient(), "services", n.cfg.Namespace, fields.Everything()),
|
||||||
&apiv1.Service{}, n.cfg.ResyncPeriod, cache.ResourceEventHandlerFuncs{})
|
&apiv1.Service{}, n.cfg.ResyncPeriod, cache.ResourceEventHandlerFuncs{})
|
||||||
|
|
||||||
controller.Run(n.stopCh)
|
return lister, controller
|
||||||
|
|
||||||
return lister
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/util/filesystem"
|
"k8s.io/kubernetes/pkg/util/filesystem"
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress"
|
"k8s.io/ingress-nginx/pkg/ingress"
|
||||||
|
"k8s.io/ingress-nginx/pkg/ingress/annotations"
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/class"
|
"k8s.io/ingress-nginx/pkg/ingress/annotations/class"
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/parser"
|
"k8s.io/ingress-nginx/pkg/ingress/annotations/parser"
|
||||||
ngx_config "k8s.io/ingress-nginx/pkg/ingress/controller/config"
|
ngx_config "k8s.io/ingress-nginx/pkg/ingress/controller/config"
|
||||||
|
@ -50,6 +51,7 @@ import (
|
||||||
ngx_template "k8s.io/ingress-nginx/pkg/ingress/controller/template"
|
ngx_template "k8s.io/ingress-nginx/pkg/ingress/controller/template"
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/defaults"
|
"k8s.io/ingress-nginx/pkg/ingress/defaults"
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/status"
|
"k8s.io/ingress-nginx/pkg/ingress/status"
|
||||||
|
"k8s.io/ingress-nginx/pkg/ingress/store"
|
||||||
ing_net "k8s.io/ingress-nginx/pkg/net"
|
ing_net "k8s.io/ingress-nginx/pkg/net"
|
||||||
"k8s.io/ingress-nginx/pkg/net/dns"
|
"k8s.io/ingress-nginx/pkg/net/dns"
|
||||||
"k8s.io/ingress-nginx/pkg/net/ssl"
|
"k8s.io/ingress-nginx/pkg/net/ssl"
|
||||||
|
@ -102,7 +104,7 @@ func NewNGINXController(config *Configuration) *NGINXController {
|
||||||
|
|
||||||
resolver: h,
|
resolver: h,
|
||||||
cfg: config,
|
cfg: config,
|
||||||
sslCertTracker: newSSLCertTracker(),
|
sslCertTracker: store.NewSSLCertTracker(),
|
||||||
syncRateLimiter: flowcontrol.NewTokenBucketRateLimiter(0.3, 1),
|
syncRateLimiter: flowcontrol.NewTokenBucketRateLimiter(0.3, 1),
|
||||||
|
|
||||||
recorder: eventBroadcaster.NewRecorder(scheme.Scheme, apiv1.EventSource{
|
recorder: eventBroadcaster.NewRecorder(scheme.Scheme, apiv1.EventSource{
|
||||||
|
@ -115,11 +117,13 @@ func NewNGINXController(config *Configuration) *NGINXController {
|
||||||
fileSystem: filesystem.DefaultFs{},
|
fileSystem: filesystem.DefaultFs{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n.listers, n.controllers = n.createListers(n.stopCh)
|
||||||
|
|
||||||
n.stats = newStatsCollector(config.Namespace, config.IngressClass, n.binary, n.cfg.ListenPorts.Status)
|
n.stats = newStatsCollector(config.Namespace, config.IngressClass, n.binary, n.cfg.ListenPorts.Status)
|
||||||
|
|
||||||
n.syncQueue = task.NewTaskQueue(n.syncIngress)
|
n.syncQueue = task.NewTaskQueue(n.syncIngress)
|
||||||
|
|
||||||
n.listers = n.createListers(n.stopCh)
|
n.annotations = annotations.NewAnnotationExtractor(n)
|
||||||
|
|
||||||
if config.UpdateStatus {
|
if config.UpdateStatus {
|
||||||
n.syncStatus = status.NewStatusSyncer(status.Config{
|
n.syncStatus = status.NewStatusSyncer(status.Config{
|
||||||
|
@ -135,7 +139,6 @@ func NewNGINXController(config *Configuration) *NGINXController {
|
||||||
} else {
|
} else {
|
||||||
glog.Warning("Update of ingress status is disabled (flag --update-status=false was specified)")
|
glog.Warning("Update of ingress status is disabled (flag --update-status=false was specified)")
|
||||||
}
|
}
|
||||||
n.annotations = newAnnotationExtractor(n)
|
|
||||||
|
|
||||||
var onChange func()
|
var onChange func()
|
||||||
onChange = func() {
|
onChange = func() {
|
||||||
|
@ -170,9 +173,10 @@ Error loading new template : %v
|
||||||
type NGINXController struct {
|
type NGINXController struct {
|
||||||
cfg *Configuration
|
cfg *Configuration
|
||||||
|
|
||||||
listers *ingress.StoreLister
|
listers *ingress.StoreLister
|
||||||
|
controllers *cacheController
|
||||||
|
|
||||||
annotations annotationExtractor
|
annotations annotations.Extractor
|
||||||
|
|
||||||
recorder record.EventRecorder
|
recorder record.EventRecorder
|
||||||
|
|
||||||
|
@ -182,7 +186,7 @@ type NGINXController struct {
|
||||||
|
|
||||||
// local store of SSL certificates
|
// local store of SSL certificates
|
||||||
// (only certificates used in ingress)
|
// (only certificates used in ingress)
|
||||||
sslCertTracker *sslCertTracker
|
sslCertTracker *store.SSLCertTracker
|
||||||
|
|
||||||
syncRateLimiter flowcontrol.RateLimiter
|
syncRateLimiter flowcontrol.RateLimiter
|
||||||
|
|
||||||
|
@ -234,6 +238,8 @@ type NGINXController struct {
|
||||||
func (n *NGINXController) Start() {
|
func (n *NGINXController) Start() {
|
||||||
glog.Infof("starting Ingress controller")
|
glog.Infof("starting Ingress controller")
|
||||||
|
|
||||||
|
n.controllers.Run(n.stopCh)
|
||||||
|
|
||||||
// initial sync of secrets to avoid unnecessary reloads
|
// initial sync of secrets to avoid unnecessary reloads
|
||||||
glog.Info("running initial sync of secrets")
|
glog.Info("running initial sync of secrets")
|
||||||
for _, obj := range n.listers.Ingress.List() {
|
for _, obj := range n.listers.Ingress.List() {
|
||||||
|
@ -425,12 +431,12 @@ func (n *NGINXController) SetConfig(cmap *apiv1.ConfigMap) {
|
||||||
n.backendDefaults = c.Backend
|
n.backendDefaults = c.Backend
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnUpdate is called by syncQueue in https://github.com/kubernetes/ingress-nginx/blob/master/pkg/ingress/controller/controller.go#L426
|
// OnUpdate is called periodically by syncQueue to keep the configuration in sync.
|
||||||
// periodically to keep the configuration in sync.
|
//
|
||||||
|
// 1. converts configmap configuration to custom configuration object
|
||||||
|
// 2. write the custom template (the complexity depends on the implementation)
|
||||||
|
// 3. write the configuration file
|
||||||
//
|
//
|
||||||
// convert configmap to custom configuration object (different in each implementation)
|
|
||||||
// write the custom template (the complexity depends on the implementation)
|
|
||||||
// write the configuration file
|
|
||||||
// returning nill implies the backend will be reloaded.
|
// returning nill implies the backend will be reloaded.
|
||||||
// if an error is returned means requeue the update
|
// if an error is returned means requeue the update
|
||||||
func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error {
|
func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error {
|
||||||
|
|
|
@ -354,8 +354,8 @@ func buildProxyPass(host string, b interface{}, loc interface{}) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Needs Unit Tests
|
// TODO: Needs Unit Tests
|
||||||
func filterRateLimits(input interface{}) []ratelimit.RateLimit {
|
func filterRateLimits(input interface{}) []ratelimit.Config {
|
||||||
ratelimits := []ratelimit.RateLimit{}
|
ratelimits := []ratelimit.Config{}
|
||||||
found := sets.String{}
|
found := sets.String{}
|
||||||
|
|
||||||
servers, ok := input.([]*ingress.Server)
|
servers, ok := input.([]*ingress.Server)
|
||||||
|
|
|
@ -114,7 +114,7 @@ func TestBuildLocation(t *testing.T) {
|
||||||
for k, tc := range tmplFuncTestcases {
|
for k, tc := range tmplFuncTestcases {
|
||||||
loc := &ingress.Location{
|
loc := &ingress.Location{
|
||||||
Path: tc.Path,
|
Path: tc.Path,
|
||||||
Rewrite: rewrite.Redirect{Target: tc.Target, AddBaseURL: tc.AddBaseURL},
|
Rewrite: rewrite.Config{Target: tc.Target, AddBaseURL: tc.AddBaseURL},
|
||||||
}
|
}
|
||||||
|
|
||||||
newLoc := buildLocation(loc)
|
newLoc := buildLocation(loc)
|
||||||
|
@ -128,7 +128,7 @@ func TestBuildProxyPass(t *testing.T) {
|
||||||
for k, tc := range tmplFuncTestcases {
|
for k, tc := range tmplFuncTestcases {
|
||||||
loc := &ingress.Location{
|
loc := &ingress.Location{
|
||||||
Path: tc.Path,
|
Path: tc.Path,
|
||||||
Rewrite: rewrite.Redirect{Target: tc.Target, AddBaseURL: tc.AddBaseURL, BaseURLScheme: tc.BaseURLScheme},
|
Rewrite: rewrite.Config{Target: tc.Target, AddBaseURL: tc.AddBaseURL, BaseURLScheme: tc.BaseURLScheme},
|
||||||
Backend: "upstream-name",
|
Backend: "upstream-name",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ func TestBuildProxyPass(t *testing.T) {
|
||||||
|
|
||||||
func TestBuildAuthResponseHeaders(t *testing.T) {
|
func TestBuildAuthResponseHeaders(t *testing.T) {
|
||||||
loc := &ingress.Location{
|
loc := &ingress.Location{
|
||||||
ExternalAuth: authreq.External{ResponseHeaders: []string{"h1", "H-With-Caps-And-Dashes"}},
|
ExternalAuth: authreq.Config{ResponseHeaders: []string{"h1", "H-With-Caps-And-Dashes"}},
|
||||||
}
|
}
|
||||||
headers := buildAuthResponseHeaders(loc)
|
headers := buildAuthResponseHeaders(loc)
|
||||||
expected := []string{
|
expected := []string{
|
||||||
|
|
|
@ -21,17 +21,12 @@ import (
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
"github.com/imdario/mergo"
|
|
||||||
|
|
||||||
api "k8s.io/api/core/v1"
|
api "k8s.io/api/core/v1"
|
||||||
"k8s.io/kubernetes/pkg/util/sysctl"
|
"k8s.io/kubernetes/pkg/util/sysctl"
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress"
|
"k8s.io/ingress-nginx/pkg/ingress"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeniedKeyName name of the key that contains the reason to deny a location
|
|
||||||
const DeniedKeyName = "Denied"
|
|
||||||
|
|
||||||
// newUpstream creates an upstream without servers.
|
// newUpstream creates an upstream without servers.
|
||||||
func newUpstream(name string) *ingress.Backend {
|
func newUpstream(name string) *ingress.Backend {
|
||||||
return &ingress.Backend{
|
return &ingress.Backend{
|
||||||
|
@ -46,17 +41,6 @@ func newUpstream(name string) *ingress.Backend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mergeLocationAnnotations(loc *ingress.Location, anns map[string]interface{}) {
|
|
||||||
if _, ok := anns[DeniedKeyName]; ok {
|
|
||||||
loc.Denied = anns[DeniedKeyName].(error)
|
|
||||||
}
|
|
||||||
delete(anns, DeniedKeyName)
|
|
||||||
err := mergo.Map(loc, anns)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("unexpected error merging extracted annotations in location type: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sysctlSomaxconn returns the value of net.core.somaxconn, i.e.
|
// sysctlSomaxconn returns the value of net.core.somaxconn, i.e.
|
||||||
// maximum number of connections that can be queued for acceptance
|
// maximum number of connections that can be queued for acceptance
|
||||||
// http://nginx.org/en/docs/http/ngx_http_core_module.html#listen
|
// http://nginx.org/en/docs/http/ngx_http_core_module.html#listen
|
||||||
|
|
|
@ -17,18 +17,7 @@ limitations under the License.
|
||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress"
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/auth"
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/authreq"
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/cors"
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/ipwhitelist"
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/proxy"
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/ratelimit"
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/redirect"
|
|
||||||
"k8s.io/ingress-nginx/pkg/ingress/annotations/rewrite"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type fakeError struct{}
|
type fakeError struct{}
|
||||||
|
@ -37,51 +26,6 @@ func (fe *fakeError) Error() string {
|
||||||
return "fakeError"
|
return "fakeError"
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMergeLocationAnnotations(t *testing.T) {
|
|
||||||
// initial parameters
|
|
||||||
loc := ingress.Location{}
|
|
||||||
annotations := map[string]interface{}{
|
|
||||||
"Path": "/checkpath",
|
|
||||||
"IsDefBackend": true,
|
|
||||||
"Backend": "foo_backend",
|
|
||||||
"BasicDigestAuth": auth.BasicDigest{},
|
|
||||||
DeniedKeyName: &fakeError{},
|
|
||||||
"CorsConfig": cors.CorsConfig{},
|
|
||||||
"ExternalAuth": authreq.External{},
|
|
||||||
"RateLimit": ratelimit.RateLimit{},
|
|
||||||
"Redirect": redirect.Redirect{},
|
|
||||||
"Rewrite": rewrite.Redirect{},
|
|
||||||
"Whitelist": ipwhitelist.SourceRange{},
|
|
||||||
"Proxy": proxy.Configuration{},
|
|
||||||
"UsePortInRedirects": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// create test table
|
|
||||||
type fooMergeLocationAnnotationsStruct struct {
|
|
||||||
fName string
|
|
||||||
er interface{}
|
|
||||||
}
|
|
||||||
fooTests := []fooMergeLocationAnnotationsStruct{}
|
|
||||||
for name, value := range annotations {
|
|
||||||
fva := fooMergeLocationAnnotationsStruct{name, value}
|
|
||||||
fooTests = append(fooTests, fva)
|
|
||||||
}
|
|
||||||
|
|
||||||
// execute test
|
|
||||||
mergeLocationAnnotations(&loc, annotations)
|
|
||||||
|
|
||||||
// check result
|
|
||||||
for _, foo := range fooTests {
|
|
||||||
fv := reflect.ValueOf(loc).FieldByName(foo.fName).Interface()
|
|
||||||
if !reflect.DeepEqual(fv, foo.er) {
|
|
||||||
t.Errorf("Returned %v but expected %v for the field %s", fv, foo.er, foo.fName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if _, ok := annotations[DeniedKeyName]; ok {
|
|
||||||
t.Errorf("%s should be removed after mergeLocationAnnotations", DeniedKeyName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntInSlice(t *testing.T) {
|
func TestIntInSlice(t *testing.T) {
|
||||||
fooTests := []struct {
|
fooTests := []struct {
|
||||||
i int
|
i int
|
||||||
|
|
|
@ -28,6 +28,11 @@ type IngressLister struct {
|
||||||
cache.Store
|
cache.Store
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IngressAnnotationsLister makes a Store that lists annotations in Ingress rules.
|
||||||
|
type IngressAnnotationsLister struct {
|
||||||
|
cache.Store
|
||||||
|
}
|
||||||
|
|
||||||
// SecretLister makes a Store that lists Secrets.
|
// SecretLister makes a Store that lists Secrets.
|
||||||
type SecretLister struct {
|
type SecretLister struct {
|
||||||
cache.Store
|
cache.Store
|
||||||
|
@ -94,3 +99,15 @@ func (s *EndpointLister) GetServiceEndpoints(svc *apiv1.Service) (*apiv1.Endpoin
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("could not find endpoints for service: %v", svc.Name)
|
return nil, fmt.Errorf("could not find endpoints for service: %v", svc.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SSLCertTracker holds a store of referenced Secrets in Ingress rules
|
||||||
|
type SSLCertTracker struct {
|
||||||
|
cache.ThreadSafeStore
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSSLCertTracker creates a new SSLCertTracker store
|
||||||
|
func NewSSLCertTracker() *SSLCertTracker {
|
||||||
|
return &SSLCertTracker{
|
||||||
|
cache.NewThreadSafeStore(cache.Indexers{}, cache.Indices{}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -47,11 +47,12 @@ var (
|
||||||
// StoreLister returns the configured stores for ingresses, services,
|
// StoreLister returns the configured stores for ingresses, services,
|
||||||
// endpoints, secrets and configmaps.
|
// endpoints, secrets and configmaps.
|
||||||
type StoreLister struct {
|
type StoreLister struct {
|
||||||
Ingress store.IngressLister
|
Ingress store.IngressLister
|
||||||
Service store.ServiceLister
|
Service store.ServiceLister
|
||||||
Endpoint store.EndpointLister
|
Endpoint store.EndpointLister
|
||||||
Secret store.SecretLister
|
Secret store.SecretLister
|
||||||
ConfigMap store.ConfigMapLister
|
ConfigMap store.ConfigMapLister
|
||||||
|
IngressAnnotation store.IngressAnnotationsLister
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configuration holds the definition of all the parts required to describe all
|
// Configuration holds the definition of all the parts required to describe all
|
||||||
|
@ -165,7 +166,7 @@ type Server struct {
|
||||||
RedirectFromToWWW bool `json:"redirectFromToWWW,omitempty"`
|
RedirectFromToWWW bool `json:"redirectFromToWWW,omitempty"`
|
||||||
// CertificateAuth indicates the this server requires mutual authentication
|
// CertificateAuth indicates the this server requires mutual authentication
|
||||||
// +optional
|
// +optional
|
||||||
CertificateAuth authtls.AuthSSLConfig `json:"certificateAuth"`
|
CertificateAuth authtls.Config `json:"certificateAuth"`
|
||||||
|
|
||||||
// ServerSnippet returns the snippet of server
|
// ServerSnippet returns the snippet of server
|
||||||
// +optional
|
// +optional
|
||||||
|
@ -211,28 +212,28 @@ type Location struct {
|
||||||
// BasicDigestAuth returns authentication configuration for
|
// BasicDigestAuth returns authentication configuration for
|
||||||
// an Ingress rule.
|
// an Ingress rule.
|
||||||
// +optional
|
// +optional
|
||||||
BasicDigestAuth auth.BasicDigest `json:"basicDigestAuth,omitempty"`
|
BasicDigestAuth auth.Config `json:"basicDigestAuth,omitempty"`
|
||||||
// Denied returns an error when this location cannot not be allowed
|
// Denied returns an error when this location cannot not be allowed
|
||||||
// Requesting a denied location should return HTTP code 403.
|
// Requesting a denied location should return HTTP code 403.
|
||||||
Denied error `json:"denied,omitempty"`
|
Denied error `json:"denied,omitempty"`
|
||||||
// CorsConfig returns the Cors Configration for the ingress rule
|
// CorsConfig returns the Cors Configration for the ingress rule
|
||||||
// +optional
|
// +optional
|
||||||
CorsConfig cors.CorsConfig `json:"corsConfig,omitempty"`
|
CorsConfig cors.Config `json:"corsConfig,omitempty"`
|
||||||
// ExternalAuth indicates the access to this location requires
|
// ExternalAuth indicates the access to this location requires
|
||||||
// authentication using an external provider
|
// authentication using an external provider
|
||||||
// +optional
|
// +optional
|
||||||
ExternalAuth authreq.External `json:"externalAuth,omitempty"`
|
ExternalAuth authreq.Config `json:"externalAuth,omitempty"`
|
||||||
// RateLimit describes a limit in the number of connections per IP
|
// RateLimit describes a limit in the number of connections per IP
|
||||||
// address or connections per second.
|
// address or connections per second.
|
||||||
// The Redirect annotation precedes RateLimit
|
// The Redirect annotation precedes RateLimit
|
||||||
// +optional
|
// +optional
|
||||||
RateLimit ratelimit.RateLimit `json:"rateLimit,omitempty"`
|
RateLimit ratelimit.Config `json:"rateLimit,omitempty"`
|
||||||
// Redirect describes a temporal o permanent redirection this location.
|
// Redirect describes a temporal o permanent redirection this location.
|
||||||
// +optional
|
// +optional
|
||||||
Redirect redirect.Redirect `json:"redirect,omitempty"`
|
Redirect redirect.Config `json:"redirect,omitempty"`
|
||||||
// Rewrite describes the redirection this location.
|
// Rewrite describes the redirection this location.
|
||||||
// +optional
|
// +optional
|
||||||
Rewrite rewrite.Redirect `json:"rewrite,omitempty"`
|
Rewrite rewrite.Config `json:"rewrite,omitempty"`
|
||||||
// Whitelist indicates only connections from certain client
|
// Whitelist indicates only connections from certain client
|
||||||
// addresses or networks are allowed.
|
// addresses or networks are allowed.
|
||||||
// +optional
|
// +optional
|
||||||
|
@ -240,7 +241,7 @@ type Location struct {
|
||||||
// Proxy contains information about timeouts and buffer sizes
|
// Proxy contains information about timeouts and buffer sizes
|
||||||
// to be used in connections against endpoints
|
// to be used in connections against endpoints
|
||||||
// +optional
|
// +optional
|
||||||
Proxy proxy.Configuration `json:"proxy,omitempty"`
|
Proxy proxy.Config `json:"proxy,omitempty"`
|
||||||
// UsePortInRedirects indicates if redirects must specify the port
|
// UsePortInRedirects indicates if redirects must specify the port
|
||||||
// +optional
|
// +optional
|
||||||
UsePortInRedirects bool `json:"usePortInRedirects"`
|
UsePortInRedirects bool `json:"usePortInRedirects"`
|
||||||
|
|
Loading…
Reference in a new issue