diff --git a/pkg/dev/podmandev/reconcile.go b/pkg/dev/podmandev/reconcile.go index 0d6511d0b7b..779b6a8b111 100644 --- a/pkg/dev/podmandev/reconcile.go +++ b/pkg/dev/podmandev/reconcile.go @@ -2,6 +2,7 @@ package podmandev import ( "context" + "errors" "fmt" "io" "path/filepath" @@ -18,6 +19,7 @@ import ( "github.com/redhat-developer/odo/pkg/libdevfile" "github.com/redhat-developer/odo/pkg/log" odocontext "github.com/redhat-developer/odo/pkg/odo/context" + "github.com/redhat-developer/odo/pkg/port" "github.com/redhat-developer/odo/pkg/watch" corev1 "k8s.io/api/core/v1" @@ -113,6 +115,29 @@ func (o *DevClient) reconcile( componentStatus.RunExecuted = true } + // By default, Podman will not forward to container applications listening on the loopback interface. + // So we are trying to detect such cases accordingly. + // See https://github.com/redhat-developer/odo/issues/6510#issuecomment-1439986558 + loopbackPorts, err := port.DetectRemotePortsBoundOnLoopback(o.execClient, pod.Name, pod.Spec.Containers[0].Name, fwPorts) + if err != nil { + return fmt.Errorf("unable to detect container ports bound on the loopback interface: %w", err) + } + klog.V(4).Infof("detected %d ports bound on the loopback interface in the pod: %v", len(loopbackPorts), loopbackPorts) + + if len(loopbackPorts) != 0 { + list := make([]string, 0, len(loopbackPorts)) + for _, p := range loopbackPorts { + list = append(list, fmt.Sprintf("%s (%d)", p.PortName, p.ContainerPort)) + } + + log.Errorf(`Detected that the following port(s) can be reached only via the container loopback interface: %s. +Port forwarding on Podman currently does not work with applications listening on the loopback interface. +Either change the application to make those port(s) reachable on all interfaces (0.0.0.0), or rerun 'odo dev' with any of the following options: +- --ignore-localhost: no error will be returned by odo, but port-forwarding on those ports might not work on Podman. +- --forward-localhost: odo will inject a dedicated side container to redirect traffic to such ports.`, strings.Join(list, ", ")) + return errors.New("cannot make port forwarding work with ports bound to the loopback interface only") + } + for _, fwPort := range fwPorts { s := fmt.Sprintf("Forwarding from %s:%d -> %d", fwPort.LocalAddress, fwPort.LocalPort, fwPort.ContainerPort) fmt.Fprintf(out, " - %s", log.SboldColor(color.FgGreen, s))