mirror of
https://github.com/traefik/mesh.git
synced 2026-06-01 18:37:57 +00:00
128 lines
3.3 KiB
Go
128 lines
3.3 KiB
Go
package k8s
|
|
|
|
import (
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/api/meta"
|
|
)
|
|
|
|
// ResourceFilter holds resource filtering rules.
|
|
type ResourceFilter struct {
|
|
watchedNamespaces []string
|
|
ignoredNamespaces []string
|
|
ignoredServices []namespaceName
|
|
ignoredLabels map[string]string
|
|
}
|
|
|
|
type namespaceName struct {
|
|
Name string
|
|
Namespace string
|
|
}
|
|
|
|
// ResourceFilterOption adds a filtering rule to the given ResourceFilter.
|
|
type ResourceFilterOption func(filter *ResourceFilter)
|
|
|
|
// WatchNamespaces add the given namespaces to the list of namespaces to watch.
|
|
func WatchNamespaces(namespaces ...string) ResourceFilterOption {
|
|
return func(filter *ResourceFilter) {
|
|
filter.watchedNamespaces = append(filter.watchedNamespaces, namespaces...)
|
|
}
|
|
}
|
|
|
|
// IgnoreNamespaces adds the given namespaces to the list of namespaces to ignore.
|
|
func IgnoreNamespaces(namespaces ...string) ResourceFilterOption {
|
|
return func(filter *ResourceFilter) {
|
|
filter.ignoredNamespaces = append(filter.ignoredNamespaces, namespaces...)
|
|
}
|
|
}
|
|
|
|
// IgnoreLabel ignores resources with the given label and value.
|
|
func IgnoreLabel(name, value string) ResourceFilterOption {
|
|
return func(filter *ResourceFilter) {
|
|
filter.ignoredLabels[name] = value
|
|
}
|
|
}
|
|
|
|
// IgnoreService adds the service to the list of service to ignore.
|
|
func IgnoreService(namespace, name string) ResourceFilterOption {
|
|
return func(filter *ResourceFilter) {
|
|
filter.ignoredServices = append(filter.ignoredServices, namespaceName{
|
|
Namespace: namespace,
|
|
Name: name,
|
|
})
|
|
}
|
|
}
|
|
|
|
// NewResourceFilter creates a new ResourceFilter, configured with the given options.
|
|
func NewResourceFilter(opts ...ResourceFilterOption) *ResourceFilter {
|
|
filter := &ResourceFilter{
|
|
ignoredLabels: make(map[string]string),
|
|
}
|
|
|
|
for _, opt := range opts {
|
|
opt(filter)
|
|
}
|
|
|
|
return filter
|
|
}
|
|
|
|
// IsIgnored returns true if the resource should be ignored.
|
|
func (f *ResourceFilter) IsIgnored(obj interface{}) bool {
|
|
accessor, err := meta.Accessor(obj)
|
|
if err != nil {
|
|
return true
|
|
}
|
|
|
|
pMeta := meta.AsPartialObjectMetadata(accessor)
|
|
|
|
// If we are not watching all namespaces, check if the namespace is in the watch list.
|
|
if len(f.watchedNamespaces) > 0 && !contains(f.watchedNamespaces, pMeta.Namespace) {
|
|
return true
|
|
}
|
|
|
|
// Check if the namespace is not explicitly ignored.
|
|
if contains(f.ignoredNamespaces, pMeta.Namespace) {
|
|
return true
|
|
}
|
|
|
|
// Check if the resource contains an ignored label.
|
|
for ignoredName, ignoredValue := range f.ignoredLabels {
|
|
if value, ok := pMeta.Labels[ignoredName]; ok && value == ignoredValue {
|
|
return true
|
|
}
|
|
}
|
|
|
|
if svc, ok := obj.(*corev1.Service); ok {
|
|
// Check if the service is not explicitly ignored.
|
|
if containsNamespaceName(f.ignoredServices, namespaceName{Namespace: svc.Namespace, Name: svc.Name}) {
|
|
return true
|
|
}
|
|
|
|
// Ignore ExternalName services as they are not currently supported.
|
|
if svc.Spec.Type == corev1.ServiceTypeExternalName {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func contains(slice []string, str string) bool {
|
|
for _, item := range slice {
|
|
if item == str {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func containsNamespaceName(slice []namespaceName, nn namespaceName) bool {
|
|
for _, item := range slice {
|
|
if item.Namespace == nn.Namespace && item.Name == nn.Name {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|