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

Added annotation validation methods for Custom Resources #220

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions docs/custom-resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: http-svc-consumer-ratelimiting
namespace: default #this should match the namespace of the route or service you're adding it too.
namespace: default #this should match the namespace of the route or service you're adding it too.
config:
key: value
plugin: my-plugin
Expand Down Expand Up @@ -122,7 +122,6 @@ spec:
servicePort: 80
```


## KongIngress

Ingress resource spec in Kubernetes can define routing policies
Expand Down Expand Up @@ -266,3 +265,36 @@ config:
[kong-upstream]: https://getkong.org/docs/0.14.x/admin-api/#upstream-objects
[kong-service]: https://getkong.org/docs/0.14.x/admin-api/#service-object
[kong-route]: https://getkong.org/docs/0.14.x/admin-api/#route-object

## Using mutilple ingresses on the same cluster

Kong Custom Resources are using the `kubernetes.io/ingress.class`
annotation which defaults to `nginx`. In case you have more than one Ingress deployed
on your cluster, make sure you label all your resources with the appropriate
annotation. For example:

```yaml
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: <object name>
namespace: <object namespace>
annotations:
kubernetes.io/ingress.class: <my-custom-kong-ingress>
labels:
global: "true" # optional, please note the quotes around true
# configures the plugin Globally in Kong
consumerRef: <name of an existing consumer> # optional
# applies the plugin
# in on specific route and consumer
disabled: <boolean> # optionally disable the plugin in Kong
config:
key: value
plugin: <name-of-plugin> # like key-auth, rate-limiting etc
```

Here are the list of custom resources that supports the annotation:

- KongPlugin
- KongCredential
- KongConsumer
10 changes: 5 additions & 5 deletions internal/ingress/annotations/class/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package class

import (
"github.com/golang/glog"
extensions "k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
Expand All @@ -38,13 +38,13 @@ var (
IngressClass = "nginx"
)

// IsValid returns true if the given Ingress either doesn't specify
// IsValid returns true if the given KongConsumer either doesn't specify
// the ingress.class annotation, or it's set to the configured in the
// ingress controller.
func IsValid(ing *extensions.Ingress) bool {
ingress, ok := ing.GetAnnotations()[IngressKey]
func IsValid(objectMeta *metav1.ObjectMeta) bool {
ingress, ok := objectMeta.GetAnnotations()[IngressKey]
if !ok {
glog.V(3).Infof("annotation %v is not present in ingress %v/%v", IngressKey, ing.Namespace, ing.Name)
glog.V(3).Infof("annotation %v is not present in custom resources %v/%v", IngressKey, objectMeta.Namespace, objectMeta.Name)
}

// we have 2 valid combinations
Expand Down
2 changes: 1 addition & 1 deletion internal/ingress/annotations/class/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func TestIsValidClass(t *testing.T) {
IngressClass = test.controller
DefaultClass = test.defClass

b := IsValid(ing)
b := IsValid(&ing.ObjectMeta)
if b != test.isValid {
t.Errorf("test %v - expected %v but %v was returned", test, test.isValid, b)
}
Expand Down
29 changes: 22 additions & 7 deletions internal/ingress/annotations/parser/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"strconv"

extensions "k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/kong/kubernetes-ingress-controller/internal/ingress/errors"
)
Expand Down Expand Up @@ -69,8 +70,8 @@ func (a ingAnnotations) parseInt(name string) (int, error) {
return 0, errors.ErrMissingAnnotations
}

func checkAnnotation(name string, ing *extensions.Ingress) error {
if ing == nil || len(ing.GetAnnotations()) == 0 {
func checkAnnotation(name string, objectMeta *metav1.ObjectMeta) error {
if objectMeta == nil || len(objectMeta.GetAnnotations()) == 0 {
return errors.ErrMissingAnnotations
}
if name == "" {
Expand All @@ -83,27 +84,41 @@ func checkAnnotation(name string, ing *extensions.Ingress) error {
// GetBoolAnnotation extracts a boolean from an Ingress annotation
func GetBoolAnnotation(name string, ing *extensions.Ingress) (bool, error) {
v := GetAnnotationWithPrefix(name)
err := checkAnnotation(v, ing)
if ing == nil {
return false, errors.ErrMissingAnnotations
}

err := checkAnnotation(v, &ing.ObjectMeta)

if err != nil {
return false, err
}

return ingAnnotations(ing.GetAnnotations()).parseBool(v)
}

// GetStringAnnotation extracts a string from an Ingress annotation
func GetStringAnnotation(name string, ing *extensions.Ingress) (string, error) {
func GetStringAnnotation(name string, objectMeta *metav1.ObjectMeta) (string, error) {
v := GetAnnotationWithPrefix(name)
err := checkAnnotation(v, ing)
if objectMeta == nil {
return "", errors.ErrMissingAnnotations
}

err := checkAnnotation(v, objectMeta)
if err != nil {
return "", err
}
return ingAnnotations(ing.GetAnnotations()).parseString(v)
return ingAnnotations(objectMeta.GetAnnotations()).parseString(v)
}

// GetIntAnnotation extracts an int from an Ingress annotation
func GetIntAnnotation(name string, ing *extensions.Ingress) (int, error) {
v := GetAnnotationWithPrefix(name)
err := checkAnnotation(v, ing)
if ing == nil {
return 0, errors.ErrMissingAnnotations
}

err := checkAnnotation(v, &ing.ObjectMeta)
if err != nil {
return 0, err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/ingress/annotations/parser/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func TestGetStringAnnotation(t *testing.T) {
for _, test := range tests {
data[GetAnnotationWithPrefix(test.field)] = test.value

s, err := GetStringAnnotation(test.field, ing)
s, err := GetStringAnnotation(test.field, &ing.ObjectMeta)
if test.expErr {
if err == nil {
t.Errorf("%v: expected error but retuned nil", test.name)
Expand Down
1 change: 1 addition & 0 deletions internal/ingress/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const (
rootLocation = "/"
)

// Kong Represents a Kong client and connexion information
type Kong struct {
URL string
// Headers are injected into every request to Kong's Admin API
Expand Down
1 change: 1 addition & 0 deletions internal/ingress/controller/kong.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ func (n *NGINXController) syncGlobalPlugins() error {
if name == "" {
continue
}

if _, ok := targetPluginMap[name]; ok {
glog.Error("Multiple KongPlugin definitions found with 'global' annotation for :", name,
", the plugin will not be applied")
Expand Down
Loading