Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion e2e/pkg/tests/policy/staged_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ var _ = describe.CalicoDescribe(
stopCh = make(chan time.Time, 1)

// We read flow logs from whisker-backend, we start port forward so we can query the flows
localPort, err := kubectl.PortForward("calico-system", "deployment/whisker", "3002", "", stopCh)
localPort, _, err := kubectl.PortForward("calico-system", "deployment/whisker", "3002", "", stopCh)
Expect(err).NotTo(HaveOccurred())

// Build url to get flows from whisker
Expand Down
16 changes: 9 additions & 7 deletions e2e/pkg/utils/kubectl.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,27 @@ func (k *Kubectl) Wait(kind, ns, name, user, condition string, timeout time.Dura
}

// PortForward starts a kubectl port-forward in the background, allocating a random
// local port to avoid conflicts when tests run in parallel. It returns the local port.
func (k *Kubectl) PortForward(ns, pod, remotePort, user string, timeOut chan time.Time) (int, error) {
// local port to avoid conflicts when tests run in parallel. It returns the local port
// and a channel that receives an error (or nil) when the port-forward process exits.
// Callers can select on the channel to detect unexpected port-forward termination.
func (k *Kubectl) PortForward(ns, pod, remotePort, user string, timeOut chan time.Time) (int, <-chan error, error) {
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

timeOut is declared as a bidirectional chan time.Time, but PortForward never sends on it (it only passes it to WithTimeout). Keeping it bidirectional unnecessarily restricts callers (e.g., you can’t pass <-chan time.Time values like time.After(...) directly) and weakens the API contract. Consider changing the parameter type to <-chan time.Time (and adjusting the call sites accordingly).

Suggested change
func (k *Kubectl) PortForward(ns, pod, remotePort, user string, timeOut chan time.Time) (int, <-chan error, error) {
func (k *Kubectl) PortForward(ns, pod, remotePort, user string, timeOut <-chan time.Time) (int, <-chan error, error) {

Copilot uses AI. Check for mistakes.
localPort, err := getFreePort()
if err != nil {
return 0, fmt.Errorf("failed to allocate local port: %w", err)
return 0, nil, fmt.Errorf("failed to allocate local port: %w", err)
}

options := []string{"port-forward", pod, fmt.Sprintf("%d:%s", localPort, remotePort)}
if user != "" {
options = append(options, fmt.Sprintf("--as=%v", user))
}

errCh := make(chan error, 1)
go func() {
defer close(errCh)
_, err := kubectl.NewKubectlCommand(ns, options...).WithTimeout(timeOut).Exec()
if err != nil {
return
}
errCh <- err
}()
return localPort, nil
return localPort, errCh, nil
}

func getFreePort() (int, error) {
Expand Down
Loading