more progress on reading config file
This commit is contained in:
parent
cc71e12cb1
commit
dfd1aa8ccf
170
backup.go
170
backup.go
@ -13,47 +13,75 @@ import (
|
|||||||
|
|
||||||
"git.andrewnw.xyz/CyberShell/backy/pkg/backy"
|
"git.andrewnw.xyz/CyberShell/backy/pkg/backy"
|
||||||
"github.com/kevinburke/ssh_config"
|
"github.com/kevinburke/ssh_config"
|
||||||
|
"github.com/spf13/viper"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// const logFile = "backy.log"
|
||||||
|
|
||||||
type backupCommand struct {
|
type backupCommand struct {
|
||||||
|
|
||||||
// command to run
|
// command to run
|
||||||
cmd string
|
Cmd string
|
||||||
|
|
||||||
// host on which to run cmd
|
// host on which to run cmd
|
||||||
host string
|
Host string
|
||||||
|
|
||||||
// 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 not local
|
// Not applicable when host is not local
|
||||||
shell string
|
Shell string
|
||||||
// path to the command
|
|
||||||
|
|
||||||
path string
|
|
||||||
|
|
||||||
// cmdArgs is an array that holds the arguments to cmd
|
// cmdArgs is an array that holds the arguments to cmd
|
||||||
cmdArgs []string
|
CmdArgs []string
|
||||||
}
|
}
|
||||||
|
|
||||||
var remoteHost *backy.Host
|
// type config struct {
|
||||||
|
// Commands struct {
|
||||||
|
// backupCommand `mapstructure:",squash"`
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
var testCmd = &backupCommand{
|
||||||
|
Cmd: "hostname",
|
||||||
|
Shell: "bash",
|
||||||
|
CmdArgs: []string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
var remoteHost backy.Host
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
|
var test = true
|
||||||
|
|
||||||
|
if test {
|
||||||
|
|
||||||
|
readConfigFile()
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
remoteHost.User = "root"
|
||||||
|
testCmd.runCmd()
|
||||||
|
// shutdownEmailSvr.runCmd()
|
||||||
|
// backupEmailSvrRestic.runCmd()
|
||||||
|
// backupEmailSvrRsync.runCmd()
|
||||||
|
// startEmailSvr.runCmd()
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (command *backupCommand) runCmd() {
|
func (command *backupCommand) runCmd() {
|
||||||
|
|
||||||
var cmdArgsStr string
|
var cmdArgsStr string
|
||||||
for _, v := range command.cmdArgs {
|
for _, v := range command.CmdArgs {
|
||||||
cmdArgsStr += fmt.Sprintf(" %s", v)
|
cmdArgsStr += fmt.Sprintf(" %s", v)
|
||||||
}
|
}
|
||||||
fmt.Printf("\n\nRunning command: " + command.cmd + " " + cmdArgsStr + " on host " + command.host + "...\n\n")
|
|
||||||
if command.host != "local" {
|
fmt.Printf("\n\nRunning command: " + command.Cmd + " " + cmdArgsStr + " on host " + command.Host + "...\n\n")
|
||||||
|
if command.Host != "local" {
|
||||||
|
|
||||||
remoteHost.Port = 22
|
remoteHost.Port = 22
|
||||||
remoteHost.Host = command.host
|
remoteHost.Host = command.Host
|
||||||
|
|
||||||
sshc, err := connectToSSHHost(remoteHost)
|
sshc, err := connectToSSHHost(&remoteHost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("ssh dial: %w", err))
|
panic(fmt.Errorf("ssh dial: %w", err))
|
||||||
}
|
}
|
||||||
@ -64,8 +92,8 @@ func (command *backupCommand) runCmd() {
|
|||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
cmd := command.cmd
|
cmd := command.Cmd
|
||||||
for _, a := range command.cmdArgs {
|
for _, a := range command.CmdArgs {
|
||||||
cmd += " " + a
|
cmd += " " + a
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,31 +104,31 @@ func (command *backupCommand) runCmd() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("error when running cmd " + cmd + "\n Error: " + err.Error()))
|
panic(fmt.Errorf("error when running cmd " + cmd + "\n Error: " + err.Error()))
|
||||||
}
|
}
|
||||||
// fmt.Printf("Output: %s\n", string(output))
|
|
||||||
} else {
|
} else {
|
||||||
// shell := "/bin/bash"
|
// shell := "/bin/bash"
|
||||||
var err error
|
var err error
|
||||||
if command.shell != "" {
|
if command.Shell != "" {
|
||||||
cmdArgsStr = fmt.Sprintf("%s %s", command.cmd, cmdArgsStr)
|
cmdArgsStr = fmt.Sprintf("%s %s", command.Cmd, cmdArgsStr)
|
||||||
localCMD := exec.Command(command.shell, "-c", cmdArgsStr)
|
localCMD := exec.Command(command.Shell, "-c", cmdArgsStr)
|
||||||
|
|
||||||
var stdoutBuf, stderrBuf bytes.Buffer
|
var stdoutBuf, stderrBuf bytes.Buffer
|
||||||
localCMD.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
|
localCMD.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
|
||||||
localCMD.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)
|
localCMD.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)
|
||||||
err = localCMD.Run()
|
err = localCMD.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("error when running cmd: %s: %w", command.cmd, err))
|
panic(fmt.Errorf("error when running cmd: %s: %w", command.Cmd, err))
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
// localCMD := exec.Command(command.cmd, command.args...)
|
localCMD := exec.Command(command.Cmd, command.CmdArgs...)
|
||||||
|
|
||||||
// var stdoutBuf, stderrBuf bytes.Buffer
|
var stdoutBuf, stderrBuf bytes.Buffer
|
||||||
// localCMD.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
|
localCMD.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
|
||||||
// localCMD.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)
|
localCMD.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)
|
||||||
// err = localCMD.Run()
|
err = localCMD.Run()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("error when running cmd: %s: %w", command.cmd, err))
|
panic(fmt.Errorf("error when running cmd: %s: %w", command.Cmd, err))
|
||||||
}
|
}
|
||||||
// fmt.Printf("%s\n", string(output))
|
// fmt.Printf("%s\n", string(output))
|
||||||
}
|
}
|
||||||
@ -147,7 +175,7 @@ func connectToSSHHost(remoteConfig *backy.Host) (*ssh.Client, error) {
|
|||||||
panic(fmt.Errorf("parse private key: %w", err))
|
panic(fmt.Errorf("parse private key: %w", err))
|
||||||
}
|
}
|
||||||
sshConfig := &ssh.ClientConfig{
|
sshConfig := &ssh.ClientConfig{
|
||||||
User: "root",
|
User: remoteHost.User,
|
||||||
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
|
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
|
||||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
@ -158,3 +186,91 @@ func connectToSSHHost(remoteConfig *backy.Host) (*ssh.Client, error) {
|
|||||||
}
|
}
|
||||||
return sshc, connectErr
|
return sshc, connectErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func readConfigFile() {
|
||||||
|
viper.SetConfigName("backy") // name of config file (without extension)
|
||||||
|
viper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name
|
||||||
|
viper.AddConfigPath("$HOME/.config/backy") // call multiple times to add many search paths
|
||||||
|
viper.AddConfigPath(".") // optionally look for config in the working directory
|
||||||
|
err := viper.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))
|
||||||
|
}
|
||||||
|
// if err := viper.ReadInConfig(); err != nil {
|
||||||
|
// if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
||||||
|
// // Config file not found; ignore error if desired
|
||||||
|
// } else {
|
||||||
|
// // Config file was found but another error was produced
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Config file found and successfully parsed
|
||||||
|
|
||||||
|
// viper.WriteConfig() // writes current config to predefined path set by 'viper.AddConfigPath()' and 'viper.SetConfigName'
|
||||||
|
|
||||||
|
// err = viper.Unmarshal(&C)
|
||||||
|
// if err != nil {
|
||||||
|
// panic(fmt.Errorf("unable to decode into struct, %v", err))
|
||||||
|
// }
|
||||||
|
commandsMap := viper.GetStringMapString("commands")
|
||||||
|
var cmdNames []string
|
||||||
|
for k := range commandsMap {
|
||||||
|
cmdNames = append(cmdNames, k)
|
||||||
|
}
|
||||||
|
var cmdStructs []backupCommand
|
||||||
|
for _, cmdName := range cmdNames {
|
||||||
|
var backupCmdStruct backupCommand
|
||||||
|
println(cmdName)
|
||||||
|
subCmd := viper.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")
|
||||||
|
|
||||||
|
if hostSet {
|
||||||
|
println("Host:")
|
||||||
|
println(host)
|
||||||
|
backupCmdStruct.Host = host
|
||||||
|
} else {
|
||||||
|
println("Host is not set")
|
||||||
|
}
|
||||||
|
if cmdSet {
|
||||||
|
println("Cmd:")
|
||||||
|
println(cmd)
|
||||||
|
backupCmdStruct.Cmd = cmd
|
||||||
|
} else {
|
||||||
|
println("Cmd is not set")
|
||||||
|
}
|
||||||
|
if cmdArgsSet {
|
||||||
|
println("CmdArgs:")
|
||||||
|
for _, arg := range cmdArgs {
|
||||||
|
println(arg)
|
||||||
|
}
|
||||||
|
backupCmdStruct.CmdArgs = cmdArgs
|
||||||
|
} else {
|
||||||
|
println("CmdArgs is not set")
|
||||||
|
}
|
||||||
|
cmdStructs = append(cmdStructs, backupCmdStruct)
|
||||||
|
for _, cmd := range cmdStructs {
|
||||||
|
fmt.Printf("Cmd is %s\n", cmd.Cmd)
|
||||||
|
fmt.Printf("Host is %s\n", cmd.Host)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmdOrder := viper.GetStringMapStringSlice("cmd-order")
|
||||||
|
for cmd, orderSlice := range cmdOrder {
|
||||||
|
println("Cmd name: ", cmd)
|
||||||
|
println("Cmd order: ")
|
||||||
|
for _, v := range orderSlice {
|
||||||
|
println(v)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNestedConfig(nestedConfig, key string) string {
|
||||||
|
return fmt.Sprintf("%s.%s", nestedConfig, key)
|
||||||
|
}
|
||||||
|
160
mail.go
160
mail.go
@ -1,160 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"os/exec"
|
|
||||||
"os/user"
|
|
||||||
|
|
||||||
"git.andrewnw.xyz/CyberShell/backy/pkg/backy"
|
|
||||||
"github.com/kevinburke/ssh_config"
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
)
|
|
||||||
|
|
||||||
type backupCommand struct {
|
|
||||||
|
|
||||||
// command to run
|
|
||||||
cmd string
|
|
||||||
|
|
||||||
// host on which to run cmd
|
|
||||||
host string
|
|
||||||
|
|
||||||
// Shell specifies which shell to run the command in, if any
|
|
||||||
// Not applicable when host is not local
|
|
||||||
shell string
|
|
||||||
// path to the command
|
|
||||||
|
|
||||||
path string
|
|
||||||
|
|
||||||
// cmdArgs is an array that holds the arguments to cmd
|
|
||||||
cmdArgs []string
|
|
||||||
}
|
|
||||||
|
|
||||||
var remoteHost *backy.Host
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (command *backupCommand) runCmd() {
|
|
||||||
|
|
||||||
var cmdArgsStr string
|
|
||||||
for _, v := range command.cmdArgs {
|
|
||||||
cmdArgsStr += fmt.Sprintf(" %s", v)
|
|
||||||
}
|
|
||||||
fmt.Printf("\n\nRunning command: " + command.cmd + " " + cmdArgsStr + " on host " + command.host + "...\n\n")
|
|
||||||
if command.host != "local" {
|
|
||||||
|
|
||||||
remoteHost.Port = 22
|
|
||||||
remoteHost.Host = command.host
|
|
||||||
|
|
||||||
sshc, err := connectToSSHHost(remoteHost)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("ssh dial: %w", err))
|
|
||||||
}
|
|
||||||
defer sshc.Close()
|
|
||||||
s, err := sshc.NewSession()
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("new ssh session: %w", err))
|
|
||||||
}
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
cmd := command.cmd
|
|
||||||
for _, a := range command.cmdArgs {
|
|
||||||
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)
|
|
||||||
if err != nil {
|
|
||||||
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()
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("error when running cmd: %s: %w", command.cmd, err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// localCMD := exec.Command(command.cmd, command.args...)
|
|
||||||
|
|
||||||
// var stdoutBuf, stderrBuf bytes.Buffer
|
|
||||||
// localCMD.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
|
|
||||||
// localCMD.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)
|
|
||||||
// err = localCMD.Run()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("error when running cmd: %s: %w", command.cmd, err))
|
|
||||||
}
|
|
||||||
// fmt.Printf("%s\n", string(output))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func connectToSSHHost(remoteConfig *backy.Host) (*ssh.Client, error) {
|
|
||||||
var sshc *ssh.Client
|
|
||||||
var connectErr error
|
|
||||||
|
|
||||||
f, _ := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "config"))
|
|
||||||
cfg, _ := ssh_config.Decode(f)
|
|
||||||
for _, host := range cfg.Hosts {
|
|
||||||
if host.Matches(remoteConfig.Host) {
|
|
||||||
var identityFile string
|
|
||||||
if remoteConfig.PrivateKeyPath == "" {
|
|
||||||
identityFile, _ = cfg.Get(remoteConfig.Host, "IdentityFile")
|
|
||||||
usr, _ := user.Current()
|
|
||||||
dir := usr.HomeDir
|
|
||||||
if identityFile == "~" {
|
|
||||||
// In case of "~", which won't be caught by the "else if"
|
|
||||||
identityFile = dir
|
|
||||||
} else if strings.HasPrefix(identityFile, "~/") {
|
|
||||||
// Use strings.HasPrefix so we don't match paths like
|
|
||||||
// "/something/~/something/"
|
|
||||||
identityFile = filepath.Join(dir, identityFile[2:])
|
|
||||||
}
|
|
||||||
remoteConfig.PrivateKeyPath = filepath.Join(identityFile)
|
|
||||||
}
|
|
||||||
remoteConfig.HostName, _ = cfg.Get(remoteConfig.Host, "HostName")
|
|
||||||
if remoteConfig.HostName == "" {
|
|
||||||
remoteConfig.HostName = remoteConfig.Host
|
|
||||||
}
|
|
||||||
port, _ := cfg.Get(remoteConfig.Host, "Port")
|
|
||||||
if port == "" {
|
|
||||||
port = "22"
|
|
||||||
}
|
|
||||||
privateKey, err := os.ReadFile(remoteConfig.PrivateKeyPath)
|
|
||||||
remoteConfig.HostName = remoteConfig.HostName + ":" + port
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("read private key: %w", err))
|
|
||||||
}
|
|
||||||
signer, err := ssh.ParsePrivateKey(privateKey)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("parse private key: %w", err))
|
|
||||||
}
|
|
||||||
sshConfig := &ssh.ClientConfig{
|
|
||||||
User: "root",
|
|
||||||
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
|
|
||||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
|
||||||
}
|
|
||||||
sshc, connectErr = ssh.Dial("tcp", remoteConfig.HostName, sshConfig)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return sshc, connectErr
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user