|
|
@ -19,16 +19,16 @@ import (
|
|
|
|
"bytes"
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"log"
|
|
|
|
|
|
|
|
"slices"
|
|
|
|
"sort"
|
|
|
|
"sort"
|
|
|
|
"time"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
|
|
"helm.sh/helm/v4/pkg/kube"
|
|
|
|
"helm.sh/helm/v4/pkg/kube"
|
|
|
|
|
|
|
|
|
|
|
|
"helm.sh/helm/v4/pkg/chartutil"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
|
|
|
|
"gopkg.in/yaml.v3"
|
|
|
|
|
|
|
|
|
|
|
|
"helm.sh/helm/v4/pkg/release"
|
|
|
|
"helm.sh/helm/v4/pkg/release"
|
|
|
|
helmtime "helm.sh/helm/v4/pkg/time"
|
|
|
|
helmtime "helm.sh/helm/v4/pkg/time"
|
|
|
@ -179,22 +179,20 @@ func hookHasDeletePolicy(h *release.Hook, policy release.HookDeletePolicy) bool
|
|
|
|
// outputLogsByPolicy outputs a pods logs if the hook policy instructs it to
|
|
|
|
// outputLogsByPolicy outputs a pods logs if the hook policy instructs it to
|
|
|
|
func (cfg *Configuration) outputLogsByPolicy(h *release.Hook, releaseNamespace string, policy release.HookOutputLogPolicy) error {
|
|
|
|
func (cfg *Configuration) outputLogsByPolicy(h *release.Hook, releaseNamespace string, policy release.HookOutputLogPolicy) error {
|
|
|
|
if !hookHasOutputLogPolicy(h, policy) {
|
|
|
|
if !hookHasOutputLogPolicy(h, policy) {
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace, err := cfg.deriveNamespace(h, releaseNamespace)
|
|
|
|
namespace, err := cfg.deriveNamespace(h, releaseNamespace)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch h.Kind {
|
|
|
|
switch h.Kind {
|
|
|
|
case "Job":
|
|
|
|
case "Job":
|
|
|
|
return cfg.outputContainerLogsForListOptions(namespace, metav1.ListOptions{LabelSelector: fmt.Sprintf("job-name=%s", h.Name)})
|
|
|
|
return cfg.outputContainerLogsForListOptions(namespace, metav1.ListOptions{LabelSelector: fmt.Sprintf("job-name=%s", h.Name)})
|
|
|
|
case "Pod":
|
|
|
|
case "Pod":
|
|
|
|
return cfg.outputContainerLogsForListOptions(namespace, metav1.ListOptions{FieldSelector: fmt.Sprintf("metadata.name=%s", h.Name)})
|
|
|
|
return cfg.outputContainerLogsForListOptions(namespace, metav1.ListOptions{FieldSelector: fmt.Sprintf("metadata.name=%s", h.Name)})
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (cfg *Configuration) outputContainerLogsForListOptions(namespace string, listOptions metav1.ListOptions) error {
|
|
|
|
func (cfg *Configuration) outputContainerLogsForListOptions(namespace string, listOptions metav1.ListOptions) error {
|
|
|
@ -204,35 +202,30 @@ func (cfg *Configuration) outputContainerLogsForListOptions(namespace string, li
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
err = kubeClient.OutputContainerLogsForPodList(podList, namespace, log.Writer())
|
|
|
|
err = kubeClient.OutputContainerLogsForPodList(podList, namespace, cfg.HookOutputFunc)
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (cfg *Configuration) deriveNamespace(h *release.Hook, namespace string) (string, error) {
|
|
|
|
func (cfg *Configuration) deriveNamespace(h *release.Hook, namespace string) (string, error) {
|
|
|
|
values, err := chartutil.ReadValues([]byte(h.Manifest))
|
|
|
|
tmp := struct {
|
|
|
|
|
|
|
|
Metadata struct {
|
|
|
|
|
|
|
|
Namespace string
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}{}
|
|
|
|
|
|
|
|
err := yaml.Unmarshal([]byte(h.Manifest), &tmp)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return "", errors.Wrapf(err, "unable to parse kubernetes manifest for output logs hook %s", h.Path)
|
|
|
|
return "", errors.Wrapf(err, "unable to parse metadata.namespace from kubernetes manifest for output logs hook %s", h.Path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
value, err := values.PathValue("metadata.namespace")
|
|
|
|
if tmp.Metadata.Namespace == "" {
|
|
|
|
switch err.(type) {
|
|
|
|
|
|
|
|
case nil:
|
|
|
|
|
|
|
|
return value.(string), nil
|
|
|
|
|
|
|
|
case chartutil.ErrNoValue:
|
|
|
|
|
|
|
|
return namespace, nil
|
|
|
|
return namespace, nil
|
|
|
|
default:
|
|
|
|
|
|
|
|
return "", errors.Wrapf(err, "unable to parse path of metadata.namespace in yaml for output logs hook %s", h.Path)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tmp.Metadata.Namespace, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// hookHasOutputLogPolicy determines whether the defined hook output log policy matches the hook output log policies
|
|
|
|
// hookHasOutputLogPolicy determines whether the defined hook output log policy matches the hook output log policies
|
|
|
|
// supported by helm.
|
|
|
|
// supported by helm.
|
|
|
|
func hookHasOutputLogPolicy(h *release.Hook, policy release.HookOutputLogPolicy) bool {
|
|
|
|
func hookHasOutputLogPolicy(h *release.Hook, policy release.HookOutputLogPolicy) bool {
|
|
|
|
for _, v := range h.OutputLogPolicies {
|
|
|
|
return slices.Contains(h.OutputLogPolicies, policy)
|
|
|
|
if policy == v {
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|