Skip to content

Commit

Permalink
Merge pull request #7 from akoova/upstream/v0.1.10-alignment
Browse files Browse the repository at this point in the history
v0.1.10 alignment
  • Loading branch information
furan917 authored Nov 23, 2023
2 parents 424df14 + e927272 commit 7830796
Show file tree
Hide file tree
Showing 9 changed files with 293 additions and 206 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## [0.1.10](https://github.com/furan917/MageComm/compare/v0.1.9...v0.1.10) (2023-11-23)


### Bug Fixes

* log formatting + add disallow override file option to config ([544767e](https://github.com/furan917/MageComm/commit/544767eb153363ee7707b6ceb30ca8cf432cfa99))
* magerun command now handles config override correctly ([66eb5ea](https://github.com/furan917/MageComm/commit/66eb5eaad38b6dfaa885061779aa3218ccf162d5))
* small fix for graceful interupts + some whitespacing fixes ([229a649](https://github.com/furan917/MageComm/commit/229a649443ffa8da1dd849ff26231e7ede389885))

## [0.1.9](https://github.com/furan917/MageComm/compare/v0.1.8...v0.1.9) (2023-10-11)


Expand Down
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ As this is an akoova specific fork, we will be using akoova specific tag nomencl

## Beta
Currently this tool is in beta, and is not recommended for production use.
Tested commands: RMQ based magerun command publishing, message listening, cat all supported archive types


## Installation

Expand All @@ -37,6 +35,7 @@ Download the latest release from the [releases page](https://github.com/furan917

example config.yml:
```
disallow_configfile_overwrite: true
magecomm_log_path: /var/log/magecomm.log
magecomm_log_level: warn
magecomm_max_operational_cpu_limit: 80
Expand Down Expand Up @@ -79,6 +78,7 @@ magecomm_required_magerun_command_args:
example config.json:
```
{
"disallow_configfile_overwrite": true,
"magecomm_log_path": "/var/log/magecomm.log",
"magecomm_log_level": "warn",
"magecomm_max_operational_cpu_limit": 80,
Expand Down Expand Up @@ -132,11 +132,14 @@ example config.json:
### Global Flags

- `--debug`: Enable debug mode
- `--config`: Path to overwrite config file, argument can be disabled by default config file

e.g
`magecomm --debug listen`
`magecomm --debug magerun cache:clean`
`magecomm --debug cat path/to/archive.tar.gz /path/to/file.txt`
`magecomm --config=/custom/config/path.json magerun indexer:status`
`magecomm --config=/custom/config/path.json --debug magerun indexer:reindex`

### Commands

Expand All @@ -158,11 +161,15 @@ e.g

## Configuration

The tool can be configured using a yaml or json config file at `/etc/magecomm/`(unix) / `%APPDATA%\magecomm\`(windows) or by environment variables.
lowercase for file based config, uppercase for ENV.
The tool can be configured using a yaml or json config file at `/etc/magecomm/` (unix) | `%APPDATA%\magecomm\` (windows), or using `--config=/custom/config/path.json` before the command e.g. `magecomm --config=... magerun`, or by ENV variables.
Magecomm has a fallback strategy of, config file -> ENV -> default values

_You can disable by the config override argument by placing `disallow_configfile_overwrite: true` in the default config file_

The tool supports slack command run notifications via Webhook or App integration
The tool can also supports slack command run notifications via Webhook or App integration

## Config Options
_All caps for envs, lowercase for config file_
- `MAGECOMM_LOG_PATH`: Path to log file, default: SYSLOG
- `MAGECOMM_LOG_LEVEL`: Log level, default: WARN, options (TRACE, DEBUG, INFO, WARN, ERROR, FATAL, PANIC)
- `MAGECOMM_MAX_OPERATIONAL_CPU_LIMIT`: Maximum CPU limit of system before we defer processing messages, default: 80
Expand Down
13 changes: 9 additions & 4 deletions cmd/listen.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,17 @@ var ListenCmd = &cobra.Command{
return fmt.Errorf("error creating listener: %s", err)
}

// Create a channel to handle program termination or interruption signals so we can kill any connections if needed
//Create a channel to handle program termination or interruption signals so we can kill any connections if needed
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
go listener.ListenToService(queueNames)
<-sigChan
listener.Close()
go func() {
<-sigChan
logger.Infof("Received interruption signal. Shutting down gracefully...")
listener.Close()
os.Exit(0)
}()

listener.ListenToService(queueNames)

return nil
},
Expand Down
44 changes: 33 additions & 11 deletions cmd/magerun.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@ var MagerunCmd = &cobra.Command{
//empty pre run to stop execution of parent RootCmd pre run
},
RunE: func(cmd *cobra.Command, args []string) error {

// handle global arguments (e.g. --config, --debug) as root command cannot due to DisableFlagParsing
var globalArguments = handleGlobalArguments(args)
magerunArgs := args[len(globalArguments):]

if len(magerunArgs) < 1 {
return fmt.Errorf("no command provided")
}
Expand Down Expand Up @@ -99,26 +97,50 @@ func initializeModuleWhichRequireConfig() {

func handleGlobalArguments(args []string) []string {
// Replicates RootCmd.PersistentPreRunE as it is not usable when DisableFlagParsing is set to true
// global Arg handling must be done manually
var globalArguments []string
var overrideFilePath string
for _, arg := range args {
var enableDebugLogging bool

//Note arguments between start and magerun command.
for i, arg := range args {
if strings.HasPrefix(arg, "--") {
globalArguments = append(globalArguments, arg)

if strings.HasPrefix(arg, "--config") {
// Catch both --config /file/path and --config=/file/path
overrideFilePath = strings.TrimPrefix(arg, "--config=")
overrideFilePath = strings.TrimPrefix(arg, "--config ")
//if arg is --debug then flag debug to be enabled after configuration step
if arg == "--debug" {
enableDebugLogging = true
}
if strings.HasPrefix(arg, "--debug") {
logger.EnableDebugMode()

//if arg is --config then configure
if strings.HasPrefix(arg, "--config") {
var configPath string
if strings.Contains(arg, "=") {
configPath = strings.Split(arg, "=")[1]
} else {
//ensure next argument is config path
if len(args) > i+1 && !strings.HasPrefix(args[i+1], "--") {
configPath = args[i+1]
//Ensure we remove the config path from args to avoid breaking early
args = append(args[:i+1], args[i+2:]...)
}
}
if configPath == "" {
logger.Warnf("No config file path provided with argument, using default config file path")
}

overrideFilePath = strings.Trim(configPath, `"'`)
}
}
if !strings.HasPrefix(arg, "--") {
} else {
//We have reached the magerun command, so exit loop
break
}
}

if enableDebugLogging {
logger.EnableDebugMode()
}

config_manager.Configure(overrideFilePath)
initializeModuleWhichRequireConfig()

Expand Down
77 changes: 51 additions & 26 deletions config_manager/base_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,49 +105,74 @@ func getDefault(key string) string {
}

func Configure(overrideFile string) {
if overrideFile != "" {
viper.SetConfigFile(overrideFile)
} else {
// Set base folder and file name of config file
viper.SetConfigName("config")
if runtime.GOOS == "windows" {
viper.AddConfigPath(os.Getenv("APPDATA") + "\\magecomm\\")
} else {
viper.AddConfigPath("/etc/magecomm/")
}
// Search for json config file first, then fallback to yaml
viper.SetConfigType("json")
if err := viper.ReadInConfig(); err != nil {
viper.SetConfigType("yaml")
}
overrideFile = strings.TrimSpace(overrideFile)
overrideFile = strings.Trim(overrideFile, `'"`)
defaultConfigError := configureDefaultsConfig()
disallowOverwrite := viper.GetBool("disallow_configfile_overwrite")

if disallowOverwrite && overrideFile != "" {
logger.Warnf("Config file overwriting is disallowed, ignoring passed in config file")
}

err := viper.ReadInConfig()
if err != nil {
// If the configuration file does not exist, warn user that env vars will be used
var configFileNotFoundError viper.ConfigFileNotFoundError
if errors.As(err, &configFileNotFoundError) {
logger.Infof("No config file found, reading fully from env vars, this is less secure")
} else {
logger.Warnf("Failed to read the config file, reading from ENV vars, this is less secure: %v", err)
return
if !disallowOverwrite && overrideFile != "" {
viper.Reset()
viper.SetConfigFile(overrideFile)
err := viper.ReadInConfig()
if err != nil {
if defaultConfigError == nil {
logger.Warnf("Failed to read the config file, reapplying default config")
err := configureDefaultsConfig()
if err != nil {
// We checked for this above, so this should never happen
}
} else {
logger.Warnf("Failed to read the both the override and default config file, defaulting to env variable reading")
}
}
}

if logPath := GetValue(ConfigLogPath); logPath != "" {
logger.ConfigureLogPath(logPath)
logger.Infof("Logging to file: %s", logPath)
}

if logLevel := GetValue(ConfigLogLevel); logLevel != "" {
logger.SetLogLevel(logLevel)
logger.Infof("Logging level set to: %s", logLevel)
}

configName := viper.ConfigFileUsed()
logger.Infof("Using config file: %s", configName)
}

func configureDefaultsConfig() error {
viper.Reset()

viper.SetConfigName("config")
if runtime.GOOS == "windows" {
viper.AddConfigPath(os.Getenv("APPDATA") + "\\magecomm\\")
} else {
viper.AddConfigPath("/etc/magecomm/")
}
// Search for json config file first, then fallback to yaml
viper.SetConfigType("json")
if err := viper.ReadInConfig(); err != nil {
viper.SetConfigType("yaml")
}
err := viper.ReadInConfig()
if err != nil {
// If the configuration file does not exist, warn user that env vars will be used
var configFileNotFoundError viper.ConfigFileNotFoundError
if errors.As(err, &configFileNotFoundError) {
logger.Infof("No default config file found, reading fully from env vars, this is less secure")
return err
} else {
logger.Warnf("Failed to read the default config file, reading from ENV vars, this is less secure: %v", err)
return err
}
}

return nil
}

func GetBoolValue(key string) bool {
value := GetValue(key)
for _, v := range trueValues {
Expand Down
51 changes: 33 additions & 18 deletions logger/logger.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package logger

// This package is used to log messages easily It is a wrapper around the logrus package.
// This package is used to Log messages easily It is a wrapper around the logrus package.

import (
"github.com/sirupsen/logrus"
Expand All @@ -19,14 +19,17 @@ const (
PanicLevel = logrus.PanicLevel
)

var Log *logrus.Logger
var (
Log *logrus.Logger
debugFlagSet bool
)

func init() {
logrus.SetFormatter(&logrus.TextFormatter{
Log = logrus.StandardLogger()
Log.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
})
logrus.SetLevel(logrus.WarnLevel)
Log = logrus.StandardLogger()
Log.SetLevel(logrus.WarnLevel)
}

func ConfigureLogPath(logFile string) {
Expand All @@ -37,18 +40,23 @@ func ConfigureLogPath(logFile string) {

if _, err := os.Stat(logFile); os.IsNotExist(err) {
if err := createLogFile(logFile); err != nil {
Log.Errorf("Unable to create log file, please contact your system administrator")
Log.Errorf("Unable to create Log file, please contact your system administrator")
}
}

file, err := os.OpenFile(logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0755)
if err != nil {
logrus.SetOutput(os.Stdout)
Log.Errorf("Unable to open log file, printing to stdout, please contact your system administrator")
Log.SetOutput(os.Stdout)
Log.Errorf("Unable to open Log file, printing to stdout, please contact your system administrator")
return
}

logrus.SetOutput(file)
//Log.SetFormatter(&logrus.JSONFormatter{})
Log.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
})
Log.SetOutput(file)
Log.Infof("Logging to file: %s", file.Name())
}

func createLogFile(logFile string) error {
Expand All @@ -58,24 +66,31 @@ func createLogFile(logFile string) error {
}
defer func(file *os.File) {
if err := file.Close(); err != nil {
Log.Fatal("Unable to close log file, please contact your system administrator")
Log.Fatal("Unable to close Log file, please contact your system administrator")
}
}(file)
return nil
}

func EnableDebugMode() {
SetLogLevel(logrus.DebugLevel.String())
debugFlagSet = true
}

func SetLogLevel(level string) {
if debugFlagSet {
Log.Info("Debug mode enabled by flag, ignoring log level configuration")
return
}

logrusLevel, err := logrus.ParseLevel(strings.ToLower(level))
if err != nil {
logrus.Warnf("Invalid log level: %s, defaulting to %s", level, logrus.WarnLevel.String())
Log.Warnf("Invalid Log level: %s, defaulting to %s", level, logrus.WarnLevel.String())
logrusLevel = logrus.WarnLevel
}

logrus.SetLevel(logrusLevel)
Log.SetLevel(logrusLevel)
Log.Infof("Log level set to %s", logrusLevel)
}

func Trace(args ...interface{}) {
Expand Down Expand Up @@ -111,25 +126,25 @@ func Tracef(format string, args ...interface{}) {
}

func Debugf(format string, args ...interface{}) {
logrus.Debugf(format, args...)
Log.Debugf(format, args...)
}

func Infof(format string, args ...interface{}) {
logrus.Infof(format, args...)
Log.Infof(format, args...)
}

func Warnf(format string, args ...interface{}) {
logrus.Warnf(format, args...)
Log.Warnf(format, args...)
}

func Errorf(format string, args ...interface{}) {
logrus.Errorf(format, args...)
Log.Errorf(format, args...)
}

func Fatalf(format string, args ...interface{}) {
logrus.Fatalf(format, args...)
Log.Fatalf(format, args...)
}

func Panicf(format string, args ...interface{}) {
logrus.Panicf(format, args...)
Log.Panicf(format, args...)
}
Loading

0 comments on commit 7830796

Please sign in to comment.