reverted to on hostname, added zerolog

This commit is contained in:
Andrew Woodlee 2023-01-03 23:57:19 -06:00
parent 6b85913316
commit ae87ccb4b5
2 changed files with 178 additions and 47 deletions

View File

@ -2,12 +2,14 @@ package backy
import (
"bytes"
"errors"
"fmt"
"io"
"os"
"os/exec"
"git.andrewnw.xyz/CyberShell/backy/pkg/logging"
"github.com/rs/zerolog/log"
"github.com/spf13/viper"
)
// Host defines a host to which to connect
@ -16,7 +18,7 @@ type Host struct {
ConfigFilePath string
Empty bool
Host string
HostName []string
HostName string
Port uint16
PrivateKeyPath string
PrivateKeyPassword string
@ -77,28 +79,24 @@ type BackupConfig struct {
* Runs a backup configuration
*/
func (command Command) RunCmd() logging.Logging {
func (command Command) RunCmd() {
var stdoutBuf, stderrBuf bytes.Buffer
var err error
var cmdArgs string
var cmdArgsStr string
for _, v := range command.CmdArgs {
cmdArgs += v
cmdArgsStr += fmt.Sprintf(" %s", v)
}
var remoteHost = &command.RemoteHost
fmt.Printf("\n\nRunning command: " + command.Cmd + " " + cmdArgs + " on host " + command.RemoteHost.Host + "...\n\n")
if command.Remote {
fmt.Printf("\n\nRunning command: " + command.Cmd + " " + cmdArgsStr + " on host " + command.Host + "...\n\n")
if command.Host != "" {
remoteHost.Port = 22
remoteHost.Host = command.RemoteHost.Host
sshClient, err := remoteHost.ConnectToSSHHost()
command.RemoteHost.Host = command.Host
command.RemoteHost.Port = 22
sshc, err := command.RemoteHost.ConnectToSSHHost()
if err != nil {
panic(fmt.Errorf("ssh dial: %w", err))
}
defer sshClient.Close()
s, err := sshClient.NewSession()
defer sshc.Close()
s, err := sshc.NewSession()
if err != nil {
panic(fmt.Errorf("new ssh session: %w", err))
}
@ -109,33 +107,55 @@ func (command Command) RunCmd() logging.Logging {
cmd += " " + a
}
var stdoutBuf, stderrBuf bytes.Buffer
s.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
s.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)
err = s.Run(cmd)
log.Info().Bytes(fmt.Sprintf("%s stdout", command.Cmd), stdoutBuf.Bytes()).Send()
log.Info().Bytes(fmt.Sprintf("%s stderr", command.Cmd), stderrBuf.Bytes()).Send()
if err != nil {
return logging.Logging{
Output: stdoutBuf.String(),
Err: fmt.Errorf("error running " + cmd + ": " + stderrBuf.String()),
}
panic(fmt.Errorf("error when running cmd " + cmd + "\n Error: " + err.Error()))
}
// fmt.Printf("Output: %s\n", string(output))
} else {
// shell := "/bin/bash"
var err error
if command.Shell != "" {
cmdArgsStr = fmt.Sprintf("%s %s", command.Cmd, cmdArgsStr)
localCMD := exec.Command(command.Shell, "-c", cmdArgsStr)
var stdoutBuf, stderrBuf bytes.Buffer
localCMD.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
localCMD.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)
err = localCMD.Run()
log.Info().Bytes(fmt.Sprintf("%s stdout", command.Cmd), stdoutBuf.Bytes()).Send()
log.Info().Bytes(fmt.Sprintf("%s stderr", command.Cmd), stderrBuf.Bytes()).Send()
if err != nil {
panic(fmt.Errorf("error when running cmd: %s: %w", command.Cmd, err))
}
return
}
localCMD := exec.Command(command.Cmd, command.CmdArgs...)
var stdoutBuf, stderrBuf bytes.Buffer
localCMD.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
localCMD.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)
err = localCMD.Run()
log.Info().Bytes(fmt.Sprintf("%s stdout", command.Cmd), stdoutBuf.Bytes()).Send()
log.Info().Bytes(fmt.Sprintf("%s stderr", command.Cmd), stderrBuf.Bytes()).Send()
if err != nil {
return logging.Logging{
Output: stdoutBuf.String(),
Err: fmt.Errorf(stderrBuf.String()),
}
panic(fmt.Errorf("error when running cmd: %s: %w", command.Cmd, err))
}
}
return logging.Logging{
Output: stdoutBuf.String(),
Err: nil,
}
func (config *BackyConfigFile) RunBackyConfig() {
for _, list := range config.CmdLists {
for _, cmd := range list {
cmdToRun := config.Cmds[cmd]
cmdToRun.RunCmd()
}
}
}
@ -152,3 +172,110 @@ func NewConfig() *BackyConfigFile {
Hosts: make(map[string]Host),
}
}
func ReadAndParseConfigFile() *BackyConfigFile {
backyConfigFile := NewConfig()
backyViper := viper.New()
backyViper.SetConfigName("backy") // name of config file (without extension)
backyViper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name
backyViper.AddConfigPath(".") // optionally look for config in the working directory
backyViper.AddConfigPath("$HOME/.config/backy") // call multiple times to add many search paths
err := backyViper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file
panic(fmt.Errorf("fatal error config file: %w", err))
}
commandsMap := backyViper.GetStringMapString("commands")
var cmdNames []string
for k := range commandsMap {
cmdNames = append(cmdNames, k)
}
hostConfigsMap := make(map[string]*viper.Viper)
for _, cmdName := range cmdNames {
var backupCmdStruct Command
println(cmdName)
subCmd := backyViper.Sub(getNestedConfig("commands", cmdName))
hostSet := subCmd.IsSet("host")
host := subCmd.GetString("host")
cmdSet := subCmd.IsSet("cmd")
cmd := subCmd.GetString("cmd")
cmdArgsSet := subCmd.IsSet("cmdargs")
cmdArgs := subCmd.GetStringSlice("cmdargs")
shellSet := subCmd.IsSet("shell")
shell := subCmd.GetString("shell")
if hostSet {
println("Host:")
println(host)
backupCmdStruct.Host = host
if backyViper.IsSet(getNestedConfig("hosts", host)) {
hostconfig := backyViper.Sub(getNestedConfig("hosts", host))
hostConfigsMap[host] = hostconfig
}
} else {
println("Host is not set")
}
if cmdSet {
println("Cmd:")
println(cmd)
backupCmdStruct.Cmd = cmd
} else {
println("Cmd is not set")
}
if shellSet {
println("Shell:")
println(shell)
backupCmdStruct.Shell = shell
} else {
println("Shell is not set")
}
if cmdArgsSet {
println("CmdArgs:")
for _, arg := range cmdArgs {
println(arg)
}
backupCmdStruct.CmdArgs = cmdArgs
} else {
println("CmdArgs are not set")
}
backyConfigFile.Cmds[cmdName] = backupCmdStruct
}
cmdListCfg := backyViper.GetStringMapStringSlice("cmd-lists")
var cmdNotFoundSliceErr []error
for cmdListName, cmdList := range cmdListCfg {
println("Cmd list: ", cmdListName)
for _, cmdInList := range cmdList {
println("Command in list: " + cmdInList)
_, cmdNameFound := backyConfigFile.Cmds[cmdInList]
if !backyViper.IsSet(getNestedConfig("commands", cmdInList)) && !cmdNameFound {
cmdNotFoundStr := fmt.Sprintf("command definition %s is not in config file\n", cmdInList)
cmdNotFoundErr := errors.New(cmdNotFoundStr)
cmdNotFoundSliceErr = append(cmdNotFoundSliceErr, cmdNotFoundErr)
} else {
backyConfigFile.CmdLists[cmdListName] = append(backyConfigFile.CmdLists[cmdListName], cmdInList)
}
}
}
for _, err := range cmdNotFoundSliceErr {
if err != nil {
fmt.Println(err.Error())
}
}
return backyConfigFile
}
func getNestedConfig(nestedConfig, key string) string {
return fmt.Sprintf("%s.%s", nestedConfig, key)
}
func getNestedSSHConfig(key string) string {
return fmt.Sprintf("hosts.%s.config", key)
}

