Added: Hooks for Commands.[name]: error, success, and final. Closes [#12]

Added Command.generateLogger() method.

Fixed: make command logger be used for errors, not just when running the command.
This commit is contained in:
Andrew Woodlee 2024-11-14 21:10:49 -06:00
parent b8a63f39f5
commit b7b002bd72
3 changed files with 81 additions and 62 deletions

View File

@ -391,12 +391,11 @@ func (command *Command) RunCmd(cmdCtxLogger zerolog.Logger, opts *ConfigOpts) ([
// cmdListWorker // cmdListWorker
func cmdListWorker(msgTemps *msgTemplates, jobs <-chan *CmdList, results chan<- string, opts *ConfigOpts) { func cmdListWorker(msgTemps *msgTemplates, jobs <-chan *CmdList, results chan<- string, opts *ConfigOpts) {
// iterate over list to run // iterate over list to run
for list := range jobs {
res := CmdListResults{} res := CmdListResults{}
for list := range jobs {
fieldsMap := make(map[string]interface{}) fieldsMap := make(map[string]interface{})
fieldsMap["list"] = list.Name fieldsMap["list"] = list.Name
var cmdLogger zerolog.Logger
cmdLog := opts.Logger.Info()
var count int // count of how many commands have been executed var count int // count of how many commands have been executed
var cmdsRan []string // store the commands that have been executed var cmdsRan []string // store the commands that have been executed
@ -408,17 +407,9 @@ func cmdListWorker(msgTemps *msgTemplates, jobs <-chan *CmdList, results chan<-
fieldsMap["cmd"] = opts.Cmds[cmd].Name fieldsMap["cmd"] = opts.Cmds[cmd].Name
cmdToRun := opts.Cmds[cmd] cmdToRun := opts.Cmds[cmd]
cmdLog.Fields(fieldsMap).Send()
cmdLogger := opts.Logger.With(). cmdLogger = cmdToRun.generateLogger(opts)
Str("backy-cmd", cmd).Str("Host", "local machine"). cmdLogger.Info().Fields(fieldsMap).Send()
Logger()
if cmdToRun.Host != nil {
cmdLogger = opts.Logger.With().
Str("backy-cmd", cmd).Str("Host", *cmdToRun.Host).
Logger()
}
outputArr, runOutErr := cmdToRun.RunCmd(cmdLogger, opts) outputArr, runOutErr := cmdToRun.RunCmd(cmdLogger, opts)
@ -456,17 +447,17 @@ func cmdListWorker(msgTemps *msgTemplates, jobs <-chan *CmdList, results chan<-
tmpErr := msgTemps.err.Execute(&errMsg, errStruct) tmpErr := msgTemps.err.Execute(&errMsg, errStruct)
if tmpErr != nil { if tmpErr != nil {
opts.Logger.Err(tmpErr).Send() cmdLogger.Err(tmpErr).Send()
} }
notifySendErr := list.NotifyConfig.Send(context.Background(), fmt.Sprintf("List %s failed", list.Name), errMsg.String()) notifySendErr := list.NotifyConfig.Send(context.Background(), fmt.Sprintf("List %s failed", list.Name), errMsg.String())
if notifySendErr != nil { if notifySendErr != nil {
opts.Logger.Err(notifySendErr).Send() cmdLogger.Err(notifySendErr).Send()
} }
} }
opts.Logger.Err(runOutErr).Send() cmdLogger.Err(runOutErr).Send()
break break
} else { } else {
@ -489,14 +480,14 @@ func cmdListWorker(msgTemps *msgTemplates, jobs <-chan *CmdList, results chan<-
tmpErr := msgTemps.success.Execute(&successMsg, successStruct) tmpErr := msgTemps.success.Execute(&successMsg, successStruct)
if tmpErr != nil { if tmpErr != nil {
opts.Logger.Err(tmpErr).Send() cmdLogger.Err(tmpErr).Send()
break break
} }
err := list.NotifyConfig.Send(context.Background(), fmt.Sprintf("List %s succeeded", list.Name), successMsg.String()) err := list.NotifyConfig.Send(context.Background(), fmt.Sprintf("List %s succeeded", list.Name), successMsg.String())
if err != nil { if err != nil {
opts.Logger.Err(err).Send() cmdLogger.Err(err).Send()
} }
} }
} }
@ -538,7 +529,7 @@ func (opts *ConfigOpts) RunListConfig(cron string) {
} }
close(listChan) close(listChan)
for a := 0; a <= configListsLen; a++ { for a := 1; a <= configListsLen; a++ {
l := <-results l := <-results
opts.Logger.Debug().Msg(l) opts.Logger.Debug().Msg(l)
@ -546,11 +537,15 @@ func (opts *ConfigOpts) RunListConfig(cron string) {
if l != "" { if l != "" {
// execute error hooks // execute error hooks
opts.Logger.Debug().Msg("hooks are working") opts.Logger.Debug().Msg("hooks are working")
opts.Cmds[l].ExecuteHooks("error", opts)
} else { } else {
// execute success hooks // execute success hooks
opts.Cmds[l].ExecuteHooks("success", opts)
} }
// execute final hooks // execute final hooks
opts.Cmds[l].ExecuteHooks("final", opts)
} }
@ -560,20 +555,18 @@ func (opts *ConfigOpts) RunListConfig(cron string) {
func (config *ConfigOpts) ExecuteCmds(opts *ConfigOpts) { func (config *ConfigOpts) ExecuteCmds(opts *ConfigOpts) {
for _, cmd := range opts.executeCmds { for _, cmd := range opts.executeCmds {
cmdToRun := opts.Cmds[cmd] cmdToRun := opts.Cmds[cmd]
cmdLogger := opts.Logger.With(). cmdLogger := cmdToRun.generateLogger(opts)
Str("backy-cmd", cmd).
Logger()
_, runErr := cmdToRun.RunCmd(cmdLogger, opts) _, runErr := cmdToRun.RunCmd(cmdLogger, opts)
if runErr != nil { if runErr != nil {
opts.Logger.Err(runErr).Send() opts.Logger.Err(runErr).Send()
ExecuteHooks(*cmdToRun, "error", opts) cmdToRun.ExecuteHooks("error", opts)
} else { } else {
ExecuteHooks(*cmdToRun, "success", opts) cmdToRun.ExecuteHooks("success", opts)
} }
ExecuteHooks(*cmdToRun, "final", opts) cmdToRun.ExecuteHooks("final", opts)
} }
opts.closeHostConnections() opts.closeHostConnections()
@ -617,7 +610,7 @@ func (c *ConfigOpts) closeHostConnections() {
} }
} }
func ExecuteHooks(cmd Command, hookType string, opts *ConfigOpts) { func (cmd *Command) ExecuteHooks(hookType string, opts *ConfigOpts) {
switch hookType { switch hookType {
case "error": case "error":
for _, v := range cmd.Hooks.Error { for _, v := range cmd.Hooks.Error {
@ -628,5 +621,35 @@ func ExecuteHooks(cmd Command, hookType string, opts *ConfigOpts) {
errCmd.RunCmd(cmdLogger, opts) errCmd.RunCmd(cmdLogger, opts)
} }
case "success":
for _, v := range cmd.Hooks.Success {
successCmd := opts.Cmds[v]
cmdLogger := opts.Logger.With().
Str("backy-cmd", v).
Logger()
successCmd.RunCmd(cmdLogger, opts)
}
case "final":
for _, v := range cmd.Hooks.Final {
finalCmd := opts.Cmds[v]
cmdLogger := opts.Logger.With().
Str("backy-cmd", v).
Logger()
finalCmd.RunCmd(cmdLogger, opts)
} }
} }
}
func (cmd *Command) generateLogger(opts *ConfigOpts) zerolog.Logger {
cmdLogger := opts.Logger.With().
Str("backy-cmd", cmd.Name).Str("Host", "local machine").
Logger()
if cmd.Host != nil {
cmdLogger = opts.Logger.With().
Str("backy-cmd", cmd.Name).Str("Host", *cmd.Host).
Logger()
}
return cmdLogger
}

View File

@ -298,14 +298,16 @@ func ReadConfig(opts *ConfigOpts) *ConfigOpts {
// process commands // process commands
if err := processCmds(opts); err != nil { if err := processCmds(opts); err != nil {
log.Panic().Err(err).Send() logging.ExitWithMSG(err.Error(), 1, &opts.Logger)
} }
if len(opts.executeLists) > 0 {
for l := range opts.CmdConfigLists { for l := range opts.CmdConfigLists {
if !contains(opts.executeLists, l) { if !contains(opts.executeLists, l) {
delete(opts.CmdConfigLists, l) delete(opts.CmdConfigLists, l)
} }
} }
}
if backyKoanf.Exists("notifications") { if backyKoanf.Exists("notifications") {
@ -447,9 +449,6 @@ func GetVaultKey(str string, opts *ConfigOpts, log zerolog.Logger) string {
func processCmds(opts *ConfigOpts) error { func processCmds(opts *ConfigOpts) error {
// process commands // process commands
for cmdName, cmd := range opts.Cmds { for cmdName, cmd := range opts.Cmds {
cmd.hookRefs = map[string]map[string]*Command{}
cmd.hookRefs["error"] = map[string]*Command{}
cmd.hookRefs["success"] = map[string]*Command{}
if cmd.Name == "" { if cmd.Name == "" {
cmd.Name = cmdName cmd.Name = cmdName
@ -458,19 +457,19 @@ func processCmds(opts *ConfigOpts) error {
hooks := cmd.Hooks hooks := cmd.Hooks
// resolve hooks // resolve hooks
if hooks != nil { if hooks != nil {
opts.Logger.Debug().Msg("Hooks found")
errHook, hookRefs, processHookErr := processHooks(hooks.Error, opts.Cmds, "error") processHookSuccess := processHooks(cmd, hooks.Error, opts, "error")
if !processHookErr { if processHookSuccess != nil {
return fmt.Errorf("error in command %s hook list: hook command %s not found", cmd.Name, errHook) return processHookSuccess
} }
cmd.hookRefs["error"] = hookRefs processHookSuccess = processHooks(cmd, hooks.Success, opts, "success")
if processHookSuccess != nil {
successHook, SuccessHookRefs, processHookSuccess := processHooks(hooks.Error, opts.Cmds, "error") return processHookSuccess
if !processHookSuccess { }
return fmt.Errorf("error in command %s hook list: hook command %s not found", cmd.Name, successHook) processHookSuccess = processHooks(cmd, hooks.Final, opts, "final")
if processHookSuccess != nil {
return processHookSuccess
} }
cmd.hookRefs["success"] = SuccessHookRefs
} }
// resolve hosts // resolve hosts
@ -503,34 +502,31 @@ func processCmds(opts *ConfigOpts) error {
// //
// Returns the following: // Returns the following:
// //
// 1. command string // An error, if any, if the command is not found
// 2. each hook type's command map func processHooks(cmd *Command, hooks []string, opts *ConfigOpts, hookType string) error {
// 2. a bool which determines if the command is valid
func processHooks(hooks []string, cmds map[string]*Command, hookType string) (hook string, hookRefs map[string]*Command, hookCmdFound bool) {
// fmt.Printf("%v\n", hooks)
// for _, v := range cmds {
// fmt.Printf("CmdName=%v\n", v.Name)
// fmt.Printf("Cmd=%v\n", v.Cmd)
// }
// initialize hook type // initialize hook type
hookRefs = make(map[string]*Command) var hookCmdFound bool
// hookRefs[hookType] = map[string]*Command{} cmd.hookRefs = map[string]map[string]*Command{}
for _, hook = range hooks { cmd.hookRefs[hookType] = map[string]*Command{}
for _, hook := range hooks {
var hookCmd *Command var hookCmd *Command
// TODO: match by Command.Name // TODO: match by Command.Name
hookCmd, hookCmdFound = cmds[hook] hookCmd, hookCmdFound = opts.Cmds[hook]
if !hookCmdFound { if !hookCmdFound {
return return fmt.Errorf("error in command %s hook %s list: command %s not found", cmd.Name, hookType, hook)
} }
hookRefs[hook] = hookCmd
cmd.hookRefs[hookType][hook] = hookCmd
// Recursive, decide if this is good // Recursive, decide if this is good
// if hookCmd.hookRefs == nil { // if hookCmd.hookRefs == nil {
// } // }
// hookRef[hookType][h] = hookCmd // hookRef[hookType][h] = hookCmd
} }
return return nil
} }

View File

@ -198,8 +198,8 @@ type (
Hooks struct { Hooks struct {
Error []string `yaml:"error,omitempty"` Error []string `yaml:"error,omitempty"`
SuccessHooks []string `yaml:"success,omitempty"` Success []string `yaml:"success,omitempty"`
FinalHooks []string `yaml:"final,omitempty"` Final []string `yaml:"final,omitempty"`
} }
CmdListResults struct { CmdListResults struct {