diff --git a/cmd/root.go b/cmd/root.go index cdb8166..18ac260 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -19,7 +19,7 @@ import ( "time" ) -const( +const ( ServiceName string = "gridengine_prometheus" viperSGEKey string = "sge." ) @@ -28,21 +28,21 @@ var entropy rand.Source var random *rand.Rand var RootCmd = &cobra.Command{ - Use: "gridengine_prometheus", - Short: "Start the exporter", - Long: "Start the prometheus exporter and listen for requests", - Example: `gridengine_prometheus --pidfile /var/run/gridengine_prometheus.pid --port 9018`, - Run: Start, + Use: "gridengine_prometheus", + Short: "Start the exporter", + Long: "Start the prometheus exporter and listen for requests", + Example: `gridengine_prometheus --pidfile /var/run/gridengine_prometheus.pid --port 9018`, + RunE: Start, } -func Start( cmd *cobra.Command, args []string){ +func Start(cmd *cobra.Command, args []string) error { entropy = rand.NewSource(time.Now().UnixNano()) random = rand.New(entropy) if viper.GetBool("test") { //set the underlying gogridengine variable - err := os.Setenv("GOGRIDENGINE_TEST","true") + err := os.Setenv("GOGRIDENGINE_TEST", "true") if err != nil { log.Fatalf("Attempting to set Gogridengine test variables failed: %s", err) @@ -52,34 +52,36 @@ func Start( cmd *cobra.Command, args []string){ if len(viper.GetString("config")) > 0 { err := readProvidedConfig(viper.GetString("config")) if err != nil { - log.Fatalf("Attempting to open config file %s failed with error %s", viper.GetString("config"),err) + log.Fatalf("Attempting to open config file %s failed with error %s", viper.GetString("config"), err) } } - if viper.GetBool("debug"){ - config := Config{} - viper.Unmarshal(&config) - log.Info(config) + var config Config + + if err := viper.Unmarshal(&config); err != nil { + return fmt.Errorf("failed to retrieve viper details: %w", err) + } + + if config.Debug { viper.Debug() } //Die if we don't have all the SGE configurations required. - err := validateSGE() + err := validateSGE(config) if err != nil { - log.Fatal(err) + return fmt.Errorf("failed to validate SGE configuration: %w", err) } //Set the SGE Envs for the application - err = setSGEEnvironmentVariables() + err = setSGEEnvironmentVariables(config) if err != nil { - log.Fatalf("Unable to set SGE environment variables. Details: %s",err) + log.Fatalf("Unable to set SGE environment variables. Details: %s", err) } - - if len(viper.GetString("pidfile")) > 0 { - err := writePidFile(viper.GetString("pidfile")) + if len(config.Pidfile) > 0 { + err = writePidFile(viper.GetString("pidfile")) if err != nil { - log.Error("Unable to setup PID. Continuing without a PID File") + log.Error("Unable to setup PID. Continuing without a PID File. Failure caused by: %w", err.Error()) } } @@ -90,54 +92,28 @@ func Start( cmd *cobra.Command, args []string){ log.Infof("Getting ready to start exporter on port %d", viper.GetInt("port")) - log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d",viper.GetInt("port")), nil)) + log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", viper.GetInt("port")), nil)) + + return nil } -func init(){ +func init() { pidFileIdentifier := "pidfile" - RootCmd.PersistentFlags().String(pidFileIdentifier,"/var/run/" + ServiceName,"Location in which to store a pidfile. Most useful for SystemV daemons") - viper.BindPFlag(pidFileIdentifier, RootCmd.PersistentFlags().Lookup(pidFileIdentifier)) - - listenPortIdentifier := "port" - RootCmd.PersistentFlags().Int(listenPortIdentifier,9081,"The port on which the collector should listen") - viper.BindPFlag(listenPortIdentifier,RootCmd.PersistentFlags().Lookup(listenPortIdentifier)) - - testModeIdentifier := "test" - RootCmd.PersistentFlags().Bool(testModeIdentifier,false,"Indicates whether the underlying gogridengine should be run in test mode") - viper.BindPFlag(testModeIdentifier,RootCmd.PersistentFlags().Lookup(testModeIdentifier)) - - configFileIdentifier := "config" - RootCmd.PersistentFlags().String(configFileIdentifier,"", "Specifies a viper config to load. Should be in yaml format") - viper.BindPFlag(configFileIdentifier,RootCmd.PersistentFlags().Lookup(configFileIdentifier)) - - debugIdentifier := "debug" - RootCmd.PersistentFlags().Bool(debugIdentifier,false,"Whether or not debug is on") - viper.BindPFlag(debugIdentifier, RootCmd.PersistentFlags().Lookup(debugIdentifier)) + RootCmd.PersistentFlags().String(pidFileIdentifier, "/var/run/"+ServiceName, "Location in which to store a pidfile. Most useful for SystemV daemons") + RootCmd.PersistentFlags().Int("port", 9081, "The port on which the collector should listen") + RootCmd.PersistentFlags().Bool("test", false, "Indicates whether the underlying gogridengine should be run in test mode") + RootCmd.PersistentFlags().String("config", "", "Specifies a viper config to load. Should be in yaml format") + RootCmd.PersistentFlags().Bool("debug", false, "Whether or not debug is on") //SGE Configurations - sgeArchIdentifier := "sge_arch" - RootCmd.PersistentFlags().String(sgeArchIdentifier,"lx-amd64","Identifies the architecture of the Sun Grid Engine") - viper.BindPFlag(viperSGEKey + "arch",RootCmd.PersistentFlags().Lookup(sgeArchIdentifier)) - - sgeCellIdentifier := "sge_cell" - RootCmd.PersistentFlags().String(sgeCellIdentifier,"default","The SGE Cell to use") - viper.BindPFlag(viperSGEKey + "cell", RootCmd.PersistentFlags().Lookup(sgeCellIdentifier)) - - sgeExecDPortIdentifier := "sge_execd_port" - RootCmd.PersistentFlags().Int(sgeExecDPortIdentifier,6445,"Port for the execution daemon in the grid engine") - viper.BindPFlag(viperSGEKey + "execd_port", RootCmd.PersistentFlags().Lookup(sgeExecDPortIdentifier)) - - sgeQmasterPortIdentifier := "sge_qmaster_port" - RootCmd.PersistentFlags().Int(sgeQmasterPortIdentifier,6445,"Port for the master scheduling daemon in the grid engine") - viper.BindPFlag(viperSGEKey + "qmaster_port", RootCmd.PersistentFlags().Lookup(sgeQmasterPortIdentifier)) - - sgeRootIdentifier := "sge_root" - RootCmd.PersistentFlags().String(sgeRootIdentifier,"/opt/sge", "The root location for SGE bianries") - viper.BindPFlag(viperSGEKey + "root", RootCmd.PersistentFlags().Lookup(sgeRootIdentifier)) - - sgeClusterNameIdentifier := "sge_cluster_name" - RootCmd.PersistentFlags().String(sgeClusterNameIdentifier,"p6444","Name of the SGE Cluster to bind to") - viper.BindPFlag(viperSGEKey + "cluster_name",RootCmd.PersistentFlags().Lookup(sgeClusterNameIdentifier)) + RootCmd.PersistentFlags().String("sge_arch", "lx-amd64", "Identifies the architecture of the Sun Grid Engine") + RootCmd.PersistentFlags().String("sge_cell", "default", "The SGE Cell to use") + RootCmd.PersistentFlags().Int("sge_execd_port", 6445, "Port for the execution daemon in the grid engine") + RootCmd.PersistentFlags().Int("sge_qmaster_port", 6445, "Port for the master scheduling daemon in the grid engine") + RootCmd.PersistentFlags().String("sge_root", "/opt/sge", "The root location for SGE bianries") + RootCmd.PersistentFlags().String("sge_cluster_name", "p6444", "Name of the SGE Cluster to bind to") + + _ = viper.BindPFlags(RootCmd.PersistentFlags()) } func writePidFile(pidFile string) error { @@ -161,7 +137,6 @@ func writePidFile(pidFile string) error { return ioutil.WriteFile(location, []byte(fmt.Sprintf("%d", os.Getpid())), 0664) } -//TODO Test func readProvidedConfig(path string) error { viper.SetConfigType("yaml") @@ -175,56 +150,56 @@ func readProvidedConfig(path string) error { return viper.ReadConfig(file) } -func validateSGE() error { +func validateSGE(config Config) error { - if len(viper.GetString("sge.arch")) == 0{ + if len(config.SGE.Arch) == 0 { return errors.New("the SGE architecture has not been provided") } - if len(viper.GetString("sge.cell")) == 0 { + if len(config.SGE.Cell) == 0 { return errors.New("no valid SGE cell has been configured") } - if viper.GetInt("sge.execd_port") == 0 { + if config.SGE.ExecdPort == 0 { return errors.New("no ExecD port has been specified for SGE binding") } - if viper.GetInt("sge.qmaster_port") == 0 { + if config.SGE.QmasterPort == 0 { return errors.New("no Qmaster port has been specified for SGE Binding") } - if len(viper.GetString("sge.cluster_name")) == 0 { + if len(config.SGE.ClusterName) == 0 { return errors.New("no SGE cluster name has been provided") } return nil } -func setSGEEnvironmentVariables() error { - err := os.Setenv("SGE_ARCH",viper.GetString("sge.arch")) +func setSGEEnvironmentVariables(config Config) error { + err := os.Setenv("SGE_ARCH", config.SGE.Arch) if err != nil { return err } - err = os.Setenv("SGE_CELL", viper.GetString("sge.cell")) + err = os.Setenv("SGE_CELL", config.SGE.Cell) if err != nil { return err } - err = os.Setenv("SGE_EXECD_PORT",string(rune(viper.GetInt("sge.execd_port")))) + err = os.Setenv("SGE_EXECD_PORT", strconv.Itoa(config.SGE.ExecdPort)) if err != nil { return err } - err = os.Setenv("SGE_QMASTER_PORT",string(rune(viper.GetInt("sge.qmaster_port")))) + err = os.Setenv("SGE_QMASTER_PORT", strconv.Itoa(config.SGE.QmasterPort)) if err != nil { return err } - err = os.Setenv("SGE_ROOT", viper.GetString("sge.root")) + err = os.Setenv("SGE_ROOT", config.SGE.Root) if err != nil { return err @@ -232,15 +207,15 @@ func setSGEEnvironmentVariables() error { //Update Path to include SGE_ROOT BIN and any dirs matching arch path path := os.Getenv("PATH") - binPath := filepath.Join(viper.GetString("sge.root"),"bin") - archPath := filepath.Join(binPath,viper.GetString("sge.arch")) - err = os.Setenv("PATH", path + ":" + binPath + ":" + archPath) + binPath := filepath.Join(config.SGE.Root, "bin") + archPath := filepath.Join(binPath, config.SGE.Arch) + err = os.Setenv("PATH", path+":"+binPath+":"+archPath) if err != nil { return err } - err = os.Setenv("SGE_CLUSTER_NAME", viper.GetString("sge.cluster_name")) + err = os.Setenv("SGE_CLUSTER_NAME", config.SGE.ClusterName) if err != nil { return err @@ -249,20 +224,19 @@ func setSGEEnvironmentVariables() error { return nil } - type Config struct { - Test bool `yaml:"test" json:"test"` - Port int `yaml:"port" josn:"port"` + Test bool `yaml:"test" json:"test"` + Port int `yaml:"port" josn:"port"` Pidfile string `yaml:"pidfile" json:"pidfile"` - SGE SGE `mapstructure:"sge"` - + SGE SGE `mapstructure:"sge"` + Debug bool `mapstructure:"debug" yaml:"debug"` } type SGE struct { - Arch string `yaml:"arch" json:"arch"` - Cell string `yaml:"cell" json:"cell"` - ExecdPort int `yaml:"execd_port" json:"execd_port" mapstructure:"execd_port"` - QmasterPort int `yaml:"qmaster_port" json:"qmaster_port" mapstructure:"qmaster_port"` - Root string `yaml:"root" json:"root"` + Arch string `yaml:"arch" json:"arch"` + Cell string `yaml:"cell" json:"cell"` + ExecdPort int `yaml:"execd_port" json:"execd_port" mapstructure:"execd_port"` + QmasterPort int `yaml:"qmaster_port" json:"qmaster_port" mapstructure:"qmaster_port"` + Root string `yaml:"root" json:"root"` ClusterName string `yaml:"cluster_name" json:"cluster_name" mapstructure:"cluster_name"` -} \ No newline at end of file +}