|
|
|
|
@ -18,6 +18,7 @@ package action
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
|
|
|
|
"slices"
|
|
|
|
|
@ -25,6 +26,8 @@ import (
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
v1 "k8s.io/api/core/v1"
|
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
|
"k8s.io/client-go/kubernetes"
|
|
|
|
|
|
|
|
|
|
chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
|
|
|
|
|
"helm.sh/helm/v4/pkg/kube"
|
|
|
|
|
@ -124,9 +127,9 @@ func (r *ReleaseTesting) GetPodLogs(out io.Writer, rel *release.Release) error {
|
|
|
|
|
return fmt.Errorf("unable to get kubernetes client to fetch pod logs: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hooksByWight := append([]*release.Hook{}, rel.Hooks...)
|
|
|
|
|
sort.Stable(hookByWeight(hooksByWight))
|
|
|
|
|
for _, h := range hooksByWight {
|
|
|
|
|
hooksByWeight := append([]*release.Hook{}, rel.Hooks...)
|
|
|
|
|
sort.Stable(hookByWeight(hooksByWeight))
|
|
|
|
|
for _, h := range hooksByWeight {
|
|
|
|
|
for _, e := range h.Events {
|
|
|
|
|
if e == release.HookTest {
|
|
|
|
|
if slices.Contains(r.Filters[ExcludeNameFilter], h.Name) {
|
|
|
|
|
@ -135,20 +138,43 @@ func (r *ReleaseTesting) GetPodLogs(out io.Writer, rel *release.Release) error {
|
|
|
|
|
if len(r.Filters[IncludeNameFilter]) > 0 && !slices.Contains(r.Filters[IncludeNameFilter], h.Name) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
req := client.CoreV1().Pods(r.Namespace).GetLogs(h.Name, &v1.PodLogOptions{})
|
|
|
|
|
logReader, err := req.Stream(context.Background())
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("unable to get pod logs for %s: %w", h.Name, err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fmt.Fprintf(out, "POD LOGS: %s\n", h.Name)
|
|
|
|
|
_, err = io.Copy(out, logReader)
|
|
|
|
|
fmt.Fprintln(out)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("unable to write pod logs for %s: %w", h.Name, err)
|
|
|
|
|
if err := r.getContainerLogs(out, client, h.Name); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getContainerLogs fetches logs from all containers (init and regular) in the
|
|
|
|
|
// named pod and writes them to out. It continues on per-container errors and
|
|
|
|
|
// returns all of them joined at the end.
|
|
|
|
|
func (r *ReleaseTesting) getContainerLogs(out io.Writer, client kubernetes.Interface, podName string) error {
|
|
|
|
|
pod, err := client.CoreV1().Pods(r.Namespace).Get(context.Background(), podName, metav1.GetOptions{})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("unable to get pod %s: %w", podName, err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
allContainers := append(pod.Spec.InitContainers, pod.Spec.Containers...)
|
|
|
|
|
|
|
|
|
|
var errs []error
|
|
|
|
|
for _, c := range allContainers {
|
|
|
|
|
opts := &v1.PodLogOptions{Container: c.Name}
|
|
|
|
|
req := client.CoreV1().Pods(r.Namespace).GetLogs(podName, opts)
|
|
|
|
|
logReader, err := req.Stream(context.Background())
|
|
|
|
|
if err != nil {
|
|
|
|
|
errs = append(errs, fmt.Errorf("unable to get logs for pod %s, container %s: %w", podName, c.Name, err))
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fmt.Fprintf(out, "POD LOGS: %s (%s)\n", podName, c.Name)
|
|
|
|
|
_, err = io.Copy(out, logReader)
|
|
|
|
|
logReader.Close()
|
|
|
|
|
fmt.Fprintln(out)
|
|
|
|
|
if err != nil {
|
|
|
|
|
errs = append(errs, fmt.Errorf("unable to write logs for pod %s, container %s: %w", podName, c.Name, err))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return errors.Join(errs...)
|
|
|
|
|
}
|
|
|
|
|
|