Configuration - Control over command timeouts
This commit is contained in:
parent
dad5a17d36
commit
44eb5c5356
3 changed files with 61 additions and 14 deletions
22
config.go
22
config.go
|
@ -61,9 +61,12 @@ type (
|
|||
|
||||
// Handlers. Each handler has a name and contains a list of commands.
|
||||
tHandlers map[string][]string
|
||||
// Handler timeouts.
|
||||
tHandlerTimeouts map[string]int
|
||||
|
||||
// Certificate file updates configuration.
|
||||
tCertFileUpdateConfig struct {
|
||||
CmdTimeout *int `yaml:"command_timeout"`
|
||||
PreCommands []string `yaml:"pre_commands"`
|
||||
Handlers []string `yaml:"handlers"`
|
||||
PostCommands []string `yaml:"post_commands"`
|
||||
|
@ -86,9 +89,11 @@ type (
|
|||
|
||||
// Main configuration.
|
||||
tConfiguration struct {
|
||||
CmdTimeout int `yaml:"command_timeout"`
|
||||
Socket *tSocketConfig `yaml:"socket"`
|
||||
LdapConfig tLdapConfig `yaml:"ldap"`
|
||||
Handlers tHandlers `yaml:"handlers"`
|
||||
HandlerTimeouts tHandlerTimeouts `yaml:"handler_timeouts"`
|
||||
Certificates []tCertificateFileConfig `yaml:"certificates"`
|
||||
}
|
||||
)
|
||||
|
@ -235,7 +240,7 @@ func checkFileList(files []string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Validate the list of handles
|
||||
// Validate the list of handlers and the timeout.
|
||||
func (c *tCertFileUpdateConfig) Validate(handlers *tHandlers) error {
|
||||
set := make(map[string]bool)
|
||||
for _, handler := range c.Handlers {
|
||||
|
@ -247,6 +252,9 @@ func (c *tCertFileUpdateConfig) Validate(handlers *tHandlers) error {
|
|||
}
|
||||
set[handler] = true
|
||||
}
|
||||
if c.CmdTimeout != nil && *c.CmdTimeout <= 0 {
|
||||
return fmt.Errorf("Command timeout must be >0.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -289,6 +297,9 @@ func (c *tCertificateFileConfig) Validate(handlers *tHandlers) error {
|
|||
|
||||
// Validate the configuration
|
||||
func (c *tConfiguration) Validate() error {
|
||||
if c.CmdTimeout <= 0 {
|
||||
return fmt.Errorf("Default command timeout must be >0.")
|
||||
}
|
||||
if c.Socket != nil {
|
||||
err := c.Socket.Validate()
|
||||
if err != nil {
|
||||
|
@ -299,6 +310,14 @@ func (c *tConfiguration) Validate() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for hdl, timeout := range c.HandlerTimeouts {
|
||||
if _, exists := c.Handlers[hdl]; !exists {
|
||||
return fmt.Errorf("Can't set timeout for unknown handler %s", hdl)
|
||||
}
|
||||
if timeout <= 0 {
|
||||
return fmt.Errorf("Command timeout for handler %s must be >0.", hdl)
|
||||
}
|
||||
}
|
||||
for idx, cfc := range c.Certificates {
|
||||
if cfc.Path == "" {
|
||||
return fmt.Errorf("Certificate file entry #%d has no path.", idx+1)
|
||||
|
@ -314,6 +333,7 @@ func (c *tConfiguration) Validate() error {
|
|||
// Create a configuration data structure containing default values.
|
||||
func defaultConfiguration() tConfiguration {
|
||||
cfg := tConfiguration{}
|
||||
cfg.CmdTimeout = 5
|
||||
cfg.LdapConfig.Defaults.TLS = "no"
|
||||
cfg.LdapConfig.Structure.CAChaining = "seeAlso"
|
||||
return cfg
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
# fetchcert configuration example / documentation
|
||||
# ===============================================
|
||||
|
||||
# Default command execution timeout (seconds). 5 seconds is the default.
|
||||
command_timeout: 5
|
||||
|
||||
# The UNIX socket the main program listens on. May be omitted if the program
|
||||
# is intended to run in standalone mode only.
|
||||
socket:
|
||||
|
@ -63,6 +66,11 @@ handlers:
|
|||
- /usr/sbin/apache2ctl configtest
|
||||
- /usr/sbin/apache2ctl graceful
|
||||
|
||||
# Handler command timeouts. If this section is missing, or if no entry is
|
||||
# present for a handler, the default command timeout will be used.
|
||||
handler_timeouts:
|
||||
apache: 1
|
||||
|
||||
# Certificates that must be updated
|
||||
certificates:
|
||||
|
||||
|
@ -101,6 +109,10 @@ certificates:
|
|||
- /some/other/file.pem
|
||||
# Define what must be done after an update.
|
||||
after_update:
|
||||
# Command execution timeout for pre- and post-commands. If this entry is
|
||||
# missing, the default from command_timeout above will be used. This does
|
||||
# not affect handlers.
|
||||
command_timeout: 1
|
||||
# Commands to execute before handlers are run. The order of the commands
|
||||
# is respected. If a command fails to run, execution stops.
|
||||
pre_commands: []
|
||||
|
|
33
update.go
33
update.go
|
@ -122,7 +122,11 @@ func (u *tUpdate) runPreCommands() {
|
|||
|
||||
l := log.WithField("file", u.config.Certificates[i].Path)
|
||||
l.Info("Running pre-commands")
|
||||
err := u.runCommands(commands, l)
|
||||
timeout := u.config.CmdTimeout
|
||||
if u.config.Certificates[i].AfterUpdate.CmdTimeout != nil {
|
||||
timeout = *u.config.Certificates[i].AfterUpdate.CmdTimeout
|
||||
}
|
||||
err := u.runCommands(timeout, commands, l)
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
|
@ -159,7 +163,11 @@ func (u *tUpdate) runHandlers(handlers []string) map[string]bool {
|
|||
for _, handler := range handlers {
|
||||
l := log.WithField("handler", handler)
|
||||
l.Info("Running handler")
|
||||
err := u.runCommands(u.config.Handlers[handler], l)
|
||||
timeout := u.config.CmdTimeout
|
||||
if ht, exists := u.config.HandlerTimeouts[handler]; exists {
|
||||
timeout = ht
|
||||
}
|
||||
err := u.runCommands(timeout, u.config.Handlers[handler], l)
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
|
@ -204,7 +212,11 @@ func (u *tUpdate) runPostCommands() {
|
|||
|
||||
l := log.WithField("file", u.config.Certificates[i].Path)
|
||||
l.Info("Running post-commands")
|
||||
err := u.runCommands(commands, l)
|
||||
timeout := u.config.CmdTimeout
|
||||
if u.config.Certificates[i].AfterUpdate.CmdTimeout != nil {
|
||||
timeout = *u.config.Certificates[i].AfterUpdate.CmdTimeout
|
||||
}
|
||||
err := u.runCommands(timeout, commands, l)
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
|
@ -215,10 +227,10 @@ func (u *tUpdate) runPostCommands() {
|
|||
}
|
||||
}
|
||||
|
||||
// Run a list of commands
|
||||
func (u *tUpdate) runCommands(commands []string, log *logrus.Entry) error {
|
||||
// Run a list of commands.
|
||||
func (u *tUpdate) runCommands(timeout int, commands []string, log *logrus.Entry) error {
|
||||
for i := range commands {
|
||||
err := u.runCommand(commands[i], log)
|
||||
err := u.runCommand(timeout, commands[i], log)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"Failed while executing command '%s': %w",
|
||||
|
@ -230,11 +242,14 @@ func (u *tUpdate) runCommands(commands []string, log *logrus.Entry) error {
|
|||
}
|
||||
|
||||
// Run a command through the `sh` shell.
|
||||
func (b *tUpdate) runCommand(command string, log *logrus.Entry) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
func (b *tUpdate) runCommand(timeout int, command string, log *logrus.Entry) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
|
||||
defer cancel()
|
||||
|
||||
log = log.WithField("command", command)
|
||||
log = log.WithFields(logrus.Fields{
|
||||
"command": command,
|
||||
"timeout": timeout,
|
||||
})
|
||||
log.Debug("Executing command")
|
||||
cmd := exec.CommandContext(ctx, "sh", "-c", command)
|
||||
output, err := cmd.CombinedOutput()
|
||||
|
|
Loading…
Reference in a new issue