diff --git a/config/crd/bases/boot.ironcore.dev_httpbootconfigs.yaml b/config/crd/bases/boot.ironcore.dev_httpbootconfigs.yaml index 670616d..4ed47cb 100644 --- a/config/crd/bases/boot.ironcore.dev_httpbootconfigs.yaml +++ b/config/crd/bases/boot.ironcore.dev_httpbootconfigs.yaml @@ -52,10 +52,15 @@ spec: referenced object inside the same namespace. properties: name: + default: "" description: |- Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string type: object x-kubernetes-map-type: atomic diff --git a/config/crd/bases/boot.ironcore.dev_ipxebootconfigs.yaml b/config/crd/bases/boot.ironcore.dev_ipxebootconfigs.yaml index a4d42a2..621fde9 100644 --- a/config/crd/bases/boot.ironcore.dev_ipxebootconfigs.yaml +++ b/config/crd/bases/boot.ironcore.dev_ipxebootconfigs.yaml @@ -52,10 +52,15 @@ spec: referenced object inside the same namespace. properties: name: + default: "" description: |- Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string type: object x-kubernetes-map-type: atomic diff --git a/server/bootserver.go b/server/bootserver.go index d947a95..0c2b226 100644 --- a/server/bootserver.go +++ b/server/bootserver.go @@ -9,6 +9,7 @@ import ( "net/http" "path" "path/filepath" + "strings" "text/template" corev1 "k8s.io/api/core/v1" @@ -73,11 +74,30 @@ func handleIPXE(w http.ResponseWriter, r *http.Request, k8sClient client.Client, return } + clientIPs := []string{} + clientIPs = append(clientIPs, clientIP) + + // Attempt to extract IPs from X-Forwarded-For if present + if xff := r.Header.Get("X-Forwarded-For"); xff != "" { + for _, ip := range strings.Split(xff, ",") { + trimmedIP := strings.TrimSpace(ip) + if trimmedIP != "" { + clientIPs = append(clientIPs, trimmedIP) + } + } + } + var ipxeConfigs bootv1alpha1.IPXEBootConfigList - if err := k8sClient.List(ctx, &ipxeConfigs, client.MatchingFields{"spec.systemIP": clientIP}); err != nil { - log.Info("Failed to list IPXEBootConfig", "error", err) - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return + for _, ip := range clientIPs { + if err := k8sClient.List(ctx, &ipxeConfigs, client.MatchingFields{"spec.systemIP": ip}); err != nil { + log.Info("Failed to list IPXEBootConfig for IP", "IP", ip, "error", err) + continue + } + + if len(ipxeConfigs.Items) > 0 { + log.Info("Found IPXEBootConfig", "IP", ip) + break + } } data := defaultIpxeTemplateData