Fix IngressClass logic for newer releases (#7341)
* Fix IngressClass logic for newer releases Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@gmail.com> * Change e2e tests for the new IngressClass presence * Fix chart and admission tests Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@gmail.com> * Fix helm chart test Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@gmail.com> * Fix reviews * Remove ingressclass code from admission
This commit is contained in:
parent
0d57e87819
commit
cef147a24d
68 changed files with 1450 additions and 637 deletions
|
|
@ -41,14 +41,13 @@ import (
|
|||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/file"
|
||||
"k8s.io/ingress-nginx/internal/ingress"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/class"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
ngx_config "k8s.io/ingress-nginx/internal/ingress/controller/config"
|
||||
"k8s.io/ingress-nginx/internal/ingress/controller/ingressclass"
|
||||
ngx_template "k8s.io/ingress-nginx/internal/ingress/controller/template"
|
||||
"k8s.io/ingress-nginx/internal/ingress/defaults"
|
||||
"k8s.io/ingress-nginx/internal/ingress/errors"
|
||||
|
|
@ -121,16 +120,18 @@ type Event struct {
|
|||
|
||||
// Informer defines the required SharedIndexInformers that interact with the API server.
|
||||
type Informer struct {
|
||||
Ingress cache.SharedIndexInformer
|
||||
Endpoint cache.SharedIndexInformer
|
||||
Service cache.SharedIndexInformer
|
||||
Secret cache.SharedIndexInformer
|
||||
ConfigMap cache.SharedIndexInformer
|
||||
Ingress cache.SharedIndexInformer
|
||||
IngressClass cache.SharedIndexInformer
|
||||
Endpoint cache.SharedIndexInformer
|
||||
Service cache.SharedIndexInformer
|
||||
Secret cache.SharedIndexInformer
|
||||
ConfigMap cache.SharedIndexInformer
|
||||
}
|
||||
|
||||
// Lister contains object listers (stores).
|
||||
type Lister struct {
|
||||
Ingress IngressLister
|
||||
IngressClass IngressClassLister
|
||||
Service ServiceLister
|
||||
Endpoint EndpointLister
|
||||
Secret SecretLister
|
||||
|
|
@ -150,6 +151,7 @@ func (e NotExistsError) Error() string {
|
|||
func (i *Informer) Run(stopCh chan struct{}) {
|
||||
go i.Secret.Run(stopCh)
|
||||
go i.Endpoint.Run(stopCh)
|
||||
go i.IngressClass.Run(stopCh)
|
||||
go i.Service.Run(stopCh)
|
||||
go i.ConfigMap.Run(stopCh)
|
||||
|
||||
|
|
@ -157,6 +159,7 @@ func (i *Informer) Run(stopCh chan struct{}) {
|
|||
// from the queue
|
||||
if !cache.WaitForCacheSync(stopCh,
|
||||
i.Endpoint.HasSynced,
|
||||
i.IngressClass.HasSynced,
|
||||
i.Service.HasSynced,
|
||||
i.Secret.HasSynced,
|
||||
i.ConfigMap.HasSynced,
|
||||
|
|
@ -221,7 +224,8 @@ func New(
|
|||
resyncPeriod time.Duration,
|
||||
client clientset.Interface,
|
||||
updateCh *channels.RingChannel,
|
||||
disableCatchAll bool) Storer {
|
||||
disableCatchAll bool,
|
||||
icConfig *ingressclass.IngressClassConfiguration) Storer {
|
||||
|
||||
store := &k8sStore{
|
||||
informers: &Informer{},
|
||||
|
|
@ -296,6 +300,9 @@ func New(
|
|||
store.informers.Ingress = infFactory.Networking().V1().Ingresses().Informer()
|
||||
store.listers.Ingress.Store = store.informers.Ingress.GetStore()
|
||||
|
||||
store.informers.IngressClass = infFactory.Networking().V1().IngressClasses().Informer()
|
||||
store.listers.IngressClass.Store = cache.NewStore(cache.MetaNamespaceKeyFunc)
|
||||
|
||||
store.informers.Endpoint = infFactory.Core().V1().Endpoints().Informer()
|
||||
store.listers.Endpoint.Store = store.informers.Endpoint.GetStore()
|
||||
|
||||
|
|
@ -324,7 +331,9 @@ func New(
|
|||
}
|
||||
}
|
||||
|
||||
if !class.IsValid(ing) {
|
||||
_, err := store.GetIngressClass(ing, icConfig)
|
||||
if err != nil {
|
||||
klog.InfoS("Ignoring ingress because of error while validating ingress class", "ingress", klog.KObj(ing), "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -347,12 +356,14 @@ func New(
|
|||
ingEventHandler := cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
ing, _ := toIngress(obj)
|
||||
if !class.IsValid(ing) {
|
||||
ingressClass, _ := parser.GetStringAnnotation(class.IngressKey, ing)
|
||||
klog.InfoS("Ignoring ingress", "ingress", klog.KObj(ing), "kubernetes.io/ingress.class", ingressClass, "ingressClassName", pointer.StringPtrDerefOr(ing.Spec.IngressClassName, ""))
|
||||
ic, err := store.GetIngressClass(ing, icConfig)
|
||||
if err != nil {
|
||||
klog.InfoS("Ignoring ingress because of error while validating ingress class", "ingress", klog.KObj(ing), "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
klog.InfoS("Found valid IngressClass", "ingress", klog.KObj(ing), "ingressclass", ic)
|
||||
|
||||
if hasCatchAllIngressRule(ing.Spec) && disableCatchAll {
|
||||
klog.InfoS("Ignoring add for catch-all ingress because of --disable-catch-all", "ingress", klog.KObj(ing))
|
||||
return
|
||||
|
|
@ -374,21 +385,21 @@ func New(
|
|||
oldIng, _ := toIngress(old)
|
||||
curIng, _ := toIngress(cur)
|
||||
|
||||
validOld := class.IsValid(oldIng)
|
||||
validCur := class.IsValid(curIng)
|
||||
if !validOld && validCur {
|
||||
_, errOld := store.GetIngressClass(oldIng, icConfig)
|
||||
classCur, errCur := store.GetIngressClass(curIng, icConfig)
|
||||
if errOld != nil && errCur == nil {
|
||||
if hasCatchAllIngressRule(curIng.Spec) && disableCatchAll {
|
||||
klog.InfoS("ignoring update for catch-all ingress because of --disable-catch-all", "ingress", klog.KObj(curIng))
|
||||
return
|
||||
}
|
||||
|
||||
klog.InfoS("creating ingress", "ingress", klog.KObj(curIng), "class", class.IngressKey)
|
||||
klog.InfoS("creating ingress", "ingress", klog.KObj(curIng), "ingressclass", classCur)
|
||||
recorder.Eventf(curIng, corev1.EventTypeNormal, "Sync", "Scheduled for sync")
|
||||
} else if validOld && !validCur {
|
||||
klog.InfoS("removing ingress", "ingress", klog.KObj(curIng), "class", class.IngressKey)
|
||||
} else if errOld == nil && errCur != nil {
|
||||
klog.InfoS("removing ingress because of unknown ingressclass", "ingress", klog.KObj(curIng))
|
||||
ingDeleteHandler(old)
|
||||
return
|
||||
} else if validCur && !reflect.DeepEqual(old, cur) {
|
||||
} else if errCur == nil && !reflect.DeepEqual(old, cur) {
|
||||
if hasCatchAllIngressRule(curIng.Spec) && disableCatchAll {
|
||||
klog.InfoS("ignoring update for catch-all ingress and delete old one because of --disable-catch-all", "ingress", klog.KObj(curIng))
|
||||
ingDeleteHandler(old)
|
||||
|
|
@ -412,6 +423,63 @@ func New(
|
|||
},
|
||||
}
|
||||
|
||||
ingressClassEventHandler := cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
ingressclass := obj.(*networkingv1.IngressClass)
|
||||
if ingressclass.Spec.Controller != icConfig.Controller {
|
||||
klog.InfoS("ignoring ingressclass as the spec.controller is not the same of this ingress", "ingressclass", klog.KObj(ingressclass))
|
||||
return
|
||||
}
|
||||
err := store.listers.IngressClass.Add(ingressclass)
|
||||
if err != nil {
|
||||
klog.InfoS("error adding ingressclass to store", "ingressclass", klog.KObj(ingressclass), "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
updateCh.In() <- Event{
|
||||
Type: CreateEvent,
|
||||
Obj: obj,
|
||||
}
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
ingressclass := obj.(*networkingv1.IngressClass)
|
||||
if ingressclass.Spec.Controller != icConfig.Controller {
|
||||
klog.InfoS("ignoring ingressclass as the spec.controller is not the same of this ingress", "ingressclass", klog.KObj(ingressclass))
|
||||
return
|
||||
}
|
||||
err := store.listers.IngressClass.Delete(ingressclass)
|
||||
if err != nil {
|
||||
klog.InfoS("error removing ingressclass from store", "ingressclass", klog.KObj(ingressclass), "error", err)
|
||||
return
|
||||
}
|
||||
updateCh.In() <- Event{
|
||||
Type: DeleteEvent,
|
||||
Obj: obj,
|
||||
}
|
||||
},
|
||||
UpdateFunc: func(old, cur interface{}) {
|
||||
oic := old.(*networkingv1.IngressClass)
|
||||
cic := cur.(*networkingv1.IngressClass)
|
||||
if cic.Spec.Controller != icConfig.Controller {
|
||||
klog.InfoS("ignoring ingressclass as the spec.controller is not the same of this ingress", "ingressclass", klog.KObj(cic))
|
||||
return
|
||||
}
|
||||
// TODO: In a future we might be interested in parse parameters and use as
|
||||
// current IngressClass for this case, crossing with configmap
|
||||
if !reflect.DeepEqual(cic.Spec.Parameters, oic.Spec.Parameters) {
|
||||
err := store.listers.IngressClass.Update(cic)
|
||||
if err != nil {
|
||||
klog.InfoS("error updating ingressclass in store", "ingressclass", klog.KObj(cic), "error", err)
|
||||
return
|
||||
}
|
||||
updateCh.In() <- Event{
|
||||
Type: UpdateEvent,
|
||||
Obj: cur,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
secrEventHandler := cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
sec := obj.(*corev1.Secret)
|
||||
|
|
@ -608,6 +676,7 @@ func New(
|
|||
}
|
||||
|
||||
store.informers.Ingress.AddEventHandler(ingEventHandler)
|
||||
store.informers.IngressClass.AddEventHandler(ingressClassEventHandler)
|
||||
store.informers.Endpoint.AddEventHandler(epEventHandler)
|
||||
store.informers.Secret.AddEventHandler(secrEventHandler)
|
||||
store.informers.ConfigMap.AddEventHandler(cmEventHandler)
|
||||
|
|
@ -758,6 +827,32 @@ func (s *k8sStore) GetService(key string) (*corev1.Service, error) {
|
|||
return s.listers.Service.ByKey(key)
|
||||
}
|
||||
|
||||
func (s *k8sStore) GetIngressClass(ing *networkingv1.Ingress, icConfig *ingressclass.IngressClassConfiguration) (string, error) {
|
||||
// First we try ingressClassName
|
||||
if ing.Spec.IngressClassName != nil {
|
||||
iclass, err := s.listers.IngressClass.ByKey(*ing.Spec.IngressClassName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return iclass.Name, nil
|
||||
}
|
||||
|
||||
// Then we try annotation
|
||||
if ingressclass, ok := ing.GetAnnotations()[ingressclass.IngressKey]; ok {
|
||||
if ingressclass != icConfig.AnnotationValue {
|
||||
return "", fmt.Errorf("ingress class annotation is not equal to the expected by Ingress Controller")
|
||||
}
|
||||
return ingressclass, nil
|
||||
}
|
||||
|
||||
// Then we accept if the WithoutClass is enabled
|
||||
if icConfig.WatchWithoutClass {
|
||||
// Reserving "_" as a "wildcard" name
|
||||
return "_", nil
|
||||
}
|
||||
return "", fmt.Errorf("ingress does not contain a valid IngressClass")
|
||||
}
|
||||
|
||||
// getIngress returns the Ingress matching key.
|
||||
func (s *k8sStore) getIngress(key string) (*networkingv1.Ingress, error) {
|
||||
ing, err := s.listers.IngressWithAnnotation.ByKey(key)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue