5 Commits

Author SHA1 Message Date
9d646297c7 fix: check for nil Command.Hooks in ExecuteHooks [#12] 2024-11-15 10:46:27 -06:00
bf8d261cf3 added timeout to golangci-lint command 2024-11-14 21:18:14 -06:00
686cd0019a Added Changie files 2024-11-14 21:13:40 -06:00
b7b002bd72 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.
2024-11-14 21:10:49 -06:00
b8a63f39f5 add working command hooks
Some checks failed
ci/woodpecker/push/go-lint Pipeline failed
2024-11-11 22:44:28 -06:00
9 changed files with 232 additions and 73 deletions

View File

@ -0,0 +1,3 @@
kind: Added
body: Hooks for Commands.[name]. Error, success, and final. [#12]
time: 2024-11-14T21:01:48.823426401-06:00

View File

@ -0,0 +1,3 @@
kind: Fixed
body: make command logger be used for errors, not just when running the command
time: 2024-11-14T21:13:06.404134926-06:00

View File

@ -7,4 +7,4 @@ steps:
release: release:
image: golangci/golangci-lint:v1.53.3 image: golangci/golangci-lint:v1.53.3
commands: commands:
- golangci-lint run -v - golangci-lint run -v --timeout 5m

View File

@ -20,7 +20,7 @@ package cmd
// func config(cmd *cobra.Command, args []string) { // func config(cmd *cobra.Command, args []string) {
// opts := backy.NewOpts(cfgFile, backy.UseCron()) // opts := backy.NewOpts(cfgFile, backy.cronEnabled())
// opts.InitConfig() // opts.InitConfig()
// } // }

View File

@ -17,7 +17,7 @@ var (
func cron(cmd *cobra.Command, args []string) { func cron(cmd *cobra.Command, args []string) {
opts := backy.NewOpts(cfgFile, backy.UseCron()) opts := backy.NewOpts(cfgFile, backy.CronEnabled())
opts.InitConfig() opts.InitConfig()
backy.ReadConfig(opts) backy.ReadConfig(opts)
opts.Cron() opts.Cron()

View File

@ -30,6 +30,8 @@ var Sprintf = fmt.Sprintf
// The environment of local commands will be the machine's environment plus any extra // The environment of local commands will be the machine's environment plus any extra
// variables specified in the Env file or Environment. // variables specified in the Env file or Environment.
// Dir can also be specified for local commands. // Dir can also be specified for local commands.
//
// Returns the output as a slice and an error, if any
func (command *Command) RunCmd(cmdCtxLogger zerolog.Logger, opts *ConfigOpts) ([]string, error) { func (command *Command) RunCmd(cmdCtxLogger zerolog.Logger, opts *ConfigOpts) ([]string, error) {
var ( var (
@ -53,9 +55,9 @@ func (command *Command) RunCmd(cmdCtxLogger zerolog.Logger, opts *ConfigOpts) ([
command.Type = strings.TrimSpace(command.Type) command.Type = strings.TrimSpace(command.Type)
if command.Type != "" { if command.Type != "" {
cmdCtxLogger.Info().Str("Command", fmt.Sprintf("Running script %s on host %s", command.Cmd, *command.Host)).Send() cmdCtxLogger.Info().Str("Command", fmt.Sprintf("Running script %s on host %s", command.Name, *command.Host)).Send()
} else { } else {
cmdCtxLogger.Info().Str("Command", fmt.Sprintf("Running command %s %s on host %s", command.Cmd, ArgsStr, *command.Host)).Send() cmdCtxLogger.Info().Str("Command", fmt.Sprintf("Running command %s on host %s", command.Name, *command.Host)).Send()
} }
if command.RemoteHost.SshClient == nil { if command.RemoteHost.SshClient == nil {
@ -165,7 +167,7 @@ func (command *Command) RunCmd(cmdCtxLogger zerolog.Logger, opts *ConfigOpts) ([
outScanner := bufio.NewScanner(&cmdOutBuf) outScanner := bufio.NewScanner(&cmdOutBuf)
for outScanner.Scan() { for outScanner.Scan() {
outMap := make(map[string]interface{}) outMap := make(map[string]interface{})
outMap["cmd"] = cmd outMap["cmd"] = command.Name
outMap["output"] = outScanner.Text() outMap["output"] = outScanner.Text()
if str, ok := outMap["output"].(string); ok { if str, ok := outMap["output"].(string); ok {
outputArr = append(outputArr, str) outputArr = append(outputArr, str)
@ -178,7 +180,7 @@ func (command *Command) RunCmd(cmdCtxLogger zerolog.Logger, opts *ConfigOpts) ([
outScanner := bufio.NewScanner(&cmdOutBuf) outScanner := bufio.NewScanner(&cmdOutBuf)
for outScanner.Scan() { for outScanner.Scan() {
outMap := make(map[string]interface{}) outMap := make(map[string]interface{})
outMap["cmd"] = cmd outMap["cmd"] = command.Name
outMap["output"] = outScanner.Text() outMap["output"] = outScanner.Text()
if str, ok := outMap["output"].(string); ok { if str, ok := outMap["output"].(string); ok {
outputArr = append(outputArr, str) outputArr = append(outputArr, str)
@ -288,7 +290,7 @@ func (command *Command) RunCmd(cmdCtxLogger zerolog.Logger, opts *ConfigOpts) ([
outScanner := bufio.NewScanner(&cmdOutBuf) outScanner := bufio.NewScanner(&cmdOutBuf)
for outScanner.Scan() { for outScanner.Scan() {
outMap := make(map[string]interface{}) outMap := make(map[string]interface{})
outMap["cmd"] = cmd outMap["cmd"] = command.Name
outMap["output"] = outScanner.Text() outMap["output"] = outScanner.Text()
if str, ok := outMap["output"].(string); ok { if str, ok := outMap["output"].(string); ok {
outputArr = append(outputArr, str) outputArr = append(outputArr, str)
@ -297,14 +299,14 @@ func (command *Command) RunCmd(cmdCtxLogger zerolog.Logger, opts *ConfigOpts) ([
} }
if err != nil { if err != nil {
cmdCtxLogger.Error().Err(fmt.Errorf("error when running cmd: %s: %w", command.Cmd, err)).Send() cmdCtxLogger.Error().Err(fmt.Errorf("error when running cmd: %s: %w", command.Name, err)).Send()
return outputArr, err return outputArr, err
} }
} else { } else {
var err error var err error
if command.Shell != "" { if command.Shell != "" {
cmdCtxLogger.Info().Str("Command", fmt.Sprintf("Running command %s %s on local machine in %s", command.Cmd, ArgsStr, command.Shell)).Send() cmdCtxLogger.Info().Str("Command", fmt.Sprintf("Running command %s on local machine in %s", command.Name, command.Shell)).Send()
ArgsStr = fmt.Sprintf("%s %s", command.Cmd, ArgsStr) ArgsStr = fmt.Sprintf("%s %s", command.Cmd, ArgsStr)
@ -330,7 +332,7 @@ func (command *Command) RunCmd(cmdCtxLogger zerolog.Logger, opts *ConfigOpts) ([
for outScanner.Scan() { for outScanner.Scan() {
outMap := make(map[string]interface{}) outMap := make(map[string]interface{})
outMap["cmd"] = command.Cmd outMap["cmd"] = command.Name
outMap["output"] = outScanner.Text() outMap["output"] = outScanner.Text()
if str, ok := outMap["output"].(string); ok { if str, ok := outMap["output"].(string); ok {
outputArr = append(outputArr, str) outputArr = append(outputArr, str)
@ -339,13 +341,13 @@ func (command *Command) RunCmd(cmdCtxLogger zerolog.Logger, opts *ConfigOpts) ([
} }
if err != nil { if err != nil {
cmdCtxLogger.Error().Err(fmt.Errorf("error when running cmd %s: %w", command.Cmd, err)).Send() cmdCtxLogger.Error().Err(fmt.Errorf("error when running cmd %s: %w", command.Name, err)).Send()
return outputArr, err return outputArr, err
} }
return outputArr, nil return outputArr, nil
} }
cmdCtxLogger.Info().Str("Command", fmt.Sprintf("Running command %s %s on local machine", command.Cmd, ArgsStr)).Send() cmdCtxLogger.Info().Str("Command", fmt.Sprintf("Running command %s on local machine", command.Name)).Send()
localCMD := exec.Command(command.Cmd, command.Args...) localCMD := exec.Command(command.Cmd, command.Args...)
@ -379,7 +381,7 @@ func (command *Command) RunCmd(cmdCtxLogger zerolog.Logger, opts *ConfigOpts) ([
cmdCtxLogger.Info().Fields(outMap).Send() cmdCtxLogger.Info().Fields(outMap).Send()
} }
if err != nil { if err != nil {
cmdCtxLogger.Error().Err(fmt.Errorf("error when running cmd %s: %w", command.Cmd, err)).Send() cmdCtxLogger.Error().Err(fmt.Errorf("error when running cmd %s: %w", command.Name, err)).Send()
return outputArr, err return outputArr, err
} }
} }
@ -388,42 +390,35 @@ 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
res := CmdListResults{}
for list := range jobs { 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
var outStructArr []outStruct // stores output messages var outStructArr []outStruct // stores output messages
for _, cmd := range list.Order { for _, cmd := range list.Order {
currentCmd := opts.Cmds[cmd].Cmd
fieldsMap["cmd"] = opts.Cmds[cmd].Cmd currentCmd := 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)
if list.NotifyConfig != nil { if list.NotifyConfig != nil {
// check if the command output should be included // check if the command output should be included
if cmdToRun.GetOutput || list.GetOutput { if cmdToRun.GetOutput || list.GetOutput {
outputStruct := outStruct{ outputStruct := outStruct{
CmdName: cmd, CmdName: cmdToRun.Name,
CmdExecuted: currentCmd, CmdExecuted: currentCmd,
Output: outputArr, Output: outputArr,
} }
@ -434,6 +429,7 @@ func cmdListWorker(msgTemps *msgTemplates, jobs <-chan *CmdList, results chan<-
} }
count++ count++
if runOutErr != nil { if runOutErr != nil {
res.ErrCmd = cmd
if list.NotifyConfig != nil { if list.NotifyConfig != nil {
var errMsg bytes.Buffer var errMsg bytes.Buffer
errStruct := make(map[string]interface{}) errStruct := make(map[string]interface{})
@ -451,23 +447,24 @@ 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 {
if count == len(list.Order) {
cmdsRan = append(cmdsRan, cmd) cmdsRan = append(cmdsRan, cmd)
if count == len(list.Order) {
var successMsg bytes.Buffer var successMsg bytes.Buffer
// if notification config is not nil, and NotifyOnSuccess is true or GetOuput is true, // if notification config is not nil, and NotifyOnSuccess is true or GetOuput is true,
@ -483,23 +480,21 @@ 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 succeded", 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()
} }
} }
} else {
cmdsRan = append(cmdsRan, cmd)
} }
} }
} }
results <- "done" results <- res.ErrCmd
} }
} }
@ -535,7 +530,23 @@ func (opts *ConfigOpts) RunListConfig(cron string) {
close(listChan) close(listChan)
for a := 1; a <= configListsLen; a++ { for a := 1; a <= configListsLen; a++ {
<-results l := <-results
opts.Logger.Debug().Msg(l)
if l != "" {
// execute error hooks
opts.Logger.Debug().Msg("hooks are working")
opts.Cmds[l].ExecuteHooks("error", opts)
} else {
// execute success hooks
opts.Cmds[l].ExecuteHooks("success", opts)
}
// execute final hooks
opts.Cmds[l].ExecuteHooks("final", opts)
} }
opts.closeHostConnections() opts.closeHostConnections()
@ -544,13 +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()
cmdToRun.ExecuteHooks("error", opts)
} else {
cmdToRun.ExecuteHooks("success", opts)
} }
cmdToRun.ExecuteHooks("final", opts)
} }
opts.closeHostConnections() opts.closeHostConnections()
@ -593,3 +609,50 @@ func (c *ConfigOpts) closeHostConnections() {
} }
} }
} }
func (cmd *Command) ExecuteHooks(hookType string, opts *ConfigOpts) {
if cmd.Hooks == nil {
return
}
switch hookType {
case "error":
for _, v := range cmd.Hooks.Error {
errCmd := opts.Cmds[v]
cmdLogger := opts.Logger.With().
Str("backy-cmd", v).
Logger()
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

@ -245,6 +245,7 @@ func ReadConfig(opts *ConfigOpts) *ConfigOpts {
cmdListFilePath := path.Clean(opts.CmdListFile) cmdListFilePath := path.Clean(opts.CmdListFile)
// if path is not absolute, check config directory
if !strings.HasPrefix(cmdListFilePath, "/") { if !strings.HasPrefix(cmdListFilePath, "/") {
opts.CmdListFile = path.Join(backyConfigFileDir, cmdListFilePath) opts.CmdListFile = path.Join(backyConfigFileDir, cmdListFilePath)
} }
@ -259,7 +260,7 @@ func ReadConfig(opts *ConfigOpts) *ConfigOpts {
logging.ExitWithMSG(fmt.Sprintf("error loading config: %v", err), 1, &opts.Logger) logging.ExitWithMSG(fmt.Sprintf("error loading config: %v", err), 1, &opts.Logger)
} }
log.Info().Str("lists config file", opts.CmdListFile).Send() log.Info().Str("using lists config file", opts.CmdListFile).Send()
} }
@ -269,7 +270,7 @@ func ReadConfig(opts *ConfigOpts) *ConfigOpts {
var cmdNotFoundSliceErr []error var cmdNotFoundSliceErr []error
for cmdListName, cmdList := range opts.CmdConfigLists { for cmdListName, cmdList := range opts.CmdConfigLists {
if opts.useCron { if opts.cronEnabled {
cron := strings.TrimSpace(cmdList.Cron) cron := strings.TrimSpace(cmdList.Cron)
if cron == "" { if cron == "" {
delete(opts.CmdConfigLists, cmdListName) delete(opts.CmdConfigLists, cmdListName)
@ -291,14 +292,13 @@ func ReadConfig(opts *ConfigOpts) *ConfigOpts {
cmdNotFoundErrorLog.Errs("commands not found", cmdNotFoundSliceErr).Send() cmdNotFoundErrorLog.Errs("commands not found", cmdNotFoundSliceErr).Send()
} }
if opts.useCron && (len(opts.CmdConfigLists) == 0) { if opts.cronEnabled && (len(opts.CmdConfigLists) == 0) {
logging.ExitWithMSG("No cron fields detected in any command lists", 1, nil) logging.ExitWithMSG("No cron fields detected in any command lists", 1, nil)
} }
for c := range opts.Cmds { // process commands
if opts.executeCmds != nil && !contains(opts.executeCmds, c) { if err := processCmds(opts); err != nil {
delete(opts.Cmds, c) logging.ExitWithMSG(err.Error(), 1, &opts.Logger)
}
} }
if len(opts.executeLists) > 0 { if len(opts.executeLists) > 0 {
@ -317,23 +317,8 @@ func ReadConfig(opts *ConfigOpts) *ConfigOpts {
} }
} }
for _, cmd := range opts.Cmds {
if cmd.Host != nil {
host, hostFound := opts.Hosts[*cmd.Host]
if hostFound {
cmd.RemoteHost = host
cmd.RemoteHost.Host = host.Host
if host.HostName != "" {
cmd.RemoteHost.HostName = host.HostName
}
} else {
opts.Hosts[*cmd.Host] = &Host{Host: *cmd.Host}
cmd.RemoteHost = &Host{Host: *cmd.Host}
}
}
}
opts.SetupNotify() opts.SetupNotify()
if err := opts.setupVault(); err != nil { if err := opts.setupVault(); err != nil {
log.Err(err).Send() log.Err(err).Send()
} }
@ -460,3 +445,88 @@ func GetVaultKey(str string, opts *ConfigOpts, log zerolog.Logger) string {
} }
return value return value
} }
func processCmds(opts *ConfigOpts) error {
// process commands
for cmdName, cmd := range opts.Cmds {
if cmd.Name == "" {
cmd.Name = cmdName
}
// println("Cmd.Name = " + cmd.Name)
hooks := cmd.Hooks
// resolve hooks
if hooks != nil {
processHookSuccess := processHooks(cmd, hooks.Error, opts, "error")
if processHookSuccess != nil {
return processHookSuccess
}
processHookSuccess = processHooks(cmd, hooks.Success, opts, "success")
if processHookSuccess != nil {
return processHookSuccess
}
processHookSuccess = processHooks(cmd, hooks.Final, opts, "final")
if processHookSuccess != nil {
return processHookSuccess
}
}
// resolve hosts
if cmd.Host != nil {
host, hostFound := opts.Hosts[*cmd.Host]
if hostFound {
cmd.RemoteHost = host
cmd.RemoteHost.Host = host.Host
if host.HostName != "" {
cmd.RemoteHost.HostName = host.HostName
}
} else {
opts.Hosts[*cmd.Host] = &Host{Host: *cmd.Host}
cmd.RemoteHost = &Host{Host: *cmd.Host}
}
}
}
return nil
}
// processHooks evaluates if hooks are valid Commands
//
// Takes the following arguments:
//
// 1. a []string of hooks
// 2. a map of Commands as arguments
// 3. a string hookType, must be the hook type
//
// The cmds.hookRef is modified in this function.
//
// Returns the following:
//
// An error, if any, if the command is not found
func processHooks(cmd *Command, hooks []string, opts *ConfigOpts, hookType string) error {
// initialize hook type
var hookCmdFound bool
cmd.hookRefs = map[string]map[string]*Command{}
cmd.hookRefs[hookType] = map[string]*Command{}
for _, hook := range hooks {
var hookCmd *Command
// TODO: match by Command.Name
hookCmd, hookCmdFound = opts.Cmds[hook]
if !hookCmdFound {
return fmt.Errorf("error in command %s hook %s list: command %s not found", cmd.Name, hookType, hook)
}
cmd.hookRefs[hookType][hook] = hookCmd
// Recursive, decide if this is good
// if hookCmd.hookRefs == nil {
// }
// hookRef[hookType][h] = hookCmd
}
return nil
}

View File

@ -43,17 +43,24 @@ type (
} }
Command struct { Command struct {
Name string `yaml:"name,omitempty"`
// command to run // command to run
Cmd string `yaml:"cmd"` Cmd string `yaml:"cmd"`
// Possible values: script, scriptFile // Possible values: script, scriptFile
// If blank, it is regualar command. // If blank, it is regular command.
Type string `yaml:"type"` Type string `yaml:"type,omitempty"`
// host on which to run cmd // host on which to run cmd
Host *string `yaml:"host,omitempty"` Host *string `yaml:"host,omitempty"`
// Hooks are for running commands on certain events
Hooks *Hooks `yaml:"hooks,omitempty"`
// hook refs are internal references of commands for each hook type
hookRefs map[string]map[string]*Command
/* /*
Shell specifies which shell to run the command in, if any. Shell specifies which shell to run the command in, if any.
Not applicable when host is defined. Not applicable when host is defined.
@ -123,7 +130,7 @@ type (
CmdListFile string CmdListFile string
// use command lists using cron // use command lists using cron
useCron bool cronEnabled bool
// Holds commands to execute for the exec command // Holds commands to execute for the exec command
executeCmds []string executeCmds []string
// Holds lists to execute for the backup command // Holds lists to execute for the backup command
@ -188,4 +195,17 @@ type (
Commands []string Commands []string
Hosts []string Hosts []string
} }
Hooks struct {
Error []string `yaml:"error,omitempty"`
Success []string `yaml:"success,omitempty"`
Final []string `yaml:"final,omitempty"`
}
CmdListResults struct {
// name of the list
ListName string
// command that caused the list to fail
ErrCmd string
}
) )

View File

@ -56,10 +56,10 @@ func SetCmdsToSearch(cmds []string) BackyOptionFunc {
} }
} }
// UseCron enables the execution of command lists at specified times // cronEnabled enables the execution of command lists at specified times
func UseCron() BackyOptionFunc { func CronEnabled() BackyOptionFunc {
return func(bco *ConfigOpts) { return func(bco *ConfigOpts) {
bco.useCron = true bco.cronEnabled = true
} }
} }