v0.11.0
Some checks failed
Some checks failed
This commit is contained in:
0
pkg/backy/allowedexternaldirectives_enumer.go
Executable file → Normal file
0
pkg/backy/allowedexternaldirectives_enumer.go
Executable file → Normal file
@@ -145,6 +145,73 @@ func (e *LocalCommandExecutor) Run(cmd *Command, opts *ConfigOpts, logger zerolo
|
||||
return outputArr, nil
|
||||
}
|
||||
|
||||
// ensureRemoteHost ensures localCmd.RemoteHost is set for the given host.
|
||||
// It prefers opts.Hosts lookup and falls back to a minimal Host entry so remote execution can proceed.
|
||||
func (opts *ConfigOpts) ensureRemoteHost(localCmd *Command, host string) {
|
||||
if localCmd.RemoteHost != nil {
|
||||
return
|
||||
}
|
||||
if opts != nil && opts.Hosts != nil {
|
||||
if rh, found := opts.Hosts[host]; found {
|
||||
localCmd.RemoteHost = rh
|
||||
return
|
||||
}
|
||||
}
|
||||
// fallback: create a minimal Host so RunCmdOnHost sees a non-nil RemoteHost.
|
||||
// This uses host as the address/alias; further fields (user/key) will use defaults.
|
||||
localCmd.RemoteHost = &Host{Host: host}
|
||||
}
|
||||
|
||||
// ExecCommandOnHostsParallel runs a single configured command concurrently on the command.Hosts list.
|
||||
// It reuses the standard RunCmd / RunCmdOnHost flow so the behavior is identical to normal execution.
|
||||
func (opts *ConfigOpts) ExecCommandOnHostsParallel(cmdName string) ([]CmdResult, error) {
|
||||
cmdObj, ok := opts.Cmds[cmdName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("command %s not found", cmdName)
|
||||
}
|
||||
if len(cmdObj.Hosts) == 0 {
|
||||
return nil, fmt.Errorf("no hosts configured for command %s", cmdName)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
resultsCh := make(chan CmdResult, len(cmdObj.Hosts))
|
||||
|
||||
for _, host := range cmdObj.Hosts {
|
||||
wg.Add(1)
|
||||
go func(h string) {
|
||||
defer wg.Done()
|
||||
// shallow copy to avoid races
|
||||
local := *cmdObj
|
||||
local.Host = h
|
||||
opts.Logger.Debug().Str("host", h).Msg("executing command in parallel on host")
|
||||
|
||||
var err error
|
||||
if IsHostLocal(h) {
|
||||
_, err := local.RunCmd(local.GenerateLogger(opts), opts)
|
||||
resultsCh <- CmdResult{CmdName: cmdName, ListName: "", Error: err}
|
||||
return
|
||||
// _, err = local.RunCmd(local.GenerateLogger(opts), opts)
|
||||
}
|
||||
|
||||
// ensure RemoteHost is populated before calling RunCmdOnHost
|
||||
opts.ensureRemoteHost(&local, h)
|
||||
|
||||
_, err = local.RunCmdOnHost(local.GenerateLogger(opts), opts)
|
||||
|
||||
resultsCh <- CmdResult{CmdName: cmdName, ListName: "", Error: err}
|
||||
}(host)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
close(resultsCh)
|
||||
|
||||
var results []CmdResult
|
||||
for r := range resultsCh {
|
||||
results = append(results, r)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// RunCmd runs a Command.
|
||||
// The environment of local commands will be the machine's environment plus any extra
|
||||
// variables specified in the Env file or Environment.
|
||||
@@ -167,6 +234,14 @@ func (command *Command) RunCmd(cmdCtxLogger zerolog.Logger, opts *ConfigOpts) ([
|
||||
outputArr []string // holds the output strings returned by processes
|
||||
)
|
||||
|
||||
if command.Host != "" && command.Hosts != nil {
|
||||
cmdCtxLogger.Warn().Msg("both 'host' and 'hosts' are set; 'hosts' will be ignored")
|
||||
return nil, fmt.Errorf("both 'host' and 'hosts' are set; please set one or the other")
|
||||
} else if command.Hosts != nil {
|
||||
opts.ExecCommandOnHostsParallel(command.Name)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Getting the command type must be done before concatenating the arguments
|
||||
command = getCommandTypeAndSetCommandInfo(command)
|
||||
|
||||
|
||||
0
pkg/backy/commandtype_enumer.go
Executable file → Normal file
0
pkg/backy/commandtype_enumer.go
Executable file → Normal file
0
pkg/backy/packageoperation_enumer.go
Executable file → Normal file
0
pkg/backy/packageoperation_enumer.go
Executable file → Normal file
@@ -454,6 +454,10 @@ func (command *Command) RunCmdOnHost(cmdCtxLogger zerolog.Logger, opts *ConfigOp
|
||||
// cmdCtxLogger.Debug().Str("cmd", command.Cmd).Strs("args", command.Args).Send()
|
||||
|
||||
// Ensure SSH client is connected
|
||||
if command.RemoteHost == nil {
|
||||
cmdCtxLogger.Err(fmt.Errorf("remote host is not defined for command %s", command.Name)).Send()
|
||||
return nil, fmt.Errorf("remote host is not defined for command %s", command.Name)
|
||||
}
|
||||
if command.RemoteHost.SshClient == nil {
|
||||
if err := command.RemoteHost.ConnectToHost(opts); err != nil {
|
||||
return nil, fmt.Errorf("failed to connect to host: %w", err)
|
||||
|
||||
@@ -57,7 +57,8 @@ type (
|
||||
// See CommandType enum further down the page for acceptable values
|
||||
Type CommandType `yaml:"type,omitempty"`
|
||||
|
||||
Host string `yaml:"host,omitempty"`
|
||||
Host string `yaml:"host,omitempty"`
|
||||
Hosts []string `yaml:"hosts,omitempty"`
|
||||
|
||||
Hooks *Hooks `yaml:"hooks,omitempty"`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user