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 }