// "sync" sub-command: sync data to remote hosts
-// Copyright (C) 2021 Simon Ruderich
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// SPDX-License-Identifier: GPL-3.0-or-later
+// Copyright (C) 2021-2024 Simon Ruderich
package main
isTTY bool
+ loop *frontend.Loop
logFunc func(level safcm.LogLevel, escaped bool, msg string)
}
optionSshConfig := flag.String("sshconfig", "",
"`path` to ssh configuration file; used for tests")
- flag.CommandLine.Parse(args[2:])
+ flag.CommandLine.Parse(args[2:]) //nolint:errcheck
level, err := safcm.ParseLogLevel(*optionLog)
if err != nil {
loop := &frontend.Loop{
DebugConn: cfg.LogLevel >= safcm.LogDebug3,
LogEventFunc: func(x frontend.Event, failed *bool) {
- logEvent(x, cfg.LogLevel, isTTY, failed)
+ frontend.LogEvent(x, cfg.LogLevel, isTTY, failed)
},
SyncHostFunc: func(conn *rpc.Conn, host frontend.Host) error {
return host.(*Sync).Host(conn)
allHosts: allHosts,
allGroups: allGroups,
isTTY: isTTY,
+ loop: loop,
}
s.logFunc = func(level safcm.LogLevel, escaped bool,
msg string) {
- loop.Log(s, level, escaped, msg)
+ s.loop.Log(s, level, escaped, msg)
}
hosts = append(hosts, s)
}
return res, nil
}
-func logEvent(x frontend.Event, level safcm.LogLevel, isTTY bool, failed *bool) {
- // We have multiple event sources so this is somewhat ugly.
- var prefix, data string
- var color Color
- if x.Error != nil {
- prefix = "[error]"
- data = x.Error.Error()
- color = ColorRed
- // We logged an error, tell the caller
- *failed = true
- } else if x.Log.Level != 0 {
- if level < x.Log.Level {
- return
- }
- // LogError and LogDebug3 should not occur here
- switch x.Log.Level {
- case safcm.LogInfo:
- prefix = "[info]"
- case safcm.LogVerbose:
- prefix = "[verbose]"
- case safcm.LogDebug:
- prefix = "[debug]"
- case safcm.LogDebug2:
- prefix = "[debug2]"
- default:
- prefix = fmt.Sprintf("[INVALID=%d]", x.Log.Level)
- color = ColorRed
- }
- data = x.Log.Text
- } else {
- switch x.ConnEvent.Type {
- case rpc.ConnEventStderr:
- prefix = "[stderr]"
- case rpc.ConnEventDebug:
- prefix = "[debug3]"
- case rpc.ConnEventUpload:
- if level < safcm.LogInfo {
- return
- }
- prefix = "[info]"
- x.ConnEvent.Data = "remote helper upload in progress"
- default:
- prefix = fmt.Sprintf("[INVALID=%d]", x.ConnEvent.Type)
- color = ColorRed
- }
- data = x.ConnEvent.Data
- }
-
- host := x.Host.Name()
- if color != 0 {
- host = ColorString(isTTY, color, host)
- }
- // Make sure to escape control characters to prevent terminal
- // injection attacks
- if !x.Escaped {
- data = EscapeControlCharacters(isTTY, data)
- }
- log.Printf("%-9s [%s] %s", prefix, host, data)
-}
-
func (s *Sync) Name() string {
return s.host.Name
}
func (s *Sync) logVerbosef(format string, a ...interface{}) {
s.log(safcm.LogVerbose, false, fmt.Sprintf(format, a...))
}
-
-// sendRecv sends a message over conn and waits for the response. Any MsgLog
-// messages received before the final (non MsgLog) response are passed to
-// s.log.
-func (s *Sync) sendRecv(conn *rpc.Conn, msg safcm.Msg) (safcm.Msg, error) {
- err := conn.Send(msg)
- if err != nil {
- return nil, err
- }
- for {
- x, err := conn.Recv()
- if err != nil {
- return nil, err
- }
- log, ok := x.(safcm.MsgLog)
- if ok {
- s.log(log.Level, false, log.Text)
- continue
- }
- return x, nil
- }
-}