coredns/plugin/kubernetes/object/endpoint.go
janluk d7cdb992b4 Measure and expose DNS programming latency from Kubernetes plugin. ()
For now metric is measure only for headless services. Informer has been slighlty
refactored, so the code can measure latency without storing extra fields on
Endpoint struct.

Signed-off-by: Janek Łukaszewicz <janluk@google.com>

Suggestions from code review

Co-Authored-By: Chris O'Haver <cohaver@infoblox.com>
2019-10-04 16:48:43 +01:00

161 lines
4.2 KiB
Go

package object
import (
api "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
)
// 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
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
}
// EndpointsKey return a string using for the index.
func EndpointsKey(name, namespace string) string { return name + "." + namespace }
// ToEndpoints converts an api.Endpoints to a *Endpoints.
func ToEndpoints(obj interface{}) (*api.Endpoints, *Endpoints) {
end, ok := obj.(*api.Endpoints)
if !ok {
return nil, nil
}
e := &Endpoints{
Version: end.GetResourceVersion(),
Name: end.GetName(),
Namespace: end.GetNamespace(),
Index: EndpointsKey(end.GetName(), end.GetNamespace()),
Subsets: make([]EndpointSubset, len(end.Subsets)),
}
for i, eps := range end.Subsets {
sub := EndpointSubset{
Addresses: make([]EndpointAddress, len(eps.Addresses)),
}
if len(eps.Ports) == 0 {
// Add sentinel if there are no ports.
sub.Ports = []EndpointPort{{Port: -1}}
} else {
sub.Ports = make([]EndpointPort, len(eps.Ports))
}
for j, a := range eps.Addresses {
ea := EndpointAddress{IP: a.IP, Hostname: a.Hostname}
if a.NodeName != nil {
ea.NodeName = *a.NodeName
}
if a.TargetRef != nil {
ea.TargetRefName = a.TargetRef.Name
}
sub.Addresses[j] = ea
}
for k, p := range eps.Ports {
ep := EndpointPort{Port: p.Port, Name: p.Name, Protocol: string(p.Protocol)}
sub.Ports[k] = ep
}
e.Subsets[i] = sub
}
for _, eps := range end.Subsets {
for _, a := range eps.Addresses {
e.IndexIP = append(e.IndexIP, a.IP)
}
}
return end, e
}
// 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
}
return e1
}
// GetNamespace implements the metav1.Object interface.
func (e *Endpoints) GetNamespace() string { return e.Namespace }
// 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 }
// 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 }
// SetResourceVersion implements the metav1.Object interface.
func (e *Endpoints) SetResourceVersion(version string) {}