Skip to content

Commit

Permalink
refactor: use plugin annotation types from kubernetes-configuration (#…
Browse files Browse the repository at this point in the history
…6644)

* refactor: use plugin annotation types from kubernetes-configuration

* chore: do not add funcs to KongConsumer and KongConsumerGroup which are already defined on ObjectMeta

* chore: make linter happy
  • Loading branch information
pmalek authored Nov 14, 2024
1 parent 178818a commit 0a245bf
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 149 deletions.
51 changes: 0 additions & 51 deletions internal/annotations/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"github.com/samber/lo"
netv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8stypes "k8s.io/apimachinery/pkg/types"

kongv1beta1 "github.com/kong/kubernetes-configuration/api/configuration/v1beta1"
)
Expand Down Expand Up @@ -134,56 +133,6 @@ func IngressClassValidatorFuncFromV1Ingress(
}
}

func pluginsFromAnnotations(anns map[string]string) string {
return anns[AnnotationPrefix+PluginsKey]
}

// ExtractKongPluginsFromAnnotations extracts information about Kong
// Plugins configured using konghq.com/plugins annotation.
// This returns a list of KongPlugin resource names that should be applied.
func ExtractKongPluginsFromAnnotations(anns map[string]string) []string {
var kongPluginCRs []string
v := pluginsFromAnnotations(anns)
if v == "" {
return kongPluginCRs
}
for _, kongPlugin := range strings.Split(v, ",") {
s := strings.TrimSpace(kongPlugin)
if s != "" {
kongPluginCRs = append(kongPluginCRs, s)
}
}
return kongPluginCRs
}

type NamespacedKongPlugin k8stypes.NamespacedName

// ExtractNamespacedKongPluginsFromAnnotations extracts a KongPlugin name and optional namespace from an annotation
// value. Plugins are delimited by ",". Values are either colon-delimited "namespace:name" strings or name-only
// strings.
func ExtractNamespacedKongPluginsFromAnnotations(anns map[string]string) []NamespacedKongPlugin {
v := pluginsFromAnnotations(anns)
if v == "" {
return nil
}
split := strings.Split(v, ",")
plugins := make([]NamespacedKongPlugin, 0, len(split))
for _, s := range split {
if s != "" {
plugin := NamespacedKongPlugin{}
if strings.Contains(s, ":") {
split := strings.Split(s, ":")
plugin.Namespace = strings.TrimSpace(split[0])
plugin.Name = strings.TrimSpace(split[1])
} else {
plugin.Name = strings.TrimSpace(s)
}
plugins = append(plugins, plugin)
}
}
return plugins
}

// ExtractConfigurationName extracts the name of the KongIngress object that holds
// information about the configuration to use in Routes, Services and Upstreams.
func ExtractConfigurationName(anns map[string]string) string {
Expand Down
74 changes: 0 additions & 74 deletions internal/annotations/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,80 +129,6 @@ func TestExtractPath(t *testing.T) {
}
}

func TestExtractKongPluginsFromAnnotations(t *testing.T) {
type args struct {
anns map[string]string
}
tests := []struct {
name string
args args
want []string
}{
{
name: "non-empty",
args: args{
anns: map[string]string{
"konghq.com/plugins": "kp-rl, kp-cors",
},
},
want: []string{"kp-rl", "kp-cors"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ExtractKongPluginsFromAnnotations(tt.args.anns); !reflect.DeepEqual(got, tt.want) {
t.Errorf("ExtractKongPluginsFromAnnotations() = %v, want %v", got, tt.want)
}
})
}
}

func TestExtractNamespacedKongPluginsFromAnnotations(t *testing.T) {
type args struct {
anns map[string]string
}
tests := []struct {
name string
args args
want []NamespacedKongPlugin
}{
{
name: "empty",
args: args{
anns: map[string]string{
"konghq.com/nothing": "whatever",
},
},
want: nil,
},
{
name: "basic",
args: args{
anns: map[string]string{
"konghq.com/plugins": "kp-rl, kp-cors",
},
},
want: []NamespacedKongPlugin{{Name: "kp-rl"}, {Name: "kp-cors"}},
},
{
name: "mixed",
args: args{
anns: map[string]string{
"konghq.com/plugins": "default:kp-rl, kp-cors",
},
},
want: []NamespacedKongPlugin{{Name: "kp-rl", Namespace: "default"}, {Name: "kp-cors"}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ExtractNamespacedKongPluginsFromAnnotations(tt.args.anns); !reflect.DeepEqual(got, tt.want) {
t.Errorf("ExtractNamespacedKongPluginsFromAnnotations() = %v, want %v", got, tt.want)
}
})
}
}

