feat: optionally show logs for hooks (#699)
Resolves #689 This adds a new yaml entry for the hook definition to allow the users to specifcy if they want to show the `command` logs or not. here is an example. ``` releases: - name: myapp chart: mychart # *snip* hooks: - events: ["cleanup"] showlogs: true command: "kubectl" args: ["get", "ingress"] ``` this will display the following output: ``` hook[cleanup] logs | NAME HOSTS ADDRESS PORTS AGE hook[cleanup] logs | catalog-gateway tdc.foo 80 2d6h hook[cleanup] logs | dataset foobar.barr.foo.xxxxxxx.com 80 2d6h hook[cleanup] logs | rating fooba.barr.foo.xxxxxxx.com 80 2d6h hook[cleanup] logs | sharing foobar.barr.foo.xxxxxxx.com 80 2d6h hook[cleanup] logs | tpsvc-iam-dev foo.barr.foo.xxxxxxx.com 80 2d6h hook[cleanup] logs | tpsvc-iam-front bar.barr.foo.xxxxxxx.com 80 2d6h ```
This commit is contained in:
parent
f61334d9bb
commit
ddb5be1b9d
|
|
@ -829,9 +829,10 @@ A Helmfile hook is a per-release extension point that is composed of:
|
|||
- `events`
|
||||
- `command`
|
||||
- `args`
|
||||
- `showlogs`
|
||||
|
||||
Helmfile triggers various `events` while it is running.
|
||||
Once `events` are triggered, associated `hooks` are executed, by running the `command` with `args`.
|
||||
Once `events` are triggered, associated `hooks` are executed, by running the `command` with `args`. The standard output of the `command` will be displayed if `showlogs` is set and it's value is `true`.
|
||||
|
||||
Currently supported `events` are:
|
||||
|
||||
|
|
@ -857,6 +858,7 @@ releases:
|
|||
# *snip*
|
||||
hooks:
|
||||
- events: ["prepare", "cleanup"]
|
||||
showlogs: true
|
||||
command: "echo"
|
||||
args: ["{{`{{.Environment.Name}}`}}", "{{`{{.Release.Name}}`}}", "{{`{{.HelmfileCommand}}`}}\
|
||||
"]
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@ package event
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/roboll/helmfile/pkg/environment"
|
||||
"github.com/roboll/helmfile/pkg/helmexec"
|
||||
"github.com/roboll/helmfile/pkg/tmpl"
|
||||
"go.uber.org/zap"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Hook struct {
|
||||
|
|
@ -14,6 +16,7 @@ type Hook struct {
|
|||
Events []string `yaml:"events"`
|
||||
Command string `yaml:"command"`
|
||||
Args []string `yaml:"args"`
|
||||
ShowLogs bool `yaml:"showlogs"`
|
||||
}
|
||||
|
||||
type event struct {
|
||||
|
|
@ -90,6 +93,10 @@ func (bus *Bus) Trigger(evt string, context map[string]interface{}) (bool, error
|
|||
|
||||
bytes, err := bus.Runner.Execute(command, args, map[string]string{})
|
||||
bus.Logger.Debugf("hook[%s]: %s\n", name, string(bytes))
|
||||
if hook.ShowLogs {
|
||||
prefix := fmt.Sprintf("\nhook[%s] logs | ", evt)
|
||||
bus.Logger.Infow(prefix + strings.ReplaceAll(string(bytes), "\n", prefix))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("hook[%s]: command `%s` failed: %v", name, command, err)
|
||||
|
|
|
|||
|
|
@ -2,10 +2,13 @@ package event
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/roboll/helmfile/pkg/environment"
|
||||
"github.com/roboll/helmfile/pkg/helmexec"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/roboll/helmfile/pkg/environment"
|
||||
"github.com/roboll/helmfile/pkg/helmexec"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zaptest/observer"
|
||||
)
|
||||
|
||||
var logger = helmexec.NewLogger(os.Stdout, "warn")
|
||||
|
|
@ -35,14 +38,21 @@ func TestTrigger(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
"okhook1",
|
||||
&Hook{"okhook1", []string{"foo"}, "ok", []string{}},
|
||||
&Hook{"okhook1", []string{"foo"}, "ok", []string{}, true},
|
||||
"foo",
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"okhooké",
|
||||
&Hook{"okhook2", []string{"foo"}, "ok", []string{}, false},
|
||||
"foo",
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"missinghook1",
|
||||
&Hook{"okhook1", []string{"foo"}, "ok", []string{}},
|
||||
&Hook{"okhook1", []string{"foo"}, "ok", []string{}, false},
|
||||
"bar",
|
||||
false,
|
||||
"",
|
||||
|
|
@ -56,14 +66,14 @@ func TestTrigger(t *testing.T) {
|
|||
},
|
||||
{
|
||||
"nghook1",
|
||||
&Hook{"nghook1", []string{"foo"}, "ng", []string{}},
|
||||
&Hook{"nghook1", []string{"foo"}, "ng", []string{}, false},
|
||||
"foo",
|
||||
false,
|
||||
"hook[nghook1]: command `ng` failed: cmd failed due to invalid cmd: ng",
|
||||
},
|
||||
{
|
||||
"nghook2",
|
||||
&Hook{"nghook2", []string{"foo"}, "ok", []string{"ng"}},
|
||||
&Hook{"nghook2", []string{"foo"}, "ok", []string{"ng"}, false},
|
||||
"foo",
|
||||
false,
|
||||
"hook[nghook2]: command `ok` failed: cmd failed due to invalid arg: ng",
|
||||
|
|
@ -77,13 +87,15 @@ func TestTrigger(t *testing.T) {
|
|||
if c.hook != nil {
|
||||
hooks = append(hooks, *c.hook)
|
||||
}
|
||||
observer, observedLogs := observer.New(zap.InfoLevel)
|
||||
zeLogger := zap.New(observer).Sugar()
|
||||
bus := &Bus{
|
||||
Hooks: hooks,
|
||||
StateFilePath: "path/to/helmfile.yaml",
|
||||
BasePath: "path/to",
|
||||
Namespace: "myns",
|
||||
Env: environment.Environment{Name: "prod"},
|
||||
Logger: logger,
|
||||
Logger: zeLogger,
|
||||
ReadFile: readFile,
|
||||
}
|
||||
|
||||
|
|
@ -109,5 +121,8 @@ func TestTrigger(t *testing.T) {
|
|||
t.Errorf("unexpected error for case \"%s\": %v", c.name, err)
|
||||
}
|
||||
}
|
||||
if observedLogs.Len() != 0 && !hooks[0].ShowLogs {
|
||||
t.Errorf("unexpected error for case \"%s\": Logs should not be created : %v", c.name, observedLogs.All())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue