ExecCommand executes a command inside the pod, automatically retrying transient errors like proxy failures or network issues.
( ctx context.Context, client kubernetes.Interface, config *rest.Config, pod corev1.Pod, containerName string, timeout *time.Duration, command ...string, )
| 95 | // ExecCommand executes a command inside the pod, automatically retrying |
| 96 | // transient errors like proxy failures or network issues. |
| 97 | func ExecCommand( |
| 98 | ctx context.Context, |
| 99 | client kubernetes.Interface, |
| 100 | config *rest.Config, |
| 101 | pod corev1.Pod, |
| 102 | containerName string, |
| 103 | timeout *time.Duration, |
| 104 | command ...string, |
| 105 | ) (string, string, error) { |
| 106 | contextLogger := log.FromContext(ctx).WithValues( |
| 107 | "pod", pod.Name, |
| 108 | "namespace", pod.Namespace, |
| 109 | "container", containerName, |
| 110 | ) |
| 111 | |
| 112 | targetContainer := -1 |
| 113 | for i, cr := range pod.Spec.Containers { |
| 114 | if cr.Name == containerName { |
| 115 | targetContainer = i |
| 116 | break |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | if targetContainer < 0 { |
| 121 | return "", "", ErrorContainerNotFound |
| 122 | } |
| 123 | |
| 124 | execCtx := ctx |
| 125 | var cancelFunc context.CancelFunc |
| 126 | if timeout != nil { |
| 127 | execCtx, cancelFunc = context.WithTimeout(ctx, *timeout) |
| 128 | defer cancelFunc() |
| 129 | } |
| 130 | |
| 131 | var stdout, stderr string |
| 132 | var execErr error |
| 133 | |
| 134 | _ = retry.New( |
| 135 | retry.Attempts(execRetryAttempts), |
| 136 | retry.Delay(execRetryDelay), |
| 137 | retry.DelayType(retry.BackOffDelay), |
| 138 | retry.Context(execCtx), |
| 139 | retry.LastErrorOnly(true), |
| 140 | retry.OnRetry(func(n uint, err error) { |
| 141 | contextLogger.Info("Retrying kubectl exec", |
| 142 | "attempt", n+1, |
| 143 | "error", err.Error(), |
| 144 | ) |
| 145 | }), |
| 146 | ).Do( |
| 147 | func() error { |
| 148 | stdout, stderr, execErr = execCommandOnce( |
| 149 | execCtx, client, config, pod, |
| 150 | targetContainer, timeout, command..., |
| 151 | ) |
| 152 | |
| 153 | // Don't retry if context was cancelled or timed out |
| 154 | if execCtx.Err() != nil { |
no test coverage detected