Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal/Feature add flag --skip-empty-annotation to honor only annotated resources. #664

Merged
merged 10 commits into from
Jul 7, 2020
10 changes: 7 additions & 3 deletions cli/ingress-controller/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ type cliConfig struct {
KongCustomEntitiesSecret string

// Resource filtering
WatchNamespace string
IngressClass string
ElectionID string
WatchNamespace string
SkipClasslessIngressV1beta1 bool
IngressClass string
ElectionID string

// Ingress Status publish resource
PublishService string
Expand Down Expand Up @@ -175,6 +176,8 @@ mode of Kong. Takes the form of namespace/name.`)
// Resource filtering
flags.String("watch-namespace", apiv1.NamespaceAll,
`Namespace to watch for Ingress. Default is to watch all namespaces`)
flags.Bool("skip-classless-ingress-v1beta1", false,
`Skip non annotated Ingresses and Kong CRDs.`)
flags.String("ingress-class", annotations.DefaultIngressClass,
`Name of the ingress class to route through this controller.`)
flags.String("election-id", "ingress-controller-leader",
Expand Down Expand Up @@ -320,6 +323,7 @@ func parseFlags() (cliConfig, error) {

// Resource filtering
config.WatchNamespace = viper.GetString("watch-namespace")
config.SkipClasslessIngressV1beta1 = viper.GetBool("skip-classless-ingress-v1beta1")
config.IngressClass = viper.GetString("ingress-class")
config.ElectionID = viper.GetString("election-id")

Expand Down
8 changes: 5 additions & 3 deletions cli/ingress-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,10 @@ func main() {
var synced []cache.InformerSynced
updateChannel := channels.NewRingChannel(1024)
reh := controller.ResourceEventHandler{
UpdateCh: updateChannel,
IsValidIngresClass: annotations.IngressClassValidatorFunc(cliConfig.IngressClass),
UpdateCh: updateChannel,
IsValidIngresClass: annotations.IngressClassValidatorFunc(
cliConfig.IngressClass,
cliConfig.SkipClasslessIngressV1beta1),
}
var informers []cache.SharedIndexInformer
var cacheStores store.CacheStores
Expand Down Expand Up @@ -366,7 +368,7 @@ func main() {
runtime.HandleError(fmt.Errorf("Timed out waiting for caches to sync"))
}

store := store.New(cacheStores, cliConfig.IngressClass)
store := store.New(cacheStores, cliConfig.IngressClass, cliConfig.SkipClasslessIngressV1beta1)
kong, err := controller.NewKongController(&controllerConfig, updateChannel,
store)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cli/ingress-controller/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func TestHandleSigterm(t *testing.T) {
KubeClient: kubeClient,
},
channels.NewRingChannel(1024),
store.New(store.CacheStores{}, conf.IngressClass),
store.New(store.CacheStores{}, conf.IngressClass, conf.SkipClasslessIngressV1beta1),
)

exitCh := make(chan int, 1)
Expand Down
12 changes: 6 additions & 6 deletions internal/ingress/annotations/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ const (
DefaultIngressClass = "kong"
)

func validIngress(ingressAnnotationValue, ingressClass string) bool {
func validIngress(ingressAnnotationValue, ingressClass string, skipClasslessIngress bool) bool {
// we have 2 valid combinations
// 1 - ingress with default class | blank annotation on ingress
// 2 - ingress with specific class | same annotation on ingress
//
// and 2 invalid combinations
// 3 - ingress with default class | fixed annotation on ingress
// 4 - ingress with specific class | different annotation on ingress
if ingressAnnotationValue == "" && ingressClass == DefaultIngressClass {
if ingressAnnotationValue == "" && !skipClasslessIngress && ingressClass == DefaultIngressClass {
return true
}
return ingressAnnotationValue == ingressClass
Expand All @@ -66,22 +66,22 @@ func validIngress(ingressAnnotationValue, ingressClass string) bool {
// IngressClassValidatorFunc returns a function which can validate if an Object
// belongs to an the ingressClass or not.
func IngressClassValidatorFunc(
ingressClass string) func(obj metav1.Object) bool {
ingressClass string, skipClasslessIngress bool) func(obj metav1.Object) bool {

return func(obj metav1.Object) bool {
ingress := obj.GetAnnotations()[ingressClassKey]
return validIngress(ingress, ingressClass)
return validIngress(ingress, ingressClass, skipClasslessIngress)
}
}

// IngressClassValidatorFuncFromObjectMeta returns a function which
// can validate if an ObjectMeta belongs to an the ingressClass or not.
func IngressClassValidatorFuncFromObjectMeta(
ingressClass string) func(obj *metav1.ObjectMeta) bool {
ingressClass string, skipClasslessIngress bool) func(obj *metav1.ObjectMeta) bool {

return func(obj *metav1.ObjectMeta) bool {
ingress := obj.GetAnnotations()[ingressClassKey]
return validIngress(ingress, ingressClass)
return validIngress(ingress, ingressClass, skipClasslessIngress)
}
}

Expand Down
25 changes: 15 additions & 10 deletions internal/ingress/annotations/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,21 @@ import (

func TestIngressClassValidatorFunc(t *testing.T) {
tests := []struct {
ingress string
controller string
isValid bool
ingress string
skipClasslessIngress bool
controller string
isValid bool
}{
{"", "", true},
{"", "kong", true},
{"kong", "kong", true},
{"custom", "custom", true},
{"", "killer", false},
{"custom", "kong", false},
{"", false, "", true},
{"", false, "kong", true},
{"", true, "kong", false},
{"kong", false, "kong", true},
{"kong", true, "kong", true},
{"custom", false, "custom", true},
{"", false, "killer", false},
{"custom", false, "kong", false},
{"custom", true, "kong", false},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add {"", true, "custom", false}?

{"", true, "custom", false},
}

ing := &extensions.Ingress{
Expand All @@ -50,7 +55,7 @@ func TestIngressClassValidatorFunc(t *testing.T) {
ing.SetAnnotations(data)
for _, test := range tests {
ing.Annotations[ingressClassKey] = test.ingress
f := IngressClassValidatorFunc(test.controller)
f := IngressClassValidatorFunc(test.controller, test.skipClasslessIngress)
b := f(&ing.ObjectMeta)
if b != test.isValid {
t.Errorf("test %v - expected %v but %v was returned", test, test.isValid, b)
Expand Down
2 changes: 1 addition & 1 deletion internal/ingress/store/fake_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func NewFakeStore(

KnativeIngress: knativeIngressStore,
},
isValidIngresClass: annotations.IngressClassValidatorFuncFromObjectMeta("kong"),
isValidIngresClass: annotations.IngressClassValidatorFuncFromObjectMeta("kong", false),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make this configurable and tweak NewFakeStore to pass this in?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure!

}
return s, nil
}
11 changes: 7 additions & 4 deletions internal/ingress/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ type Store struct {

ingressClass string

skipClasslessIngress bool

isValidIngresClass func(objectMeta *metav1.ObjectMeta) bool
}

Expand All @@ -104,11 +106,12 @@ type CacheStores struct {
}

// New creates a new object store to be used in the ingress controller
func New(cs CacheStores, ingressClass string) Storer {
func New(cs CacheStores, ingressClass string, skipClasslessIngress bool) Storer {
return Store{
stores: cs,
ingressClass: ingressClass,
isValidIngresClass: annotations.IngressClassValidatorFuncFromObjectMeta(ingressClass),
stores: cs,
ingressClass: ingressClass,
skipClasslessIngress: skipClasslessIngress,
isValidIngresClass: annotations.IngressClassValidatorFuncFromObjectMeta(ingressClass, skipClasslessIngress),
}
}

Expand Down