Refactor object to share code from the kubernetes plugin (#17)

* Add go.mod

Signed-off-by: Arthur Outhenin-Chalandre <arthur@cri.epita.fr>

* Refactor the object to share kubernetes plugin objects

It also removed the unused watch endpointslicev1beta1 functions,
make sure everything is gofmt-ed and rewrite the import for consistency
across the plugin code.

Signed-off-by: Arthur Outhenin-Chalandre <arthur@cri.epita.fr>

* Add clusterId check in endpointsEquivalent

Signed-off-by: Arthur Outhenin-Chalandre <arthur@cri.epita.fr>

---------

Signed-off-by: Arthur Outhenin-Chalandre <arthur@cri.epita.fr>
This commit is contained in:
Arthur Outhenin-Chalandre 2025-01-07 14:28:36 +01:00 committed by GitHub
parent 5267acf5ce
commit 92cfbae0ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 524 additions and 597 deletions

View File

@ -4,21 +4,21 @@ import (
"context"
"errors"
"fmt"
k8s "github.com/coredns/coredns/plugin/kubernetes/object"
"sync"
"sync/atomic"
"time"
k8sObject "github.com/coredns/coredns/plugin/kubernetes/object"
"github.com/coredns/multicluster/object"
api "k8s.io/api/core/v1"
discovery "k8s.io/api/discovery/v1"
discoveryV1beta1 "k8s.io/api/discovery/v1beta1"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
mcs "sigs.k8s.io/mcs-api/pkg/client/clientset/versioned/typed/apis/v1alpha1"
"sync"
"sync/atomic"
"time"
mcs "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
mcsClientset "sigs.k8s.io/mcs-api/pkg/client/clientset/versioned/typed/apis/v1alpha1"
)
const (
@ -32,7 +32,7 @@ type controller interface {
SvcIndex(string) []*object.ServiceImport
EpIndex(string) []*object.Endpoints
GetNamespaceByName(string) (*object.Namespace, error)
GetNamespaceByName(string) (*k8sObject.Namespace, error)
Run()
HasSynced() bool
@ -49,7 +49,7 @@ type control struct {
modified int64
k8sClient kubernetes.Interface
mcsClient mcs.MulticlusterV1alpha1Interface
mcsClient mcsClientset.MulticlusterV1alpha1Interface
svcImportController cache.Controller
svcImportLister cache.Indexer
@ -72,7 +72,7 @@ type controllerOpts struct {
initEndpointsCache bool
}
func newController(ctx context.Context, k8sClient kubernetes.Interface, mcsClient mcs.MulticlusterV1alpha1Interface, opts controllerOpts) *control {
func newController(ctx context.Context, k8sClient kubernetes.Interface, mcsClient mcsClientset.MulticlusterV1alpha1Interface, opts controllerOpts) *control {
ctl := control{
k8sClient: k8sClient,
mcsClient: mcsClient,
@ -93,20 +93,20 @@ func newController(ctx context.Context, k8sClient kubernetes.Interface, mcsClien
}
func (c *control) watchServiceImport(ctx context.Context) {
c.svcImportLister, c.svcImportController = k8s.NewIndexerInformer(
c.svcImportLister, c.svcImportController = k8sObject.NewIndexerInformer(
&cache.ListWatch{
ListFunc: serviceImportListFunc(ctx, c.mcsClient, api.NamespaceAll),
WatchFunc: serviceImportWatchFunc(ctx, c.mcsClient, api.NamespaceAll),
},
&v1alpha1.ServiceImport{},
&mcs.ServiceImport{},
cache.ResourceEventHandlerFuncs{AddFunc: c.Add, UpdateFunc: c.Update, DeleteFunc: c.Delete},
cache.Indexers{svcNameNamespaceIndex: svcNameNamespaceIndexFunc},
k8s.DefaultProcessor(object.ToServiceImport, nil),
k8sObject.DefaultProcessor(object.ToServiceImport, nil),
)
}
func (c *control) watchNamespace(ctx context.Context) {
c.nsLister, c.nsController = k8s.NewIndexerInformer(
c.nsLister, c.nsController = k8sObject.NewIndexerInformer(
&cache.ListWatch{
ListFunc: namespaceListFunc(ctx, c.k8sClient),
WatchFunc: namespaceWatchFunc(ctx, c.k8sClient),
@ -114,12 +114,12 @@ func (c *control) watchNamespace(ctx context.Context) {
&api.Namespace{},
cache.ResourceEventHandlerFuncs{},
cache.Indexers{},
k8s.DefaultProcessor(object.ToNamespace, nil),
k8sObject.DefaultProcessor(k8sObject.ToNamespace, nil),
)
}
func (c *control) watchEndpointSlice(ctx context.Context) {
c.epLister, c.epController = k8s.NewIndexerInformer(
c.epLister, c.epController = k8sObject.NewIndexerInformer(
&cache.ListWatch{
ListFunc: endpointSliceListFunc(ctx, c.k8sClient, api.NamespaceAll),
WatchFunc: endpointSliceWatchFunc(ctx, c.k8sClient, api.NamespaceAll),
@ -127,22 +127,7 @@ func (c *control) watchEndpointSlice(ctx context.Context) {
&discovery.EndpointSlice{},
cache.ResourceEventHandlerFuncs{AddFunc: c.Add, UpdateFunc: c.Update, DeleteFunc: c.Delete},
cache.Indexers{epNameNamespaceIndex: epNameNamespaceIndexFunc},
k8s.DefaultProcessor(object.EndpointSliceToEndpoints, nil),
)
}
// watchEndpointSliceV1beta1 will set the endpoint Lister and Controller to watch v1beta1
// instead of the default v1.
func (c *control) WatchEndpointSliceV1beta1(ctx context.Context) {
c.epLister, c.epController = k8s.NewIndexerInformer(
&cache.ListWatch{
ListFunc: endpointSliceListFuncV1beta1(ctx, c.k8sClient, api.NamespaceAll),
WatchFunc: endpointSliceWatchFuncV1beta1(ctx, c.k8sClient, api.NamespaceAll),
},
&discoveryV1beta1.EndpointSlice{},
cache.ResourceEventHandlerFuncs{AddFunc: c.Add, UpdateFunc: c.Update, DeleteFunc: c.Delete},
cache.Indexers{epNameNamespaceIndex: epNameNamespaceIndexFunc},
k8s.DefaultProcessor(object.EndpointSliceV1beta1ToEndpoints, nil),
k8sObject.DefaultProcessor(object.EndpointSliceToEndpoints, nil),
)
}
@ -232,13 +217,13 @@ func (c *control) EpIndex(idx string) (ep []*object.Endpoints) {
return ep
}
func serviceImportListFunc(ctx context.Context, c mcs.MulticlusterV1alpha1Interface, ns string) func(meta.ListOptions) (runtime.Object, error) {
func serviceImportListFunc(ctx context.Context, c mcsClientset.MulticlusterV1alpha1Interface, ns string) func(meta.ListOptions) (runtime.Object, error) {
return func(opts meta.ListOptions) (runtime.Object, error) {
return c.ServiceImports(ns).List(ctx, opts)
}
}
func serviceImportWatchFunc(ctx context.Context, c mcs.MulticlusterV1alpha1Interface, ns string) func(options meta.ListOptions) (watch.Interface, error) {
func serviceImportWatchFunc(ctx context.Context, c mcsClientset.MulticlusterV1alpha1Interface, ns string) func(options meta.ListOptions) (watch.Interface, error) {
return func(opts meta.ListOptions) (watch.Interface, error) {
return c.ServiceImports(ns).Watch(ctx, opts)
}
@ -258,34 +243,20 @@ func namespaceWatchFunc(ctx context.Context, c kubernetes.Interface) func(option
func endpointSliceListFunc(ctx context.Context, c kubernetes.Interface, ns string) func(meta.ListOptions) (runtime.Object, error) {
return func(opts meta.ListOptions) (runtime.Object, error) {
opts.LabelSelector = v1alpha1.LabelServiceName // only slices created by MCS controller
opts.LabelSelector = mcs.LabelServiceName // only slices created by MCS controller
return c.DiscoveryV1().EndpointSlices(ns).List(ctx, opts)
}
}
func endpointSliceWatchFunc(ctx context.Context, c kubernetes.Interface, ns string) func(options meta.ListOptions) (watch.Interface, error) {
return func(opts meta.ListOptions) (watch.Interface, error) {
opts.LabelSelector = v1alpha1.LabelServiceName // only slices created by MCS controller
opts.LabelSelector = mcs.LabelServiceName // only slices created by MCS controller
return c.DiscoveryV1().EndpointSlices(ns).Watch(ctx, opts)
}
}
func endpointSliceListFuncV1beta1(ctx context.Context, c kubernetes.Interface, ns string) func(meta.ListOptions) (runtime.Object, error) {
return func(opts meta.ListOptions) (runtime.Object, error) {
opts.LabelSelector = v1alpha1.LabelServiceName // only slices created by MCS controller
return c.DiscoveryV1beta1().EndpointSlices(ns).List(ctx, opts)
}
}
func endpointSliceWatchFuncV1beta1(ctx context.Context, c kubernetes.Interface, ns string) func(options meta.ListOptions) (watch.Interface, error) {
return func(opts meta.ListOptions) (watch.Interface, error) {
opts.LabelSelector = v1alpha1.LabelServiceName // only slices created by MCS controller
return c.DiscoveryV1beta1().EndpointSlices(ns).Watch(ctx, opts)
}
}
// GetNamespaceByName returns the namespace by name. If nothing is found an error is returned.
func (c *control) GetNamespaceByName(name string) (*object.Namespace, error) {
func (c *control) GetNamespaceByName(name string) (*k8sObject.Namespace, error) {
o, exists, err := c.nsLister.GetByKey(name)
if err != nil {
return nil, err
@ -293,7 +264,7 @@ func (c *control) GetNamespaceByName(name string) (*object.Namespace, error) {
if !exists {
return nil, fmt.Errorf("namespace not found")
}
ns, ok := o.(*object.Namespace)
ns, ok := o.(*k8sObject.Namespace)
if !ok {
return nil, fmt.Errorf("found key but not namespace")
}
@ -336,6 +307,9 @@ func endpointsEquivalent(a, b *object.Endpoints) bool {
if len(a.Subsets) != len(b.Subsets) {
return false
}
if a.ClusterId != b.ClusterId {
return false
}
// we should be able to rely on
// these being sorted and able to be compared
@ -352,7 +326,7 @@ func endpointsEquivalent(a, b *object.Endpoints) bool {
// subsetsEquivalent checks if two endpoint subsets are significantly equivalent
// I.e. that they have the same ready addresses, host names, ports (including protocol
// and service names for SRV)
func subsetsEquivalent(sa, sb object.EndpointSubset) bool {
func subsetsEquivalent(sa, sb k8sObject.EndpointSubset) bool {
if len(sa.Addresses) != len(sb.Addresses) {
return false
}

77
go.mod Normal file
View File

@ -0,0 +1,77 @@
module github.com/coredns/multicluster
require (
github.com/coredns/caddy v1.1.1
github.com/coredns/coredns v1.11.4
github.com/miekg/dns v1.1.62
k8s.io/api v0.31.2
k8s.io/apimachinery v0.31.2
k8s.io/client-go v0.31.2
sigs.k8s.io/mcs-api v0.1.1-0.20241002142749-eff1ba8c3ab2
)
require (
github.com/apparentlymart/go-cidr v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/onsi/ginkgo/v2 v2.21.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.60.1 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/quic-go/quic-go v0.48.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.uber.org/mock v0.5.0 // indirect
golang.org/x/crypto v0.29.0 // indirect
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/net v0.31.0 // indirect
golang.org/x/oauth2 v0.24.0 // indirect
golang.org/x/sync v0.9.0 // indirect
golang.org/x/sys v0.27.0 // indirect
golang.org/x/term v0.26.0 // indirect
golang.org/x/text v0.20.0 // indirect
golang.org/x/time v0.8.0 // indirect
golang.org/x/tools v0.27.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f // indirect
google.golang.org/grpc v1.68.0 // indirect
google.golang.org/protobuf v1.35.2 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.3 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
go 1.23.0

191
go.sum Normal file
View File

@ -0,0 +1,191 @@
github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU=
github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/coredns/caddy v1.1.1 h1:2eYKZT7i6yxIfGP3qLJoJ7HAsDJqYB+X68g4NYjSrE0=
github.com/coredns/caddy v1.1.1/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4=
github.com/coredns/coredns v1.11.4 h1:Z0P5l1iY6uYcOsP63EzUVC+NsJozcCktzq2/QudYlLc=
github.com/coredns/coredns v1.11.4/go.mod h1:WiwgaFEb6amM8uFC5IwP4t39UndPNYo/Xk6ISaPX4Z8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU=
github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 h1:sAGdeJj0bnMgUNVeUpp6AYlVdCt3/GdI3pGRqsNSQLs=
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU=
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc=
github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/quic-go/quic-go v0.48.1 h1:y/8xmfWI9qmGTc+lBr4jKRUWLGSlSigv847ULJ4hYXA=
github.com/quic-go/quic-go v0.48.1/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o=
golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f h1:C1QccEa9kUwvMgEUORqQD9S17QesQijxjZ84sO82mfo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0=
k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk=
k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw=
k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc=
k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 h1:jGnCPejIetjiy2gqaJ5V0NLwTpF4wbQ6cZIItJCSHno=
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/mcs-api v0.1.1-0.20241002142749-eff1ba8c3ab2 h1:kYmFRW4FG7KvgoBRdvrlhFPScYu+ZKhVt+FBRl43CPE=
sigs.k8s.io/mcs-api v0.1.1-0.20241002142749-eff1ba8c3ab2/go.mod h1:x0rgWQwGd3FJzrb94BNn3Nu7YxUwBWcgjVRbkrkVy2A=
sigs.k8s.io/structured-merge-diff/v4 v4.4.3 h1:sCP7Vv3xx/CWIuTPVN38lUPx0uw0lcLfzaiDa8Ja01A=
sigs.k8s.io/structured-merge-diff/v4 v4.4.3/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

View File

@ -10,16 +10,16 @@ import (
"github.com/coredns/coredns/coremain"
"github.com/coredns/coredns/plugin/etcd/msg"
k8sObject "github.com/coredns/coredns/plugin/kubernetes/object"
"github.com/coredns/coredns/plugin/pkg/dnsutil"
"github.com/coredns/coredns/plugin/pkg/fall"
"github.com/coredns/coredns/request"
"github.com/coredns/multicluster/object"
model "github.com/coredns/multicluster/object"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
apiv1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
"sigs.k8s.io/mcs-api/pkg/client/clientset/versioned/typed/apis/v1alpha1"
mcs "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
mcsClientset "sigs.k8s.io/mcs-api/pkg/client/clientset/versioned/typed/apis/v1alpha1"
"github.com/coredns/coredns/plugin"
clog "github.com/coredns/coredns/plugin/pkg/log"
@ -79,7 +79,7 @@ func (m *MultiCluster) InitController(ctx context.Context) (onStart func() error
return nil, nil, fmt.Errorf("failed to create kubernetes notification controller: %q", err)
}
mcsClient, err := v1alpha1.NewForConfig(config)
mcsClient, err := mcsClientset.NewForConfig(config)
m.controller = newController(ctx, kubeClient, mcsClient, m.opts)
@ -188,7 +188,6 @@ func (m MultiCluster) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns
message.Extra = append(message.Extra, extra...)
w.WriteMsg(message)
return dns.RcodeSuccess, nil
}
// Name implements the Handler interface.
@ -200,7 +199,6 @@ func (m MultiCluster) Name() string { return pluginName }
// on exact match should be returned.
func (m MultiCluster) Services(ctx context.Context, state request.Request, exact bool, opt plugin.Options) ([]msg.Service, error) {
switch state.QType() {
case dns.TypeTXT:
// 1 label + zone, label must be "dns-version".
t, _ := dnsutil.TrimZone(state.Name(), state.Zone)
@ -344,7 +342,7 @@ func (m *MultiCluster) findServices(r recordRequest, zone string) (services []ms
var (
endpointsListFunc func() []*object.Endpoints
endpointsList []*object.Endpoints
serviceList []*model.ServiceImport
serviceList []*object.ServiceImport
)
if wildcard(r.service) || wildcard(r.namespace) {
@ -369,7 +367,7 @@ func (m *MultiCluster) findServices(r recordRequest, zone string) (services []ms
}
// Headless service or endpoint query
if svc.Type == apiv1alpha1.Headless || r.endpoint != "" {
if svc.Type == mcs.Headless || r.endpoint != "" {
if endpointsList == nil {
endpointsList = endpointsListFunc()
}
@ -381,7 +379,6 @@ func (m *MultiCluster) findServices(r recordRequest, zone string) (services []ms
for _, eps := range ep.Subsets {
for _, addr := range eps.Addresses {
if r.endpoint != "" {
if !match(r.cluster, ep.ClusterId) || !match(r.endpoint, endpointHostname(addr)) {
continue
@ -423,7 +420,7 @@ func (m *MultiCluster) findServices(r recordRequest, zone string) (services []ms
return services, err
}
func endpointHostname(addr object.EndpointAddress) string {
func endpointHostname(addr k8sObject.EndpointAddress) string {
if addr.Hostname != "" {
return addr.Hostname
}

View File

@ -3,12 +3,14 @@ package multicluster
import (
"context"
"fmt"
"testing"
k8sObject "github.com/coredns/coredns/plugin/kubernetes/object"
"github.com/coredns/coredns/plugin/pkg/dnstest"
"github.com/coredns/coredns/plugin/test"
"github.com/coredns/multicluster/object"
"github.com/miekg/dns"
"sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
"testing"
mcs "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
)
var dnsTestCases = []test.Case{
@ -37,34 +39,34 @@ var dnsTestCases = []test.Case{
},
{
Qname: "svc1.testns.svc.cluster.local.", Qtype: dns.TypeSRV,
Rcode: dns.RcodeSuccess,
Rcode: dns.RcodeSuccess,
Answer: []dns.RR{test.SRV("svc1.testns.svc.cluster.local. 5 IN SRV 0 100 80 svc1.testns.svc.cluster.local.")},
Extra: []dns.RR{test.A("svc1.testns.svc.cluster.local. 5 IN A 10.0.0.1")},
Extra: []dns.RR{test.A("svc1.testns.svc.cluster.local. 5 IN A 10.0.0.1")},
},
{
Qname: "svcempty.testns.svc.cluster.local.", Qtype: dns.TypeSRV,
Rcode: dns.RcodeSuccess,
Rcode: dns.RcodeSuccess,
Answer: []dns.RR{test.SRV("svcempty.testns.svc.cluster.local. 5 IN SRV 0 100 80 svcempty.testns.svc.cluster.local.")},
Extra: []dns.RR{test.A("svcempty.testns.svc.cluster.local. 5 IN A 10.0.0.1")},
Extra: []dns.RR{test.A("svcempty.testns.svc.cluster.local. 5 IN A 10.0.0.1")},
},
{
Qname: "svc6.testns.svc.cluster.local.", Qtype: dns.TypeSRV,
Rcode: dns.RcodeSuccess,
Rcode: dns.RcodeSuccess,
Answer: []dns.RR{test.SRV("svc6.testns.svc.cluster.local. 5 IN SRV 0 100 80 svc6.testns.svc.cluster.local.")},
Extra: []dns.RR{test.AAAA("svc6.testns.svc.cluster.local. 5 IN AAAA 1234:abcd::1")},
Extra: []dns.RR{test.AAAA("svc6.testns.svc.cluster.local. 5 IN AAAA 1234:abcd::1")},
},
// SRV Service (wildcard)
{
Qname: "svc1.*.svc.cluster.local.", Qtype: dns.TypeSRV,
Rcode: dns.RcodeSuccess,
Rcode: dns.RcodeSuccess,
Answer: []dns.RR{test.SRV("svc1.*.svc.cluster.local. 5 IN SRV 0 100 80 svc1.testns.svc.cluster.local.")},
Extra: []dns.RR{test.A("svc1.testns.svc.cluster.local. 5 IN A 10.0.0.1")},
Extra: []dns.RR{test.A("svc1.testns.svc.cluster.local. 5 IN A 10.0.0.1")},
},
{
Qname: "svcempty.*.svc.cluster.local.", Qtype: dns.TypeSRV,
Rcode: dns.RcodeSuccess,
Rcode: dns.RcodeSuccess,
Answer: []dns.RR{test.SRV("svcempty.*.svc.cluster.local. 5 IN SRV 0 100 80 svcempty.testns.svc.cluster.local.")},
Extra: []dns.RR{test.A("svcempty.testns.svc.cluster.local. 5 IN A 10.0.0.1")},
Extra: []dns.RR{test.A("svcempty.testns.svc.cluster.local. 5 IN A 10.0.0.1")},
},
// SRV Service Not udp/tcp
{
@ -196,7 +198,7 @@ var dnsTestCases = []test.Case{
// AAAA
{
Qname: "5678-abcd--2.clusterid.hdls1.testns.svc.cluster.local", Qtype: dns.TypeAAAA,
Rcode: dns.RcodeSuccess,
Rcode: dns.RcodeSuccess,
Answer: []dns.RR{test.AAAA("5678-abcd--2.clusterid.hdls1.testns.svc.cluster.local. 5 IN AAAA 5678:abcd::2")},
},
// AAAA Service (with an existing A record, but no AAAA record)
@ -346,7 +348,7 @@ var dnsTestCases = []test.Case{
},
{
Qname: "svc-dual-stack.testns.svc.cluster.local.", Qtype: dns.TypeSRV,
Rcode: dns.RcodeSuccess,
Rcode: dns.RcodeSuccess,
Answer: []dns.RR{test.SRV("svc-dual-stack.testns.svc.cluster.local. 5 IN SRV 0 50 80 svc-dual-stack.testns.svc.cluster.local.")},
Extra: []dns.RR{
test.A("svc-dual-stack.testns.svc.cluster.local. 5 IN A 10.0.0.3"),
@ -370,7 +372,6 @@ var dnsTestCases = []test.Case{
}
func TestServeDNS(t *testing.T) {
m := New([]string{"cluster.local."})
m.controller = &controllerMock2{}
m.Next = test.NextHandler(dns.RcodeSuccess, nil)
@ -469,7 +470,6 @@ var notSyncedTestCases = []test.Case{
}
func TestNotSyncedServeDNS(t *testing.T) {
m := New([]string{"cluster.local."})
m.controller = &controllerMock2{
notSynced: true,
@ -520,9 +520,9 @@ var svcIndex = map[string][]*object.ServiceImport{
{
Name: "kubedns",
Namespace: "kube-system",
Type: v1alpha1.ClusterSetIP,
Type: mcs.ClusterSetIP,
ClusterIPs: []string{"10.0.0.10"},
Ports: []v1alpha1.ServicePort{
Ports: []mcs.ServicePort{
{Name: "dns", Protocol: "udp", Port: 53},
},
},
@ -531,9 +531,9 @@ var svcIndex = map[string][]*object.ServiceImport{
{
Name: "svc1",
Namespace: "testns",
Type: v1alpha1.ClusterSetIP,
Type: mcs.ClusterSetIP,
ClusterIPs: []string{"10.0.0.1"},
Ports: []v1alpha1.ServicePort{
Ports: []mcs.ServicePort{
{Name: "http", Protocol: "tcp", Port: 80},
},
},
@ -542,9 +542,9 @@ var svcIndex = map[string][]*object.ServiceImport{
{
Name: "svcempty",
Namespace: "testns",
Type: v1alpha1.ClusterSetIP,
Type: mcs.ClusterSetIP,
ClusterIPs: []string{"10.0.0.1"},
Ports: []v1alpha1.ServicePort{
Ports: []mcs.ServicePort{
{Name: "http", Protocol: "tcp", Port: 80},
},
},
@ -553,9 +553,9 @@ var svcIndex = map[string][]*object.ServiceImport{
{
Name: "svc6",
Namespace: "testns",
Type: v1alpha1.ClusterSetIP,
Type: mcs.ClusterSetIP,
ClusterIPs: []string{"1234:abcd::1"},
Ports: []v1alpha1.ServicePort{
Ports: []mcs.ServicePort{
{Name: "http", Protocol: "tcp", Port: 80},
},
},
@ -564,22 +564,22 @@ var svcIndex = map[string][]*object.ServiceImport{
{
Name: "hdls1",
Namespace: "testns",
Type: v1alpha1.Headless,
Type: mcs.Headless,
},
},
"hdlsprtls.testns": {
{
Name: "hdlsprtls",
Namespace: "testns",
Type: v1alpha1.Headless,
Type: mcs.Headless,
},
},
"svc-dual-stack.testns": {
{
Name: "svc-dual-stack",
Namespace: "testns",
Type: v1alpha1.ClusterSetIP,
ClusterIPs: []string{"10.0.0.3", "10::3"}, Ports: []v1alpha1.ServicePort{
Type: mcs.ClusterSetIP,
ClusterIPs: []string{"10.0.0.3", "10::3"}, Ports: []mcs.ServicePort{
{Name: "http", Protocol: "tcp", Port: 80},
},
},
@ -598,85 +598,95 @@ func (controllerMock2) ServiceList() []*object.ServiceImport {
var epsIndex = map[string][]*object.Endpoints{
"kubedns.kube-system": {{
Subsets: []object.EndpointSubset{
{
Addresses: []object.EndpointAddress{
{IP: "172.0.0.100"},
},
Ports: []object.EndpointPort{
{Port: 53, Protocol: "udp", Name: "dns"},
Endpoints: k8sObject.Endpoints{
Subsets: []k8sObject.EndpointSubset{
{
Addresses: []k8sObject.EndpointAddress{
{IP: "172.0.0.100"},
},
Ports: []k8sObject.EndpointPort{
{Port: 53, Protocol: "udp", Name: "dns"},
},
},
},
Name: "kubedns",
Namespace: "kube-system",
Index: object.EndpointsKey("kubedns", "kube-system"),
},
ClusterId: "clusterid",
Name: "kubedns",
Namespace: "kube-system",
Index: object.EndpointsKey("kubedns", "kube-system"),
}},
"svc1.testns": {{
Subsets: []object.EndpointSubset{
{
Addresses: []object.EndpointAddress{
{IP: "172.0.0.1", Hostname: "ep1a"},
},
Ports: []object.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
Endpoints: k8sObject.Endpoints{
Subsets: []k8sObject.EndpointSubset{
{
Addresses: []k8sObject.EndpointAddress{
{IP: "172.0.0.1", Hostname: "ep1a"},
},
Ports: []k8sObject.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
},
},
},
Name: "svc1-slice1",
Namespace: "testns",
Index: object.EndpointsKey("svc1", "testns"),
},
ClusterId: "clusterid",
Name: "svc1-slice1",
Namespace: "testns",
Index: object.EndpointsKey("svc1", "testns"),
}},
"svcempty.testns": {{
Subsets: []object.EndpointSubset{
{
Addresses: nil,
Ports: []object.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
Endpoints: k8sObject.Endpoints{
Subsets: []k8sObject.EndpointSubset{
{
Addresses: nil,
Ports: []k8sObject.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
},
},
},
Name: "svcempty-slice1",
Namespace: "testns",
Index: object.EndpointsKey("svcempty", "testns"),
},
ClusterId: "clusterid",
Name: "svcempty-slice1",
Namespace: "testns",
Index: object.EndpointsKey("svcempty", "testns"),
}},
"hdls1.testns": {{
Subsets: []object.EndpointSubset{
{
Addresses: []object.EndpointAddress{
{IP: "172.0.0.2"},
{IP: "172.0.0.3"},
{IP: "172.0.0.4", Hostname: "dup-name"},
{IP: "172.0.0.5", Hostname: "dup-name"},
{IP: "5678:abcd::1"},
{IP: "5678:abcd::2"},
},
Ports: []object.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
Endpoints: k8sObject.Endpoints{
Subsets: []k8sObject.EndpointSubset{
{
Addresses: []k8sObject.EndpointAddress{
{IP: "172.0.0.2"},
{IP: "172.0.0.3"},
{IP: "172.0.0.4", Hostname: "dup-name"},
{IP: "172.0.0.5", Hostname: "dup-name"},
{IP: "5678:abcd::1"},
{IP: "5678:abcd::2"},
},
Ports: []k8sObject.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
},
},
},
Name: "hdls1-slice1",
Namespace: "testns",
Index: object.EndpointsKey("hdls1", "testns"),
},
ClusterId: "clusterid",
Name: "hdls1-slice1",
Namespace: "testns",
Index: object.EndpointsKey("hdls1", "testns"),
}},
"hdlsprtls.testns": {{
Subsets: []object.EndpointSubset{
{
Addresses: []object.EndpointAddress{
{IP: "172.0.0.20"},
Endpoints: k8sObject.Endpoints{
Subsets: []k8sObject.EndpointSubset{
{
Addresses: []k8sObject.EndpointAddress{
{IP: "172.0.0.20"},
},
Ports: []k8sObject.EndpointPort{{Port: -1}},
},
Ports: []object.EndpointPort{{Port: -1}},
},
Name: "hdlsprtls-slice1",
Namespace: "testns",
Index: object.EndpointsKey("hdlsprtls", "testns"),
},
ClusterId: "clusterid",
Name: "hdlsprtls-slice1",
Namespace: "testns",
Index: object.EndpointsKey("hdlsprtls", "testns"),
}},
}
@ -692,14 +702,14 @@ func (controllerMock2) EndpointsList() []*object.Endpoints {
return eps
}
func (controllerMock2) GetNamespaceByName(name string) (*object.Namespace, error) {
func (controllerMock2) GetNamespaceByName(name string) (*k8sObject.Namespace, error) {
if name == "pod-nons" { // handler_pod_verified_test.go uses this for non-existent namespace.
return nil, fmt.Errorf("namespace not found")
}
if name == "nsnoexist" {
return nil, fmt.Errorf("namespace not found")
}
return &object.Namespace{
return &k8sObject.Namespace{
Name: name,
}, nil
}

View File

@ -2,16 +2,18 @@ package multicluster
import (
"context"
"testing"
"github.com/coredns/coredns/plugin"
k8sObject "github.com/coredns/coredns/plugin/kubernetes/object"
"github.com/coredns/coredns/request"
"github.com/coredns/multicluster/object"
"github.com/miekg/dns"
"sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
"testing"
mcs "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
)
func TestWildcard(t *testing.T) {
var tests = []struct {
tests := []struct {
s string
expected bool
}{
@ -32,7 +34,7 @@ func TestWildcard(t *testing.T) {
}
func TestEndpointHostname(t *testing.T) {
var tests = []struct {
tests := []struct {
ip string
hostname string
expected string
@ -41,7 +43,7 @@ func TestEndpointHostname(t *testing.T) {
{"10.11.12.13", "epname", "epname"},
}
for _, test := range tests {
result := endpointHostname(object.EndpointAddress{IP: test.ip, Hostname: test.hostname})
result := endpointHostname(k8sObject.EndpointAddress{IP: test.ip, Hostname: test.hostname})
if result != test.expected {
t.Errorf("Expected endpoint name for (ip:%v hostname:%v) to be '%v', but got '%v'", test.ip, test.hostname, test.expected, result)
}
@ -61,7 +63,7 @@ func (controllerMock) SvcIndex(string) []*object.ServiceImport {
Name: "svc1",
Namespace: "testns",
ClusterIPs: []string{"10.0.0.1"},
Ports: []v1alpha1.ServicePort{
Ports: []mcs.ServicePort{
{Name: "http", Protocol: "tcp", Port: 80},
},
},
@ -69,14 +71,14 @@ func (controllerMock) SvcIndex(string) []*object.ServiceImport {
Name: "svc-dual-stack",
Namespace: "testns",
ClusterIPs: []string{"10.0.0.2", "10::2"},
Ports: []v1alpha1.ServicePort{
Ports: []mcs.ServicePort{
{Name: "http", Protocol: "tcp", Port: 80},
},
},
{
Name: "hdls1",
Namespace: "testns",
Type: v1alpha1.Headless,
Type: mcs.Headless,
},
}
return svcs
@ -88,7 +90,7 @@ func (controllerMock) ServiceList() []*object.ServiceImport {
Name: "svc1",
Namespace: "testns",
ClusterIPs: []string{"10.0.0.1"},
Ports: []v1alpha1.ServicePort{
Ports: []mcs.ServicePort{
{Name: "http", Protocol: "tcp", Port: 80},
},
},
@ -96,14 +98,14 @@ func (controllerMock) ServiceList() []*object.ServiceImport {
Name: "svc-dual-stack",
Namespace: "testns",
ClusterIPs: []string{"10.0.0.2", "10::2"},
Ports: []v1alpha1.ServicePort{
Ports: []mcs.ServicePort{
{Name: "http", Protocol: "tcp", Port: 80},
},
},
{
Name: "hdls1",
Namespace: "testns",
Type: v1alpha1.Headless,
Type: mcs.Headless,
},
}
return svcs
@ -112,42 +114,48 @@ func (controllerMock) ServiceList() []*object.ServiceImport {
func (controllerMock) EpIndex(string) []*object.Endpoints {
eps := []*object.Endpoints{
{
Subsets: []object.EndpointSubset{
{
Addresses: []object.EndpointAddress{
{IP: "172.0.0.1", Hostname: "ep1a"},
},
Ports: []object.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
Endpoints: k8sObject.Endpoints{
Subsets: []k8sObject.EndpointSubset{
{
Addresses: []k8sObject.EndpointAddress{
{IP: "172.0.0.1", Hostname: "ep1a"},
},
Ports: []k8sObject.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
},
},
},
Name: "svc1-slice1",
Namespace: "testns",
Index: object.EndpointsKey("svc1", "testns"),
},
Name: "svc1-slice1",
Namespace: "testns",
ClusterId: "clusterid",
Index: object.EndpointsKey("svc1", "testns"),
},
{
Subsets: []object.EndpointSubset{
{
Addresses: []object.EndpointAddress{
{IP: "172.0.0.2"},
},
Ports: []object.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
Endpoints: k8sObject.Endpoints{
Subsets: []k8sObject.EndpointSubset{
{
Addresses: []k8sObject.EndpointAddress{
{IP: "172.0.0.2"},
},
Ports: []k8sObject.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
},
},
},
Name: "hdls1-slice1",
Namespace: "testns",
Index: object.EndpointsKey("hdls1", "testns"),
},
Name: "hdls1-slice1",
Namespace: "testns",
ClusterId: "clusterid",
Index: object.EndpointsKey("hdls1", "testns"),
},
{
Subsets: []object.EndpointSubset{
{
Addresses: []object.EndpointAddress{
{IP: "10.9.8.7", NodeName: "test.node.foo.bar"},
Endpoints: k8sObject.Endpoints{
Subsets: []k8sObject.EndpointSubset{
{
Addresses: []k8sObject.EndpointAddress{
{IP: "10.9.8.7", NodeName: "test.node.foo.bar"},
},
},
},
},
@ -159,55 +167,63 @@ func (controllerMock) EpIndex(string) []*object.Endpoints {
func (controllerMock) EndpointsList() []*object.Endpoints {
eps := []*object.Endpoints{
{
Subsets: []object.EndpointSubset{
{
Addresses: []object.EndpointAddress{
{IP: "172.0.0.1", Hostname: "ep1a"},
},
Ports: []object.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
Endpoints: k8sObject.Endpoints{
Subsets: []k8sObject.EndpointSubset{
{
Addresses: []k8sObject.EndpointAddress{
{IP: "172.0.0.1", Hostname: "ep1a"},
},
Ports: []k8sObject.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
},
},
},
Name: "svc1-slice1",
Namespace: "testns",
Index: object.EndpointsKey("svc1", "testns"),
},
Name: "svc1-slice1",
Namespace: "testns",
Index: object.EndpointsKey("svc1", "testns"),
},
{
Subsets: []object.EndpointSubset{
{
Addresses: []object.EndpointAddress{
{IP: "172.0.0.2"},
},
Ports: []object.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
Endpoints: k8sObject.Endpoints{
Subsets: []k8sObject.EndpointSubset{
{
Addresses: []k8sObject.EndpointAddress{
{IP: "172.0.0.2"},
},
Ports: []k8sObject.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
},
},
},
Name: "hdls1-slice1",
Namespace: "testns",
Index: object.EndpointsKey("hdls1", "testns"),
},
Name: "hdls1-slice1",
Namespace: "testns",
Index: object.EndpointsKey("hdls1", "testns"),
},
{
Subsets: []object.EndpointSubset{
{
Addresses: []object.EndpointAddress{
{IP: "172.0.0.2"},
},
Ports: []object.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
Endpoints: k8sObject.Endpoints{
Subsets: []k8sObject.EndpointSubset{
{
Addresses: []k8sObject.EndpointAddress{
{IP: "172.0.0.2"},
},
Ports: []k8sObject.EndpointPort{
{Port: 80, Protocol: "tcp", Name: "http"},
},
},
},
Name: "hdls1-slice2",
Namespace: "testns",
Index: object.EndpointsKey("hdls1", "testns"),
},
Name: "hdls1-slice2",
Namespace: "testns",
Index: object.EndpointsKey("hdls1", "testns"),
},
{
Subsets: []object.EndpointSubset{
{
Addresses: []object.EndpointAddress{
{IP: "10.9.8.7", NodeName: "test.node.foo.bar"},
Endpoints: k8sObject.Endpoints{
Subsets: []k8sObject.EndpointSubset{
{
Addresses: []k8sObject.EndpointAddress{
{IP: "10.9.8.7", NodeName: "test.node.foo.bar"},
},
},
},
},
@ -216,8 +232,8 @@ func (controllerMock) EndpointsList() []*object.Endpoints {
return eps
}
func (controllerMock) GetNamespaceByName(name string) (*object.Namespace, error) {
return &object.Namespace{
func (controllerMock) GetNamespaceByName(name string) (*k8sObject.Namespace, error) {
return &k8sObject.Namespace{
Name: name,
}, nil
}

View File

@ -1,53 +1,18 @@
package object
import (
"fmt"
"github.com/coredns/coredns/plugin/kubernetes/object"
mcs "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
discovery "k8s.io/api/discovery/v1"
discoveryV1beta1 "k8s.io/api/discovery/v1beta1"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
const (
LabelClusterId = "multicluster.kubernetes.io/source-cluster"
)
// Endpoints is a stripped down api.Endpoints with only the items we need for CoreDNS.
type Endpoints struct {
// Don't add new fields to this struct without talking to the CoreDNS maintainers.
Version string
object.Endpoints
ClusterId string
Name string
Namespace string
Index string
IndexIP []string
Subsets []EndpointSubset
*Empty
}
// EndpointSubset is a group of addresses with a common set of ports. The
// expanded set of endpoints is the Cartesian product of Addresses x Ports.
type EndpointSubset struct {
Addresses []EndpointAddress
Ports []EndpointPort
}
// EndpointAddress is a tuple that describes single IP address.
type EndpointAddress struct {
IP string
Hostname string
NodeName string
TargetRefName string
}
// EndpointPort is a tuple that describes a single port.
type EndpointPort struct {
Port int32
Name string
Protocol string
*object.Empty
}
// EndpointsKey returns a string using for the index.
@ -55,172 +20,45 @@ func EndpointsKey(name, namespace string) string { return name + "." + namespace
// EndpointSliceToEndpoints converts a *discovery.EndpointSlice to a *Endpoints.
func EndpointSliceToEndpoints(obj meta.Object) (meta.Object, error) {
ends, ok := obj.(*discovery.EndpointSlice)
if !ok {
return nil, fmt.Errorf("unexpected object %v", obj)
ends, err := object.EndpointSliceToEndpoints(obj)
if err != nil {
return nil, err
}
labels := obj.GetLabels()
e := &Endpoints{
Version: ends.GetResourceVersion(),
ClusterId: ends.Labels[LabelClusterId],
Name: ends.GetName(),
Namespace: ends.GetNamespace(),
Index: EndpointsKey(ends.Labels[mcs.LabelServiceName], ends.GetNamespace()),
Subsets: make([]EndpointSubset, 1),
Endpoints: *ends.(*object.Endpoints),
ClusterId: labels[mcs.LabelSourceCluster],
}
if len(ends.Ports) == 0 {
// Add sentinel if there are no ports.
e.Subsets[0].Ports = []EndpointPort{{Port: -1}}
} else {
e.Subsets[0].Ports = make([]EndpointPort, len(ends.Ports))
for k, p := range ends.Ports {
ep := EndpointPort{Port: *p.Port, Name: *p.Name, Protocol: string(*p.Protocol)}
e.Subsets[0].Ports[k] = ep
}
}
for _, end := range ends.Endpoints {
if !endpointsliceReady(end.Conditions.Ready) {
continue
}
for _, a := range end.Addresses {
ea := EndpointAddress{IP: a}
if end.Hostname != nil {
ea.Hostname = *end.Hostname
}
if end.TargetRef != nil {
ea.TargetRefName = end.TargetRef.Name
}
if end.NodeName != nil {
ea.NodeName = *end.NodeName
}
e.Subsets[0].Addresses = append(e.Subsets[0].Addresses, ea)
e.IndexIP = append(e.IndexIP, a)
}
}
*ends = discovery.EndpointSlice{}
e.Endpoints.Index = EndpointsKey(labels[mcs.LabelServiceName], ends.GetNamespace())
return e, nil
}
// EndpointSliceV1beta1ToEndpoints converts a v1beta1 *discovery.EndpointSlice to a *Endpoints.
func EndpointSliceV1beta1ToEndpoints(obj meta.Object) (meta.Object, error) {
ends, ok := obj.(*discoveryV1beta1.EndpointSlice)
if !ok {
return nil, fmt.Errorf("unexpected object %v", obj)
}
e := &Endpoints{
Version: ends.GetResourceVersion(),
Name: ends.GetName(),
Namespace: ends.GetNamespace(),
Index: EndpointsKey(ends.Labels[mcs.LabelServiceName], ends.GetNamespace()),
Subsets: make([]EndpointSubset, 1),
}
if len(ends.Ports) == 0 {
// Add sentinel if there are no ports.
e.Subsets[0].Ports = []EndpointPort{{Port: -1}}
} else {
e.Subsets[0].Ports = make([]EndpointPort, len(ends.Ports))
for k, p := range ends.Ports {
ep := EndpointPort{Port: *p.Port, Name: *p.Name, Protocol: string(*p.Protocol)}
e.Subsets[0].Ports[k] = ep
}
}
for _, end := range ends.Endpoints {
if !endpointsliceReady(end.Conditions.Ready) {
continue
}
for _, a := range end.Addresses {
ea := EndpointAddress{IP: a}
if end.Hostname != nil {
ea.Hostname = *end.Hostname
}
if end.TargetRef != nil {
ea.TargetRefName = end.TargetRef.Name
}
// EndpointSlice does not contain NodeName, leave blank
e.Subsets[0].Addresses = append(e.Subsets[0].Addresses, ea)
e.IndexIP = append(e.IndexIP, a)
}
}
*ends = discoveryV1beta1.EndpointSlice{}
return e, nil
}
func endpointsliceReady(ready *bool) bool {
// Per API docs: a nil value indicates an unknown state. In most cases consumers
// should interpret this unknown state as ready.
if ready == nil {
return true
}
return *ready
}
// CopyWithoutSubsets copies e, without the subsets.
func (e *Endpoints) CopyWithoutSubsets() *Endpoints {
e1 := &Endpoints{
Version: e.Version,
Name: e.Name,
Namespace: e.Namespace,
Index: e.Index,
IndexIP: make([]string, len(e.IndexIP)),
}
copy(e1.IndexIP, e.IndexIP)
return e1
}
var _ runtime.Object = &Endpoints{}
// DeepCopyObject implements the ObjectKind interface.
func (e *Endpoints) DeepCopyObject() runtime.Object {
e1 := &Endpoints{
Version: e.Version,
Name: e.Name,
Namespace: e.Namespace,
Index: e.Index,
IndexIP: make([]string, len(e.IndexIP)),
Subsets: make([]EndpointSubset, len(e.Subsets)),
}
copy(e1.IndexIP, e.IndexIP)
for i, eps := range e.Subsets {
sub := EndpointSubset{
Addresses: make([]EndpointAddress, len(eps.Addresses)),
Ports: make([]EndpointPort, len(eps.Ports)),
}
for j, a := range eps.Addresses {
ea := EndpointAddress{IP: a.IP, Hostname: a.Hostname, NodeName: a.NodeName, TargetRefName: a.TargetRefName}
sub.Addresses[j] = ea
}
for k, p := range eps.Ports {
ep := EndpointPort{Port: p.Port, Name: p.Name, Protocol: p.Protocol}
sub.Ports[k] = ep
}
e1.Subsets[i] = sub
ClusterId: e.ClusterId,
Endpoints: *e.Endpoints.DeepCopyObject().(*object.Endpoints),
}
return e1
}
// GetNamespace implements the metav1.Object interface.
func (e *Endpoints) GetNamespace() string { return e.Namespace }
func (e *Endpoints) GetNamespace() string { return e.Endpoints.GetNamespace() }
// SetNamespace implements the metav1.Object interface.
func (e *Endpoints) SetNamespace(namespace string) {}
// GetName implements the metav1.Object interface.
func (e *Endpoints) GetName() string { return e.Name }
func (e *Endpoints) GetName() string { return e.Endpoints.GetName() }
// SetName implements the metav1.Object interface.
func (e *Endpoints) SetName(name string) {}
// GetResourceVersion implements the metav1.Object interface.
func (e *Endpoints) GetResourceVersion() string { return e.Version }
func (e *Endpoints) GetResourceVersion() string { return e.Endpoints.GetResourceVersion() }
// SetResourceVersion implements the metav1.Object interface.
func (e *Endpoints) SetResourceVersion(version string) {}

View File

@ -1,61 +0,0 @@
package object
import (
"fmt"
api "k8s.io/api/core/v1"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
// Namespace is a stripped down api.Namespace with only the items we need for CoreDNS.
type Namespace struct {
// Don't add new fields to this struct without talking to the CoreDNS maintainers.
Version string
Name string
*Empty
}
// ToNamespace returns a function that converts an api.Namespace to a *Namespace.
func ToNamespace(obj meta.Object) (meta.Object, error) {
ns, ok := obj.(*api.Namespace)
if !ok {
return nil, fmt.Errorf("unexpected object %v", obj)
}
n := &Namespace{
Version: ns.GetResourceVersion(),
Name: ns.GetName(),
}
*ns = api.Namespace{}
return n, nil
}
var _ runtime.Object = &Namespace{}
// DeepCopyObject implements the ObjectKind interface.
func (n *Namespace) DeepCopyObject() runtime.Object {
n1 := &Namespace{
Version: n.Version,
Name: n.Name,
}
return n1
}
// GetNamespace implements the metav1.Object interface.
func (n *Namespace) GetNamespace() string { return "" }
// SetNamespace implements the metav1.Object interface.
func (n *Namespace) SetNamespace(namespace string) {}
// GetName implements the metav1.Object interface.
func (n *Namespace) GetName() string { return n.Name }
// SetName implements the metav1.Object interface.
func (n *Namespace) SetName(name string) {}
// GetResourceVersion implements the metav1.Object interface.
func (n *Namespace) GetResourceVersion() string { return n.Version }
// SetResourceVersion implements the metav1.Object interface.
func (n *Namespace) SetResourceVersion(version string) {}

View File

@ -1,119 +0,0 @@
// Package object holds functions that convert the objects from the k8s API in
// to a more memory efficient structures.
//
// Adding new fields to any of the structures defined in pod.go, endpoint.go
// and service.go should not be done lightly as this increases the memory use
// and will leads to OOMs in the k8s scale test.
//
// We can do some optimizations here as well. We store IP addresses as strings,
// this might be moved to uint32 (for v4) for instance, but then we need to
// convert those again.
//
// Also the msg.Service use in this plugin may be deprecated at some point, as
// we don't use most of those features anyway and would free us from the *etcd*
// dependency, where msg.Service is defined. And should save some mem/cpu as we
// convert to and from msg.Services.
package object
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/cache"
)
// ToFunc converts one v1.Object to another v1.Object.
type ToFunc func(v1.Object) (v1.Object, error)
// ProcessorBuilder returns function to process cache events.
type ProcessorBuilder func(cache.Indexer, cache.ResourceEventHandler) cache.ProcessFunc
// Empty is an empty struct.
type Empty struct{}
// GetObjectKind implements the ObjectKind interface as a noop.
func (e *Empty) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
// GetGenerateName implements the metav1.Object interface.
func (e *Empty) GetGenerateName() string { return "" }
// SetGenerateName implements the metav1.Object interface.
func (e *Empty) SetGenerateName(name string) {}
// GetUID implements the metav1.Object interface.
func (e *Empty) GetUID() types.UID { return "" }
// SetUID implements the metav1.Object interface.
func (e *Empty) SetUID(uid types.UID) {}
// GetGeneration implements the metav1.Object interface.
func (e *Empty) GetGeneration() int64 { return 0 }
// SetGeneration implements the metav1.Object interface.
func (e *Empty) SetGeneration(generation int64) {}
// GetSelfLink implements the metav1.Object interface.
func (e *Empty) GetSelfLink() string { return "" }
// SetSelfLink implements the metav1.Object interface.
func (e *Empty) SetSelfLink(selfLink string) {}
// GetCreationTimestamp implements the metav1.Object interface.
func (e *Empty) GetCreationTimestamp() v1.Time { return v1.Time{} }
// SetCreationTimestamp implements the metav1.Object interface.
func (e *Empty) SetCreationTimestamp(timestamp v1.Time) {}
// GetDeletionTimestamp implements the metav1.Object interface.
func (e *Empty) GetDeletionTimestamp() *v1.Time { return &v1.Time{} }
// SetDeletionTimestamp implements the metav1.Object interface.
func (e *Empty) SetDeletionTimestamp(timestamp *v1.Time) {}
// GetDeletionGracePeriodSeconds implements the metav1.Object interface.
func (e *Empty) GetDeletionGracePeriodSeconds() *int64 { return nil }
// SetDeletionGracePeriodSeconds implements the metav1.Object interface.
func (e *Empty) SetDeletionGracePeriodSeconds(*int64) {}
// GetLabels implements the metav1.Object interface.
func (e *Empty) GetLabels() map[string]string { return nil }
// SetLabels implements the metav1.Object interface.
func (e *Empty) SetLabels(labels map[string]string) {}
// GetAnnotations implements the metav1.Object interface.
func (e *Empty) GetAnnotations() map[string]string { return nil }
// SetAnnotations implements the metav1.Object interface.
func (e *Empty) SetAnnotations(annotations map[string]string) {}
// GetFinalizers implements the metav1.Object interface.
func (e *Empty) GetFinalizers() []string { return nil }
// SetFinalizers implements the metav1.Object interface.
func (e *Empty) SetFinalizers(finalizers []string) {}
// GetOwnerReferences implements the metav1.Object interface.
func (e *Empty) GetOwnerReferences() []v1.OwnerReference { return nil }
// SetOwnerReferences implements the metav1.Object interface.
func (e *Empty) SetOwnerReferences([]v1.OwnerReference) {}
// GetClusterName implements the metav1.Object interface.
func (e *Empty) GetClusterName() string { return "" }
// SetClusterName implements the metav1.Object interface.
func (e *Empty) SetClusterName(clusterName string) {}
// GetZZZ_DeprecatedClusterName implements the metav1.Object interface.
func (e *Empty) GetZZZ_DeprecatedClusterName() string { return "" }
// SetZZZ_DeprecatedClusterName implements the metav1.Object interface.
func (e *Empty) SetZZZ_DeprecatedClusterName(clusterName string) {}
// GetManagedFields implements the metav1.Object interface.
func (e *Empty) GetManagedFields() []v1.ManagedFieldsEntry { return nil }
// SetManagedFields implements the metav1.Object interface.
func (e *Empty) SetManagedFields(managedFields []v1.ManagedFieldsEntry) {}

View File

@ -2,21 +2,22 @@ package object
import (
"fmt"
"github.com/coredns/coredns/plugin/kubernetes/object"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
v1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
mcs "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
)
// ServiceImport is a stripped down api.ServiceImport with only the items we need for CoreDNS.
type ServiceImport struct {
Version string
Name string
Namespace string
Index string
ClusterIPs []string
Type v1alpha1.ServiceImportType
Ports []v1alpha1.ServicePort
Version string
Name string
Namespace string
Index string
ClusterIPs []string
Type mcs.ServiceImportType
Ports []mcs.ServicePort
*object.Empty
}
@ -26,17 +27,17 @@ func ServiceKey(name, namespace string) string { return name + "." + namespace }
// ToServiceImport converts an v1alpha1.ServiceImport to a *ServiceImport.
func ToServiceImport(obj meta.Object) (meta.Object, error) {
svc, ok := obj.(*v1alpha1.ServiceImport)
svc, ok := obj.(*mcs.ServiceImport)
if !ok {
return nil, fmt.Errorf("unexpected object %v", obj)
}
s := &ServiceImport{
Version: svc.GetResourceVersion(),
Name: svc.GetName(),
Namespace: svc.GetNamespace(),
Index: ServiceKey(svc.GetName(), svc.GetNamespace()),
Type: svc.Spec.Type,
Version: svc.GetResourceVersion(),
Name: svc.GetName(),
Namespace: svc.GetNamespace(),
Index: ServiceKey(svc.GetName(), svc.GetNamespace()),
Type: svc.Spec.Type,
}
if len(svc.Spec.IPs) > 0 {
@ -45,7 +46,7 @@ func ToServiceImport(obj meta.Object) (meta.Object, error) {
}
if len(svc.Spec.Ports) > 0 {
s.Ports = make([]v1alpha1.ServicePort, len(svc.Spec.Ports))
s.Ports = make([]mcs.ServicePort, len(svc.Spec.Ports))
copy(s.Ports, svc.Spec.Ports)
}
@ -57,13 +58,13 @@ var _ runtime.Object = &ServiceImport{}
// DeepCopyObject implements the ObjectKind interface.
func (s *ServiceImport) DeepCopyObject() runtime.Object {
s1 := &ServiceImport{
Version: s.Version,
Name: s.Name,
Namespace: s.Namespace,
Index: s.Index,
Type: s.Type,
ClusterIPs: make([]string, len(s.ClusterIPs)),
Ports: make([]v1alpha1.ServicePort, len(s.Ports)),
Version: s.Version,
Name: s.Name,
Namespace: s.Namespace,
Index: s.Index,
Type: s.Type,
ClusterIPs: make([]string, len(s.ClusterIPs)),
Ports: make([]mcs.ServicePort, len(s.Ports)),
}
copy(s1.ClusterIPs, s.ClusterIPs)
copy(s1.Ports, s.Ports)

View File

@ -1,9 +1,10 @@
package multicluster
import (
"github.com/coredns/coredns/plugin/pkg/dnsutil"
"strings"
"github.com/coredns/coredns/plugin/pkg/dnsutil"
"github.com/miekg/dns"
)

View File

@ -2,6 +2,7 @@ package multicluster
import (
"context"
"github.com/coredns/caddy"
"github.com/coredns/coredns/core/dnsserver"
"github.com/coredns/coredns/plugin"

View File

@ -1,10 +1,11 @@
package multicluster
import (
"github.com/coredns/caddy"
"github.com/coredns/coredns/plugin/pkg/fall"
"strings"
"testing"
"github.com/coredns/caddy"
"github.com/coredns/coredns/plugin/pkg/fall"
)
func TestParseStanza(t *testing.T) {