github.com/tommi2day/tnscli@v0.0.0-20240401211958-338fc0647b73/cmd/rootcmd.go (about)

     1  // Package cmd commands
     2  package cmd
     3  
     4  import (
     5  	"fmt"
     6  	"os"
     7  	"path"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/mitchellh/go-homedir"
    12  
    13  	"github.com/tommi2day/gomodules/dblib"
    14  
    15  	"github.com/spf13/viper"
    16  
    17  	log "github.com/sirupsen/logrus"
    18  	"github.com/spf13/cobra"
    19  	"github.com/tommi2day/gomodules/common"
    20  	prefixed "github.com/x-cray/logrus-prefixed-formatter"
    21  )
    22  
    23  const (
    24  	// allows you to override any config values using
    25  	// env APP_MY_VAR = "MY_VALUE"
    26  	// e.g. export APP_LDAP_USERNAME test
    27  	// maps to ldap.username
    28  
    29  	configEnvPrefix = "TNSCLI"
    30  	configName      = "tnscli"
    31  	configType      = "yaml"
    32  )
    33  
    34  var (
    35  	// RootCmd function to execute in tests
    36  	RootCmd = &cobra.Command{
    37  		Use:   "tnscli",
    38  		Short: "tnscli – Small Oracle TNS Service and Connect Test Tool",
    39  		Long:  ``,
    40  	}
    41  
    42  	oracleHome = common.GetEnv("ORACLE_HOME", "/opt/oracle")
    43  	tnsAdmin   = common.GetEnv("TNS_ADMIN", path.Join(oracleHome, "network", "admin"))
    44  
    45  	filename       = ""
    46  	debugFlag      = false
    47  	infoFlag       = false
    48  	cfgFile        = ""
    49  	noLogColorFlag = false
    50  	unitTestFlag   = false
    51  )
    52  
    53  func init() {
    54  	cobra.OnInitialize(initConfig, initLdapConfig)
    55  	// parse commandline
    56  	RootCmd.PersistentFlags().BoolVarP(&debugFlag, "debug", "", false, "verbose debug output")
    57  	RootCmd.PersistentFlags().BoolVarP(&infoFlag, "info", "", false, "reduced info output")
    58  	RootCmd.PersistentFlags().BoolVarP(&unitTestFlag, "unit-test", "", false, "redirect output for unit tests")
    59  	RootCmd.PersistentFlags().StringVarP(&tnsAdmin, "tns_admin", "A", tnsAdmin, "TNS_ADMIN directory")
    60  	RootCmd.PersistentFlags().StringVarP(&filename, "filename", "f", "", "path to alternate tnsnames.ora")
    61  	RootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file")
    62  	RootCmd.PersistentFlags().BoolVarP(&noLogColorFlag, "no-color", "", false, "disable colored log output")
    63  
    64  	if err := viper.BindPFlags(RootCmd.PersistentFlags()); err != nil {
    65  		log.Fatal(err)
    66  	}
    67  }
    68  
    69  // Execute run application
    70  func Execute() {
    71  	if err := RootCmd.Execute(); err != nil {
    72  		// fmt.Println(err)
    73  		os.Exit(1)
    74  	}
    75  }
    76  
    77  func initConfig() {
    78  	viper.SetConfigType(configType)
    79  	viper.SetConfigName(configName)
    80  	if cfgFile == "" {
    81  		// Use config file from the flag.
    82  		// Find home directory.
    83  		home, err := homedir.Dir()
    84  		if err != nil {
    85  			fmt.Println(err)
    86  			os.Exit(1)
    87  		}
    88  
    89  		// Search config in $HOME/etc and current directory.
    90  		etc := path.Join(home, "etc")
    91  		viper.AddConfigPath(etc)
    92  		viper.AddConfigPath(".")
    93  	} else {
    94  		// set filename form cli
    95  		viper.SetConfigFile(cfgFile)
    96  	}
    97  
    98  	// env var overrides
    99  	viper.AutomaticEnv() // read in environment variables that match
   100  	viper.SetEnvPrefix(configEnvPrefix)
   101  	// env var `LDAP_USERNAME` will be mapped to `ldap.username`
   102  	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
   103  
   104  	// If a config file is found, read it in.
   105  	haveConfig, err := processConfig()
   106  	// check flags
   107  	processFlags()
   108  
   109  	// logger settings
   110  	log.SetLevel(log.ErrorLevel)
   111  	switch {
   112  	case viper.GetBool("debug"):
   113  		// report function name
   114  		log.SetReportCaller(true)
   115  		log.SetLevel(log.DebugLevel)
   116  	case viper.GetBool("info"):
   117  		log.SetLevel(log.InfoLevel)
   118  	}
   119  	logFormatter := &prefixed.TextFormatter{
   120  		DisableColors:   noLogColorFlag,
   121  		FullTimestamp:   true,
   122  		TimestampFormat: time.RFC1123,
   123  	}
   124  	log.SetFormatter(logFormatter)
   125  	if unitTestFlag {
   126  		log.SetOutput(RootCmd.OutOrStdout())
   127  	}
   128  
   129  	// debug config file
   130  	if haveConfig {
   131  		log.Debugf("found configfile %s", cfgFile)
   132  	} else {
   133  		log.Debugf("Error using %s config : %s", configType, err)
   134  	}
   135  
   136  	// fix tnsadmin settings
   137  	ta, err := dblib.CheckTNSadmin(viper.GetString("tns_admin"))
   138  	if err == nil {
   139  		tnsAdmin = ta
   140  		viper.Set("tns_admin", tnsAdmin)
   141  	}
   142  	if filename == "" {
   143  		filename = path.Join(tnsAdmin, "tnsnames.ora")
   144  	}
   145  }
   146  
   147  // processConfig reads in config file and ENV variables if set.
   148  func processConfig() (bool, error) {
   149  	err := viper.ReadInConfig()
   150  	haveConfig := false
   151  	if err == nil {
   152  		cfgFile = viper.ConfigFileUsed()
   153  		haveConfig = true
   154  		viper.Set("config", cfgFile)
   155  	}
   156  	return haveConfig, err
   157  }
   158  
   159  // processFlags set config from flags
   160  func processFlags() {
   161  	if common.CmdFlagChanged(RootCmd, "debug") {
   162  		viper.Set("debug", debugFlag)
   163  	}
   164  	if common.CmdFlagChanged(RootCmd, "info") {
   165  		viper.Set("info", infoFlag)
   166  	}
   167  	if common.CmdFlagChanged(RootCmd, "no-color") {
   168  		viper.Set("no-color", noLogColorFlag)
   169  	}
   170  	debugFlag = viper.GetBool("debug")
   171  	infoFlag = viper.GetBool("info")
   172  }