Progress on sub-commands, added unmarshalling
This commit is contained in:
		
							
								
								
									
										28
									
								
								cmd/backup.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								cmd/backup.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					package cmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"git.andrewnw.xyz/CyberShell/backy/pkg/backy"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						backupCmd = &cobra.Command{
 | 
				
			||||||
 | 
							Use:   "backup [--commands==list1,list2]",
 | 
				
			||||||
 | 
							Short: "Runs commands defined in config file.",
 | 
				
			||||||
 | 
							Long: `Backup executes commands defined in config file, 
 | 
				
			||||||
 | 
							use the -cmds flag to execute the specified commands.`,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					var CmdList *[]string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						cobra.OnInitialize(initConfig)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						backupCmd.Flags().StringSliceVarP(CmdList, "commands", "cmds", nil, "Accepts a comma-separated list of command lists to execute.")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func backup() {
 | 
				
			||||||
 | 
						backyConfig := backy.NewOpts(cfgFile)
 | 
				
			||||||
 | 
						backyConfig.GetConfig()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -32,7 +32,7 @@ func init() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file to read from")
 | 
						rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file to read from")
 | 
				
			||||||
	rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Sets verbose level")
 | 
						rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Sets verbose level")
 | 
				
			||||||
	rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration")
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func initConfig() {
 | 
					func initConfig() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,15 +7,19 @@ import (
 | 
				
			|||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"os/exec"
 | 
						"os/exec"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/rs/zerolog/log"
 | 
						"github.com/rs/zerolog"
 | 
				
			||||||
	"github.com/spf13/viper"
 | 
						"github.com/spf13/viper"
 | 
				
			||||||
 | 
						"gopkg.in/natefinch/lumberjack.v2"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Host defines a host to which to connect
 | 
					// Host defines a host to which to connect
 | 
				
			||||||
// If not provided, the values will be looked up in the default ssh config files
 | 
					// If not provided, the values will be looked up in the default ssh config files
 | 
				
			||||||
type Host struct {
 | 
					type Host struct {
 | 
				
			||||||
	ConfigFilePath     string
 | 
						ConfigFilePath     string
 | 
				
			||||||
 | 
						UseConfigFile      bool
 | 
				
			||||||
	Empty              bool
 | 
						Empty              bool
 | 
				
			||||||
	Host               string
 | 
						Host               string
 | 
				
			||||||
	HostName           string
 | 
						HostName           string
 | 
				
			||||||
@@ -26,44 +30,55 @@ type Host struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Command struct {
 | 
					type Command struct {
 | 
				
			||||||
	Remote bool
 | 
						Remote bool `yaml:"remote,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// command to run
 | 
						// command to run
 | 
				
			||||||
	Cmd string
 | 
						Cmd string `yaml:"cmd"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// host on which to run cmd
 | 
						// host on which to run cmd
 | 
				
			||||||
	Host string
 | 
						Host *string `yaml:"host,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
		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 defined
 | 
							Not applicable when host is defined.
 | 
				
			||||||
	*/
 | 
						*/
 | 
				
			||||||
	Shell string
 | 
						Shell string `yaml:"shell,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	RemoteHost Host
 | 
						RemoteHost Host `yaml:"-"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// cmdArgs is an array that holds the arguments to cmd
 | 
						// cmdArgs is an array that holds the arguments to cmd
 | 
				
			||||||
	CmdArgs []string
 | 
						CmdArgs []string `yaml:"cmdArgs,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
							Dir specifies a directory in which to run the command.
 | 
				
			||||||
 | 
							Ignored if Host is set.
 | 
				
			||||||
 | 
						*/
 | 
				
			||||||
 | 
						Dir *string `yaml:"dir,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type BackyGlobalOpts struct {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type BackyConfigFile struct {
 | 
					type BackyConfigFile struct {
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
		Cmds holds the commands for a list
 | 
							Cmds holds the commands for a list.
 | 
				
			||||||
		key is the name of the command
 | 
							Key is the name of the command,
 | 
				
			||||||
	*/
 | 
						*/
 | 
				
			||||||
	Cmds map[string]Command
 | 
						Cmds map[string]Command `yaml:"commands"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
		CmdLists holds the lists of commands to be run in order
 | 
							CmdLists holds the lists of commands to be run in order.
 | 
				
			||||||
		key is the command list name
 | 
							Key is the command list name.
 | 
				
			||||||
	*/
 | 
						*/
 | 
				
			||||||
	CmdLists map[string][]string
 | 
						CmdLists map[string][]string `yaml:"cmd-lists"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
		Hosts holds the Host config
 | 
							Hosts holds the Host config.
 | 
				
			||||||
		key is the host
 | 
							key is the host.
 | 
				
			||||||
	*/
 | 
						*/
 | 
				
			||||||
	Hosts map[string]Host
 | 
						Hosts map[string]Host `yaml:"hosts"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Logger zerolog.Logger
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BackupConfig is a configuration struct that is used to define backups
 | 
					// BackupConfig is a configuration struct that is used to define backups
 | 
				
			||||||
@@ -79,19 +94,19 @@ type BackupConfig struct {
 | 
				
			|||||||
* Runs a backup configuration
 | 
					* Runs a backup configuration
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (command Command) RunCmd() {
 | 
					func (command Command) RunCmd(log *zerolog.Logger) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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")
 | 
						fmt.Printf("\n\nRunning command: " + command.Cmd + " " + cmdArgsStr + " on host " + *command.Host + "...\n\n")
 | 
				
			||||||
	if command.Host != "" {
 | 
						if command.Host != nil {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		command.RemoteHost.Host = command.Host
 | 
							command.RemoteHost.Host = *command.Host
 | 
				
			||||||
		command.RemoteHost.Port = 22
 | 
							command.RemoteHost.Port = 22
 | 
				
			||||||
		sshc, err := command.RemoteHost.ConnectToSSHHost()
 | 
							sshc, err := command.RemoteHost.ConnectToSSHHost(log)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			panic(fmt.Errorf("ssh dial: %w", err))
 | 
								panic(fmt.Errorf("ssh dial: %w", err))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -123,6 +138,9 @@ func (command Command) RunCmd() {
 | 
				
			|||||||
		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)
 | 
				
			||||||
 | 
								if command.Dir != nil {
 | 
				
			||||||
 | 
									localCMD.Dir = *command.Dir
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var stdoutBuf, stderrBuf bytes.Buffer
 | 
								var stdoutBuf, stderrBuf bytes.Buffer
 | 
				
			||||||
			localCMD.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
 | 
								localCMD.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
 | 
				
			||||||
@@ -137,7 +155,9 @@ func (command Command) RunCmd() {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		localCMD := exec.Command(command.Cmd, command.CmdArgs...)
 | 
							localCMD := exec.Command(command.Cmd, command.CmdArgs...)
 | 
				
			||||||
 | 
							if command.Dir != nil {
 | 
				
			||||||
 | 
								localCMD.Dir = *command.Dir
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		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)
 | 
				
			||||||
@@ -154,17 +174,49 @@ func (config *BackyConfigFile) RunBackyConfig() {
 | 
				
			|||||||
	for _, list := range config.CmdLists {
 | 
						for _, list := range config.CmdLists {
 | 
				
			||||||
		for _, cmd := range list {
 | 
							for _, cmd := range list {
 | 
				
			||||||
			cmdToRun := config.Cmds[cmd]
 | 
								cmdToRun := config.Cmds[cmd]
 | 
				
			||||||
			cmdToRun.RunCmd()
 | 
								cmdToRun.RunCmd(&config.Logger)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type BackyConfigOpts struct {
 | 
				
			||||||
 | 
						// Holds config file
 | 
				
			||||||
 | 
						ConfigFile *BackyConfigFile
 | 
				
			||||||
 | 
						// Holds config file
 | 
				
			||||||
 | 
						ConfigFilePath string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Global log level
 | 
				
			||||||
 | 
						BackyLogLvl *string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type BackyOptionFunc func(*BackyConfigOpts)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *BackyConfigOpts) LogLvl(level string) BackyOptionFunc {
 | 
				
			||||||
 | 
						return func(bco *BackyConfigOpts) {
 | 
				
			||||||
 | 
							c.BackyLogLvl = &level
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (c *BackyConfigOpts) GetConfig() {
 | 
				
			||||||
 | 
						c.ConfigFile = ReadAndParseConfigFile(c.ConfigFilePath)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func New() BackupConfig {
 | 
					func New() BackupConfig {
 | 
				
			||||||
	return BackupConfig{}
 | 
						return BackupConfig{}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewConfig initializes new config that holds information
 | 
					func NewOpts(configFilePath string, opts ...BackyOptionFunc) *BackyConfigOpts {
 | 
				
			||||||
// from the config file
 | 
						b := &BackyConfigOpts{}
 | 
				
			||||||
 | 
						b.ConfigFilePath = configFilePath
 | 
				
			||||||
 | 
						for _, opt := range opts {
 | 
				
			||||||
 | 
							opt(b)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return b
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					*	NewConfig initializes new config that holds information
 | 
				
			||||||
 | 
					* 	from the config file
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
func NewConfig() *BackyConfigFile {
 | 
					func NewConfig() *BackyConfigFile {
 | 
				
			||||||
	return &BackyConfigFile{
 | 
						return &BackyConfigFile{
 | 
				
			||||||
		Cmds:     make(map[string]Command),
 | 
							Cmds:     make(map[string]Command),
 | 
				
			||||||
@@ -173,21 +225,89 @@ func NewConfig() *BackyConfigFile {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ReadAndParseConfigFile() *BackyConfigFile {
 | 
					func ReadAndParseConfigFile(configFile string) *BackyConfigFile {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	backyConfigFile := NewConfig()
 | 
						backyConfigFile := NewConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	backyViper := viper.New()
 | 
						backyViper := viper.New()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if configFile != "" {
 | 
				
			||||||
 | 
							backyViper.SetConfigFile(configFile)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
		backyViper.SetConfigName("backy")               // name of config file (without extension)
 | 
							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.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(".")                   // optionally look for config in the working directory
 | 
				
			||||||
		backyViper.AddConfigPath("$HOME/.config/backy") // call multiple times to add many search paths
 | 
							backyViper.AddConfigPath("$HOME/.config/backy") // call multiple times to add many search paths
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	err := backyViper.ReadInConfig() // Find and read the config file
 | 
						err := backyViper.ReadInConfig() // Find and read the config file
 | 
				
			||||||
	if err != nil {                  // Handle errors reading the config file
 | 
						if err != nil {                  // Handle errors reading the config file
 | 
				
			||||||
		panic(fmt.Errorf("fatal error config file: %w", err))
 | 
							panic(fmt.Errorf("fatal error finding config file: %w", err))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						backyLoggingOpts := backyViper.Sub("logging")
 | 
				
			||||||
 | 
						verbose := backyLoggingOpts.GetBool("verbose")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logFile := backyLoggingOpts.GetString("file")
 | 
				
			||||||
 | 
						if verbose {
 | 
				
			||||||
 | 
							zerolog.Level.String(zerolog.DebugLevel)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC1123}
 | 
				
			||||||
 | 
						output.FormatLevel = func(i interface{}) string {
 | 
				
			||||||
 | 
							return strings.ToUpper(fmt.Sprintf("| %-6s|", i))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						output.FormatMessage = func(i interface{}) string {
 | 
				
			||||||
 | 
							return fmt.Sprintf("%s", i)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						output.FormatFieldName = func(i interface{}) string {
 | 
				
			||||||
 | 
							return fmt.Sprintf("%s: ", i)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						output.FormatFieldValue = func(i interface{}) string {
 | 
				
			||||||
 | 
							return strings.ToUpper(fmt.Sprintf("%s", i))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fileLogger := &lumberjack.Logger{
 | 
				
			||||||
 | 
							MaxSize:    500, // megabytes
 | 
				
			||||||
 | 
							MaxBackups: 3,
 | 
				
			||||||
 | 
							MaxAge:     28,   //days
 | 
				
			||||||
 | 
							Compress:   true, // disabled by default
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if strings.Trim(logFile, " ") != "" {
 | 
				
			||||||
 | 
							fileLogger.Filename = logFile
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							fileLogger.Filename = "./backy.log"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// UNIX Time is faster and smaller than most timestamps
 | 
				
			||||||
 | 
						zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
 | 
				
			||||||
 | 
						// zerolog.TimeFieldFormat = time.RFC1123
 | 
				
			||||||
 | 
						writers := zerolog.MultiLevelWriter(os.Stdout, fileLogger)
 | 
				
			||||||
 | 
						log := zerolog.New(writers).With().Timestamp().Logger()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						backyConfigFile.Logger = log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	commandsMap := backyViper.GetStringMapString("commands")
 | 
						commandsMap := backyViper.GetStringMapString("commands")
 | 
				
			||||||
 | 
						commandsMapViper := backyViper.Sub("commands")
 | 
				
			||||||
 | 
						unmarshalErr := commandsMapViper.Unmarshal(&backyConfigFile.Cmds)
 | 
				
			||||||
 | 
						if unmarshalErr != nil {
 | 
				
			||||||
 | 
							panic(fmt.Errorf("error unmarshalling cmds struct: %w", unmarshalErr))
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							for cmdName, cmdConf := range backyConfigFile.Cmds {
 | 
				
			||||||
 | 
								fmt.Printf("\nCommand Name: %s\n", cmdName)
 | 
				
			||||||
 | 
								fmt.Printf("Shell: %v\n", cmdConf.Shell)
 | 
				
			||||||
 | 
								fmt.Printf("Command: %s\n", cmdConf.Cmd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if len(cmdConf.CmdArgs) > 0 {
 | 
				
			||||||
 | 
									fmt.Println("\nCmd Args:")
 | 
				
			||||||
 | 
									for _, args := range cmdConf.CmdArgs {
 | 
				
			||||||
 | 
										fmt.Printf("%s\n", args)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if cmdConf.Host != nil {
 | 
				
			||||||
 | 
									fmt.Printf("Host: %s\n", *backyConfigFile.Cmds[cmdName].Host)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							os.Exit(0)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	var cmdNames []string
 | 
						var cmdNames []string
 | 
				
			||||||
	for k := range commandsMap {
 | 
						for k := range commandsMap {
 | 
				
			||||||
		cmdNames = append(cmdNames, k)
 | 
							cmdNames = append(cmdNames, k)
 | 
				
			||||||
@@ -196,63 +316,30 @@ func ReadAndParseConfigFile() *BackyConfigFile {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	for _, cmdName := range cmdNames {
 | 
						for _, cmdName := range cmdNames {
 | 
				
			||||||
		var backupCmdStruct Command
 | 
							var backupCmdStruct Command
 | 
				
			||||||
		println(cmdName)
 | 
					 | 
				
			||||||
		subCmd := backyViper.Sub(getNestedConfig("commands", cmdName))
 | 
							subCmd := backyViper.Sub(getNestedConfig("commands", cmdName))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		hostSet := subCmd.IsSet("host")
 | 
							hostSet := subCmd.IsSet("host")
 | 
				
			||||||
		host := subCmd.GetString("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 {
 | 
							if hostSet {
 | 
				
			||||||
			println("Host:")
 | 
								log.Debug().Timestamp().Str(cmdName, "host is set").Str("host", host).Send()
 | 
				
			||||||
			println(host)
 | 
								backupCmdStruct.Host = &host
 | 
				
			||||||
			backupCmdStruct.Host = host
 | 
					 | 
				
			||||||
			if backyViper.IsSet(getNestedConfig("hosts", host)) {
 | 
								if backyViper.IsSet(getNestedConfig("hosts", host)) {
 | 
				
			||||||
				hostconfig := backyViper.Sub(getNestedConfig("hosts", host))
 | 
									hostconfig := backyViper.Sub(getNestedConfig("hosts", host))
 | 
				
			||||||
				hostConfigsMap[host] = hostconfig
 | 
									hostConfigsMap[host] = hostconfig
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			println("Host is not set")
 | 
								log.Debug().Timestamp().Str(cmdName, "host is not set").Send()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if cmdSet {
 | 
					
 | 
				
			||||||
			println("Cmd:")
 | 
							// backyConfigFile.Cmds[cmdName] = backupCmdStruct
 | 
				
			||||||
			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")
 | 
						cmdListCfg := backyViper.GetStringMapStringSlice("cmd-lists")
 | 
				
			||||||
	var cmdNotFoundSliceErr []error
 | 
						var cmdNotFoundSliceErr []error
 | 
				
			||||||
	for cmdListName, cmdList := range cmdListCfg {
 | 
						for cmdListName, cmdList := range cmdListCfg {
 | 
				
			||||||
		println("Cmd list: ", cmdListName)
 | 
					 | 
				
			||||||
		for _, cmdInList := range cmdList {
 | 
							for _, cmdInList := range cmdList {
 | 
				
			||||||
			println("Command in list: " + cmdInList)
 | 
					 | 
				
			||||||
			_, cmdNameFound := backyConfigFile.Cmds[cmdInList]
 | 
								_, cmdNameFound := backyConfigFile.Cmds[cmdInList]
 | 
				
			||||||
			if !backyViper.IsSet(getNestedConfig("commands", cmdInList)) && !cmdNameFound {
 | 
								if !backyViper.IsSet(getNestedConfig("commands", cmdInList)) && !cmdNameFound {
 | 
				
			||||||
				cmdNotFoundStr := fmt.Sprintf("command definition %s is not in config file\n", cmdInList)
 | 
									cmdNotFoundStr := fmt.Sprintf("command definition %s is not in config file\n", cmdInList)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,18 +2,15 @@ package backy
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"os/user"
 | 
						"os/user"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/kevinburke/ssh_config"
 | 
						"github.com/kevinburke/ssh_config"
 | 
				
			||||||
	"github.com/rs/zerolog"
 | 
						"github.com/rs/zerolog"
 | 
				
			||||||
	"golang.org/x/crypto/ssh"
 | 
						"golang.org/x/crypto/ssh"
 | 
				
			||||||
	"golang.org/x/crypto/ssh/knownhosts"
 | 
						"golang.org/x/crypto/ssh/knownhosts"
 | 
				
			||||||
	"gopkg.in/natefinch/lumberjack.v2"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type SshConfig struct {
 | 
					type SshConfig struct {
 | 
				
			||||||
@@ -53,45 +50,7 @@ func (config SshConfig) GetSSHConfig() (SshConfig, error) {
 | 
				
			|||||||
	return config, nil
 | 
						return config, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (remoteConfig *Host) ConnectToSSHHost() (*ssh.Client, error) {
 | 
					func (remoteConfig *Host) ConnectToSSHHost(log *zerolog.Logger) (*ssh.Client, error) {
 | 
				
			||||||
	output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}
 | 
					 | 
				
			||||||
	output.FormatLevel = func(i interface{}) string {
 | 
					 | 
				
			||||||
		return strings.ToUpper(fmt.Sprintf("| %-6s|", i))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	output.FormatMessage = func(i interface{}) string {
 | 
					 | 
				
			||||||
		return fmt.Sprintf("%s", i)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	output.FormatFieldName = func(i interface{}) string {
 | 
					 | 
				
			||||||
		return fmt.Sprintf("%s: ", i)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	output.FormatFieldValue = func(i interface{}) string {
 | 
					 | 
				
			||||||
		return strings.ToUpper(fmt.Sprintf("%s", i))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fileLogger := &lumberjack.Logger{
 | 
					 | 
				
			||||||
		Filename:   "./backy.log",
 | 
					 | 
				
			||||||
		MaxSize:    500, // megabytes
 | 
					 | 
				
			||||||
		MaxBackups: 3,
 | 
					 | 
				
			||||||
		MaxAge:     28,   //days
 | 
					 | 
				
			||||||
		Compress:   true, // disabled by default
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// fileOutput := zerolog.ConsoleWriter{Out: fileLogger, TimeFormat: time.RFC3339}
 | 
					 | 
				
			||||||
	// fileOutput.FormatLevel = func(i interface{}) string {
 | 
					 | 
				
			||||||
	// 	return strings.ToUpper(fmt.Sprintf("| %-6s|", i))
 | 
					 | 
				
			||||||
	// }
 | 
					 | 
				
			||||||
	// fileOutput.FormatMessage = func(i interface{}) string {
 | 
					 | 
				
			||||||
	// 	return fmt.Sprintf("%s", i)
 | 
					 | 
				
			||||||
	// }
 | 
					 | 
				
			||||||
	// fileOutput.FormatFieldName = func(i interface{}) string {
 | 
					 | 
				
			||||||
	// 	return fmt.Sprintf("%s: ", i)
 | 
					 | 
				
			||||||
	// }
 | 
					 | 
				
			||||||
	// fileOutput.FormatFieldValue = func(i interface{}) string {
 | 
					 | 
				
			||||||
	// 	return strings.ToUpper(fmt.Sprintf("%s", i))
 | 
					 | 
				
			||||||
	// }
 | 
					 | 
				
			||||||
	zerolog.TimeFieldFormat = time.RFC1123
 | 
					 | 
				
			||||||
	writers := zerolog.MultiLevelWriter(os.Stdout, fileLogger)
 | 
					 | 
				
			||||||
	log := zerolog.New(writers).With().Timestamp().Logger()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var sshClient *ssh.Client
 | 
						var sshClient *ssh.Client
 | 
				
			||||||
	var connectErr error
 | 
						var connectErr error
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user