func TestExtractConfigurationName(t *testing.T) {
type args struct {
anns map[string]string
Expand Down
4 changes: 3 additions & 1 deletion internal/dataplane/fallback/graph_dependencies_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
k8stypes "k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/kong/kubernetes-configuration/pkg/metadata"

"github.com/kong/kubernetes-ingress-controller/v3/internal/annotations"
"github.com/kong/kubernetes-ingress-controller/v3/internal/store"
)
Expand All @@ -14,7 +16,7 @@ import (
// that refers them in its annotations.
func resolveObjectDependenciesPlugin(cache store.CacheStores, obj client.Object) []client.Object {
var dependencies []client.Object
for _, pluginName := range annotations.ExtractKongPluginsFromAnnotations(obj.GetAnnotations()) {
for _, pluginName := range metadata.ExtractPlugins(obj) {
// KongPlugin is tied to a namespace.
if plugin, exists, err := cache.Plugin.GetByKey(
fmt.Sprintf("%s/%s", obj.GetNamespace(), pluginName),
Expand Down
14 changes: 8 additions & 6 deletions internal/dataplane/kongstate/customentity.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import (
"github.com/kong/go-kong/kong"
"github.com/kong/go-kong/kong/custom"
"github.com/samber/lo"
k8stypes "k8s.io/apimachinery/pkg/types"

kongv1alpha1 "github.com/kong/kubernetes-configuration/api/configuration/v1alpha1"
"github.com/kong/kubernetes-ingress-controller/v3/internal/annotations"

"github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/failures"
"github.com/kong/kubernetes-ingress-controller/v3/internal/store"
"github.com/kong/kubernetes-ingress-controller/v3/internal/util"
Expand Down Expand Up @@ -302,13 +303,14 @@ func findCustomEntityRelatedPlugin(logger logr.Logger, cacheStore store.Storer,
}

// Extract the plugin key to get the plugin relations.
paretRefNamespace := lo.FromPtrOr(parentRef.Namespace, "")
parentRefNamespace := lo.FromPtrOr(parentRef.Namespace, "")
// if the namespace in parentRef is not same as the namespace of KCE itself, check if the reference is allowed by ReferenceGrant.
if paretRefNamespace != "" && paretRefNamespace != k8sEntity.Namespace {
paretRefNamespace, err := extractReferredPluginNamespace(logger, cacheStore, k8sEntity, annotations.NamespacedKongPlugin{
Namespace: paretRefNamespace,
if parentRefNamespace != "" && parentRefNamespace != k8sEntity.Namespace {
nn := k8stypes.NamespacedName{
Namespace: parentRefNamespace,
Name: parentRef.Name,
})
}
paretRefNamespace, err := extractReferredPluginNamespace(logger, cacheStore, k8sEntity, nn)
if err != nil {
return "", false, err
}
Expand Down
29 changes: 12 additions & 17 deletions internal/dataplane/kongstate/kongstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import (
corev1 "k8s.io/api/core/v1"
netv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8stypes "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
"sigs.k8s.io/controller-runtime/pkg/client"

kongv1alpha1 "github.com/kong/kubernetes-configuration/api/configuration/v1alpha1"
kongv1beta1 "github.com/kong/kubernetes-configuration/api/configuration/v1beta1"
"github.com/kong/kubernetes-configuration/pkg/metadata"

"github.com/kong/kubernetes-ingress-controller/v3/internal/admission/validation/consumers/credentials"
"github.com/kong/kubernetes-ingress-controller/v3/internal/annotations"
Expand Down Expand Up @@ -386,7 +388,7 @@ func (ks *KongState) getPluginRelations(cacheStore store.Storer, log logr.Logger
RouteRelation entityRelationType = iota
ServiceRelation entityRelationType = iota
)
addRelation := func(referrer client.Object, plugin annotations.NamespacedKongPlugin, identifier string, t entityRelationType) {
addRelation := func(referrer client.Object, plugin k8stypes.NamespacedName, identifier string, t entityRelationType) {
// There are 2 types of KongPlugin references: local and remote.
// A local reference is one where the KongPlugin is in the same namespace as the referrer.
// A remote reference is one where the KongPlugin is in a different namespace.
Expand Down Expand Up @@ -423,16 +425,14 @@ func (ks *KongState) getPluginRelations(cacheStore store.Storer, log logr.Logger

for i := range ks.Services {
for _, svc := range ks.Services[i].K8sServices {
pluginList := annotations.ExtractNamespacedKongPluginsFromAnnotations(svc.GetAnnotations())
for _, plugin := range pluginList {
for _, plugin := range metadata.ExtractPluginsNamespacedNames(svc) {
addRelation(svc, plugin, *ks.Services[i].Name, ServiceRelation)
}
}

for j := range ks.Services[i].Routes {
ingress := ks.Services[i].Routes[j].Ingress
pluginList := annotations.ExtractNamespacedKongPluginsFromAnnotations(ingress.Annotations)
for _, plugin := range pluginList {
for _, plugin := range metadata.ExtractPluginsNamespacedNames(ingress) {
// pretend we have a full Ingress struct for reference checks.
// REVIEW: we only need an object to carry type meta and object meta here, maybe we should create some other types of virtual object here?
virtualIngress := netv1.Ingress{
Expand All @@ -449,15 +449,13 @@ func (ks *KongState) getPluginRelations(cacheStore store.Storer, log logr.Logger
}

for _, c := range ks.Consumers {
pluginList := annotations.ExtractNamespacedKongPluginsFromAnnotations(c.K8sKongConsumer.GetAnnotations())
for _, plugin := range pluginList {
for _, plugin := range metadata.ExtractPluginsNamespacedNames(&c.K8sKongConsumer) {
addRelation(&c.K8sKongConsumer, plugin, *c.Username, ConsumerRelation)
}
}

for _, cg := range ks.ConsumerGroups {
pluginList := annotations.ExtractNamespacedKongPluginsFromAnnotations(cg.K8sKongConsumerGroup.GetAnnotations())
for _, plugin := range pluginList {
for _, plugin := range metadata.ExtractPluginsNamespacedNames(&cg.K8sKongConsumerGroup) {
addRelation(&cg.K8sKongConsumerGroup, plugin, *cg.Name, ConsumerGroupRelation)
}
}
Expand Down Expand Up @@ -782,7 +780,7 @@ func (ks *KongState) getPluginRelatedEntitiesRef(cacheStore store.Storer, log lo
RelatedEntities: map[string]RelatedEntitiesRef{},
RouteAttachedService: map[string]*Service{},
}
addRelation := func(referrer client.Object, plugin annotations.NamespacedKongPlugin, entity any) {
addRelation := func(referrer client.Object, plugin k8stypes.NamespacedName, entity any) {
namespace, err := extractReferredPluginNamespace(log, cacheStore, referrer, plugin)
if err != nil {
log.Error(err, "could not bind requested plugin", "plugin", plugin.Name, "namespace", plugin.Namespace)
Expand All @@ -806,16 +804,14 @@ func (ks *KongState) getPluginRelatedEntitiesRef(cacheStore store.Storer, log lo

for i := range ks.Services {
for _, svc := range ks.Services[i].K8sServices {
pluginList := annotations.ExtractNamespacedKongPluginsFromAnnotations(svc.GetAnnotations())
for _, plugin := range pluginList {
for _, plugin := range metadata.ExtractPluginsNamespacedNames(svc) {
addRelation(svc, plugin, &ks.Services[i])
}
}

for j, r := range ks.Services[i].Routes {
ingress := ks.Services[i].Routes[j].Ingress
pluginList := annotations.ExtractNamespacedKongPluginsFromAnnotations(ingress.Annotations)
for _, plugin := range pluginList {
for _, plugin := range metadata.ExtractPluginsNamespacedNames(ingress) {
// Pretend we have a full Ingress struct for reference checks.
virtualIngress := netv1.Ingress{
// Fill the actual type of the object for reference checks.
Expand All @@ -835,16 +831,15 @@ func (ks *KongState) getPluginRelatedEntitiesRef(cacheStore store.Storer, log lo
}

for i, c := range ks.Consumers {
pluginList := annotations.ExtractNamespacedKongPluginsFromAnnotations(c.K8sKongConsumer.GetAnnotations())
for _, plugin := range pluginList {
for _, plugin := range metadata.ExtractPluginsNamespacedNames(&c.K8sKongConsumer) {
addRelation(&c.K8sKongConsumer, plugin, &ks.Consumers[i])
}
}
return pluginRels
}

func extractReferredPluginNamespace(
log logr.Logger, cacheStore store.Storer, referrer client.Object, plugin annotations.NamespacedKongPlugin,
log logr.Logger, cacheStore store.Storer, referrer client.Object, plugin k8stypes.NamespacedName,
) (string, error) {
// There are 2 types of KongPlugin references: local and remote.
// A local reference is one where the KongPlugin is in the same namespace as the referrer.
Expand Down
Loading

0 comments on commit 0a245bf

Please sign in to comment.