This is an automated email from the ASF dual-hosted git repository. astefanutti pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 3a6651f878676791d407ad56beed41bb57ac481b Author: Antonin Stefanutti <anto...@stefanutti.fr> AuthorDate: Fri Nov 12 11:44:20 2021 +0100 chore(heath): Extract port number from readiness probe before proxying via API server --- pkg/controller/integration/health.go | 45 +++++++++++++++++++++++++++++++++-- pkg/controller/integration/monitor.go | 2 +- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/pkg/controller/integration/health.go b/pkg/controller/integration/health.go index e14d241..e56b10a 100644 --- a/pkg/controller/integration/health.go +++ b/pkg/controller/integration/health.go @@ -20,10 +20,12 @@ package integration import ( "context" "fmt" + "strconv" "strings" "time" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes" ) @@ -45,15 +47,54 @@ type HealthCheckResponse struct { Data map[string]interface{} `json:"data,omitempty"` } -func proxyGetHTTPProbe(ctx context.Context, c kubernetes.Interface, p *corev1.Probe, pod *corev1.Pod) ([]byte, error) { +func proxyGetHTTPProbe(ctx context.Context, c kubernetes.Interface, p *corev1.Probe, pod *corev1.Pod, container *corev1.Container) ([]byte, error) { if p.HTTPGet == nil { return nil, fmt.Errorf("missing probe handler for %s/%s", pod.Namespace, pod.Name) } + // We have to extract the port number from the HTTP probe in case it's a named port, + // as Pod proxying via the API Server does not work with named ports. + port, err := extractPortNumber(p.HTTPGet.Port, container) + if err != nil { + return nil, err + } + probeCtx, cancel := context.WithTimeout(ctx, time.Duration(p.TimeoutSeconds)*time.Second) defer cancel() params := make(map[string]string) return c.CoreV1().Pods(pod.Namespace). - ProxyGet(strings.ToLower(string(p.HTTPGet.Scheme)), pod.Name, p.HTTPGet.Port.String(), p.HTTPGet.Path, params). + ProxyGet(strings.ToLower(string(p.HTTPGet.Scheme)), pod.Name, strconv.Itoa(port), p.HTTPGet.Path, params). DoRaw(probeCtx) } + +func extractPortNumber(port intstr.IntOrString, container *corev1.Container) (int, error) { + number := -1 + var err error + switch port.Type { + case intstr.Int: + number = port.IntValue() + case intstr.String: + if number, err = findPortByName(container, port.StrVal); err != nil { + // Last ditch effort - maybe it was an int stored as string? + if number, err = strconv.Atoi(port.StrVal); err != nil { + return number, err + } + } + default: + return number, fmt.Errorf("intOrString had no kind: %+v", port) + } + if number > 0 && number < 65536 { + return number, nil + } + return number, fmt.Errorf("invalid port number: %v", number) +} + +// findPortByName is a helper function to look up a port in a container by name. +func findPortByName(container *corev1.Container, portName string) (int, error) { + for _, port := range container.Ports { + if port.Name == portName { + return int(port.ContainerPort), nil + } + } + return 0, fmt.Errorf("port %s not found", portName) +} diff --git a/pkg/controller/integration/monitor.go b/pkg/controller/integration/monitor.go index d4bd5ab..08ee93d 100644 --- a/pkg/controller/integration/monitor.go +++ b/pkg/controller/integration/monitor.go @@ -368,7 +368,7 @@ func (action *monitorAction) updateIntegrationPhaseAndReadyCondition(ctx context return fmt.Errorf("integration container not found in Pod %s/%s", pod.Namespace, pod.Name) } if probe := container.ReadinessProbe; probe != nil && probe.HTTPGet != nil { - body, err := proxyGetHTTPProbe(ctx, action.client, probe, &pod) + body, err := proxyGetHTTPProbe(ctx, action.client, probe, &pod, container) if err == nil { continue }