View File

@ -30,14 +30,14 @@ type SshConfig struct {
host string
// host name to connect to
hostName []string
hostName string
user string
}
func (config SshConfig) GetSSHConfig() (SshConfig, error) {
hostNames := ssh_config.GetAll(config.host, "HostName")
if hostNames == nil {
hostNames := ssh_config.Get(config.host, "HostName")
if hostNames == "" {
return SshConfig{}, errors.New("hostname not found")
}
config.hostName = hostNames
@ -116,22 +116,24 @@ func (remoteConfig *Host) ConnectToSSHHost() (*ssh.Client, error) {
identityFile = filepath.Join(dir, identityFile[2:])
}
remoteConfig.PrivateKeyPath = filepath.Join(identityFile)
log.Debug().Str("Private key path", remoteConfig.PrivateKeyPath).Send()
}
remoteConfig.HostName, _ = cfg.GetAll(remoteConfig.Host, "HostName")
if remoteConfig.HostName == nil {
remoteConfig.HostName, _ = cfg.Get(remoteConfig.Host, "HostName")
remoteConfig.User, _ = cfg.Get(remoteConfig.Host, "User")
if remoteConfig.HostName == "" {
port, _ := cfg.Get(remoteConfig.Host, "Port")
if port == "" {
port = "22"
}
remoteConfig.HostName[0] = remoteConfig.Host + ":" + port
// remoteConfig.HostName[0] = remoteConfig.Host + ":" + port
} else {
for index, hostName := range remoteConfig.HostName {
port, _ := cfg.Get(remoteConfig.Host, "Port")
if port == "" {
port = "22"
}
remoteConfig.HostName[index] = hostName + ":" + port
// for index, hostName := range remoteConfig.HostName {
port, _ := cfg.Get(remoteConfig.Host, "Port")
if port == "" {
port = "22"
}
remoteConfig.HostName = remoteConfig.HostName + ":" + port
// remoteConfig.HostName[index] = hostName + ":" + port
}
// TODO: Add value/option to config for host key and add bool to check for host key
@ -151,14 +153,16 @@ func (remoteConfig *Host) ConnectToSSHHost() (*ssh.Client, error) {
User: remoteConfig.User,
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
HostKeyCallback: hostKeyCallback,
// HostKeyAlgorithms: []string{ssh.KeyAlgoECDSA256},
}
for _, host := range remoteConfig.HostName {
log.Info().Msgf("Connecting to host %s", host)
sshClient, connectErr = ssh.Dial("tcp", host, sshConfig)
if connectErr != nil {
log.Fatal().Err(connectErr).Str("host", host).Msg("error when connecting to host")
}
// for _, host := range remoteConfig.HostName {
log.Info().Msgf("Connecting to host %s", remoteConfig.HostName)
sshClient, connectErr = ssh.Dial("tcp", remoteConfig.HostName, sshConfig)
if connectErr != nil {
log.Fatal().Str("host", remoteConfig.HostName).Err(connectErr).Send()
}
// }
break
}