diff --git a/controlplane/kubeadm/internal/proxy/dial.go b/controlplane/kubeadm/internal/proxy/dial.go index def43e207ae4..f30ced0bb697 100644 --- a/controlplane/kubeadm/internal/proxy/dial.go +++ b/controlplane/kubeadm/internal/proxy/dial.go @@ -83,8 +83,14 @@ func (d *Dialer) DialContextWithAddr(ctx context.Context, addr string) (net.Conn } // DialContext creates proxied port-forwarded connections. -// ctx is currently unused, but fulfils the type signature used by GRPC. -func (d *Dialer) DialContext(_ context.Context, _ string, addr string) (net.Conn, error) { +func (d *Dialer) DialContext(ctx context.Context, _ string, addr string) (net.Conn, error) { + // Check if context is already cancelled or timed out + select { + case <-ctx.Done(): + return nil, errors.Wrap(ctx.Err(), "context cancelled before establishing connection") + default: + } + req := d.clientset.CoreV1().RESTClient(). Post(). Resource(d.proxy.Kind). @@ -92,7 +98,15 @@ func (d *Dialer) DialContext(_ context.Context, _ string, addr string) (net.Conn Name(addr). SubResource("portforward") - dialer := spdy.NewDialer(d.upgrader, &http.Client{Transport: d.proxyTransport}, "POST", req.URL()) + httpClient := &http.Client{ + Transport: d.proxyTransport, + } + + if deadline, ok := ctx.Deadline(); ok { + httpClient.Timeout = time.Until(deadline) + } + + dialer := spdy.NewDialer(d.upgrader, httpClient, "POST", req.URL()) // Create a new connection from the dialer. // diff --git a/controlplane/kubeadm/internal/workload_cluster.go b/controlplane/kubeadm/internal/workload_cluster.go index a2d3e3c6a2bf..901cf53391c5 100644 --- a/controlplane/kubeadm/internal/workload_cluster.go +++ b/controlplane/kubeadm/internal/workload_cluster.go @@ -318,6 +318,10 @@ func (w *Workload) ClusterStatus(ctx context.Context) (ClusterStatus, error) { // GetAPIServerCertificateExpiry returns the certificate expiry of the apiserver on the given node. func (w *Workload) GetAPIServerCertificateExpiry(ctx context.Context, kubeadmConfig *bootstrapv1.KubeadmConfig, nodeName string) (*time.Time, error) { + // Create a context with 15 second timeout + ctx, cancel := context.WithTimeoutCause(ctx, 15*time.Second, errors.New("timeout getting API server certificate expiry")) + defer cancel() + // Create a proxy. p := proxy.Proxy{ Kind: "pods",