From cc4666cc94be41d8b4558122717a2da9fb5a7b1a Mon Sep 17 00:00:00 2001 From: Ondra Kupka Date: Fri, 18 Jul 2025 23:35:24 +0200 Subject: [PATCH] kubectl/logs: Add LogOptions.RunLogsContext LogOptions.RunLogs unfortunately registers a signal handler and calls os.Exit(1) after finished processing when a signal is received. This makes it basically impossible to call that function from any custom code. This patch adds RunLogsContext, which does exactly what RunLogs does, but the context to be used is passed in. RunLogs retains the current contract, but it uses RunLogsContext internally, then calls os.Exit(1) when a signal is received. --- .../src/k8s.io/kubectl/pkg/cmd/logs/logs.go | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/logs/logs.go b/staging/src/k8s.io/kubectl/pkg/cmd/logs/logs.go index e7f9bd391ec..c7c31ae4c9c 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/logs/logs.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/logs/logs.go @@ -356,8 +356,21 @@ func (o LogsOptions) Validate() error { return nil } -// RunLogs retrieves a pod log +// RunLogs wraps RunLogsContext with signal handling. +// When a signal is received, streaming is stopped, then followed by os.Exit(1). func (o LogsOptions) RunLogs() error { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + intr := interrupt.New(nil, cancel) + return intr.Run(func() error { + return o.RunLogsContext(ctx) + }) +} + +// RunLogsContext retrieves a pod log. +// +// This function does not handle signals. To interrupt streaming, cancel the context. +func (o LogsOptions) RunLogsContext(ctx context.Context) error { var requests map[corev1.ObjectReference]rest.ResponseWrapper var err error if o.AllPods { @@ -378,16 +391,10 @@ func (o LogsOptions) RunLogs() error { } } - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - intr := interrupt.New(nil, cancel) - return intr.Run(func() error { - if o.Follow && len(requests) > 1 { - return o.parallelConsumeRequest(ctx, requests) - } - - return o.sequentialConsumeRequest(ctx, requests) - }) + if o.Follow && len(requests) > 1 { + return o.parallelConsumeRequest(ctx, requests) + } + return o.sequentialConsumeRequest(ctx, requests) } func (o LogsOptions) parallelConsumeRequest(ctx context.Context, requests map[corev1.ObjectReference]rest.ResponseWrapper) error {