feat: helm test --logs, support outputing logs only from failed pods, succeeded pods, or all pods.

helm test --logs all (default) // output logs of all pods
helm test --logs failed  // only output logs of failed pods
helm test --logs succeeded // only output logs of succeeded pods

Signed-off-by: Zhenghao Lou <rhzx3519@gmail.com>
pull/11952/head
Zhenghao Lou 3 years ago
parent 952708b436
commit dc9ca9c23b

@ -40,7 +40,7 @@ The tests to be run are defined in the chart that was installed.
func newReleaseTestCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { func newReleaseTestCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
client := action.NewReleaseTesting(cfg) client := action.NewReleaseTesting(cfg)
var outfmt = output.Table var outfmt = output.Table
var outputLogs bool var outputLogs string
var filter []string var filter []string
cmd := &cobra.Command{ cmd := &cobra.Command{
@ -76,10 +76,16 @@ func newReleaseTestCmd(cfg *action.Configuration, out io.Writer) *cobra.Command
return err return err
} }
if outputLogs { if outputLogs != "" {
podLogFilter := action.PodAll
if outputLogs == string(action.PodSucceeded) {
podLogFilter = action.PodSucceeded
} else if outputLogs == string(action.PodFailed) {
podLogFilter = action.PodFailed
}
// Print a newline to stdout to separate the output // Print a newline to stdout to separate the output
fmt.Fprintln(out) fmt.Fprintln(out)
if err := client.GetPodLogs(out, rel); err != nil { if err := client.GetPodLogs(out, rel, podLogFilter); err != nil {
return err return err
} }
} }
@ -90,7 +96,7 @@ func newReleaseTestCmd(cfg *action.Configuration, out io.Writer) *cobra.Command
f := cmd.Flags() f := cmd.Flags()
f.DurationVar(&client.Timeout, "timeout", 300*time.Second, "time to wait for any individual Kubernetes operation (like Jobs for hooks)") f.DurationVar(&client.Timeout, "timeout", 300*time.Second, "time to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&outputLogs, "logs", false, "dump the logs from test pods (this runs after all tests are complete, but before any cleanup)") f.StringVar(&outputLogs, "logs", "", "dump the logs from test pods (this runs after all tests are complete, but before any cleanup), options include [\"all\", \"succeeded\", \"failed\"]")
f.StringSliceVar(&filter, "filter", []string{}, "specify tests by attribute (currently \"name\") using attribute=value syntax or '!attribute=value' to exclude a test (can specify multiple or separate values with commas: name=test1,name=test2)") f.StringSliceVar(&filter, "filter", []string{}, "specify tests by attribute (currently \"name\") using attribute=value syntax or '!attribute=value' to exclude a test (can specify multiple or separate values with commas: name=test1,name=test2)")
return cmd return cmd

@ -23,10 +23,17 @@ import (
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
"helm.sh/helm/v3/pkg/chartutil" "helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/release" "helm.sh/helm/v3/pkg/release"
v1 "k8s.io/api/core/v1"
)
type PodLogFilter string
const (
PodAll PodLogFilter = "all"
PodSucceeded PodLogFilter = "succeeded"
PodFailed PodLogFilter = "failed"
) )
// ReleaseTesting is the action for testing a release. // ReleaseTesting is the action for testing a release.
@ -101,7 +108,7 @@ func (r *ReleaseTesting) Run(name string) (*release.Release, error) {
// GetPodLogs will write the logs for all test pods in the given release into // GetPodLogs will write the logs for all test pods in the given release into
// the given writer. These can be immediately output to the user or captured for // the given writer. These can be immediately output to the user or captured for
// other uses // other uses
func (r *ReleaseTesting) GetPodLogs(out io.Writer, rel *release.Release) error { func (r *ReleaseTesting) GetPodLogs(out io.Writer, rel *release.Release, filter PodLogFilter) error {
client, err := r.cfg.KubernetesClientSet() client, err := r.cfg.KubernetesClientSet()
if err != nil { if err != nil {
return errors.Wrap(err, "unable to get kubernetes client to fetch pod logs") return errors.Wrap(err, "unable to get kubernetes client to fetch pod logs")
@ -110,6 +117,15 @@ func (r *ReleaseTesting) GetPodLogs(out io.Writer, rel *release.Release) error {
for _, h := range rel.Hooks { for _, h := range rel.Hooks {
for _, e := range h.Events { for _, e := range h.Events {
if e == release.HookTest { if e == release.HookTest {
// only print logs of failed pods
if filter == PodFailed && h.LastRun.Phase != release.HookPhaseFailed {
continue
}
// only print logs of succeeded pods
if filter == PodSucceeded && h.LastRun.Phase != release.HookPhaseSucceeded {
continue
}
req := client.CoreV1().Pods(r.Namespace).GetLogs(h.Name, &v1.PodLogOptions{}) req := client.CoreV1().Pods(r.Namespace).GetLogs(h.Name, &v1.PodLogOptions{})
logReader, err := req.Stream(context.Background()) logReader, err := req.Stream(context.Background())
if err != nil { if err != nil {

Loading…
Cancel
Save