Files
coredns/plugin/kubernetes/object/pod.go
Christian Menges 2e2324715b plugin/kubernetes: support pods with multiple IPs (#8635)
The Pod object stored only the primary pod IP (status.podIP), causing
PodIndex lookups to fail for IPv6 clients in dual-stack clusters. This
prevented the metadata plugin from populating client-pod-name and
client-namespace.

Replace the PodIP string field with a PodIPs []string slice populated
from status.podIPs, and update podIPIndexFunc to index all IPs.

Signed-off-by: Christian Norbert Menges <christian.norbert.menges@sap.com>
2026-10-15 01:12:29 -07:00

89 lines
2.3 KiB
Go

package object
import (
"errors"
"fmt"
"maps"
"slices"
api "k8s.io/api/core/v1"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
// Pod is a stripped down api.Pod with only the items we need for CoreDNS.
type Pod struct {
// Don't add new fields to this struct without talking to the CoreDNS maintainers.
Version string
PodIPs []string
Name string
Namespace string
Labels map[string]string
*Empty
}
var errPodTerminating = errors.New("pod terminating")
// ToPod converts an api.Pod to a *Pod.
func ToPod(obj meta.Object) (meta.Object, error) {
apiPod, ok := obj.(*api.Pod)
if !ok {
return nil, fmt.Errorf("unexpected object %v", obj)
}
podIPs := make([]string, len(apiPod.Status.PodIPs))
for i, pip := range apiPod.Status.PodIPs {
podIPs[i] = pip.IP
}
pod := &Pod{
Version: apiPod.GetResourceVersion(),
PodIPs: podIPs,
Namespace: apiPod.GetNamespace(),
Name: apiPod.GetName(),
Labels: apiPod.GetLabels(),
}
t := apiPod.DeletionTimestamp
if t != nil && !(*t).Time.IsZero() {
// if the pod is in the process of termination, return an error so it can be ignored
// during add/update event processing
return pod, errPodTerminating
}
*apiPod = api.Pod{}
return pod, nil
}
var _ runtime.Object = &Pod{}
// DeepCopyObject implements the ObjectKind interface.
func (p *Pod) DeepCopyObject() runtime.Object {
p1 := &Pod{
Version: p.Version,
PodIPs: slices.Clone(p.PodIPs),
Namespace: p.Namespace,
Name: p.Name,
// maps.Clone returns nil for a nil map, so an unlabelled pod stays unlabelled.
Labels: maps.Clone(p.Labels),
}
return p1
}
// GetNamespace implements the metav1.Object interface.
func (p *Pod) GetNamespace() string { return p.Namespace }
// SetNamespace implements the metav1.Object interface.
func (p *Pod) SetNamespace(_namespace string) {}
// GetName implements the metav1.Object interface.
func (p *Pod) GetName() string { return p.Name }
// SetName implements the metav1.Object interface.
func (p *Pod) SetName(_name string) {}
// GetResourceVersion implements the metav1.Object interface.
func (p *Pod) GetResourceVersion() string { return p.Version }
// SetResourceVersion implements the metav1.Object interface.
func (p *Pod) SetResourceVersion(_version string) {}