From 6150b1507b4a5e8235fdd4c21bb8f1d6f5071c2c Mon Sep 17 00:00:00 2001 From: Shaharia Azam Date: Fri, 7 Apr 2023 17:21:18 +0200 Subject: [PATCH 1/4] Added logging configuration --- go.mod | 1 + go.sum | 4 + pkg/config/config.go | 29 ++- pkg/config/config_test.go | 274 ++++++++++++++++++++++++++ pkg/config/testdata/valid_config.yaml | 5 +- pkg/logging/logging.go | 41 ++++ pkg/util/util.go | 47 +++++ 7 files changed, 399 insertions(+), 2 deletions(-) create mode 100644 pkg/logging/logging.go diff --git a/go.mod b/go.mod index ba355012..0574c5c3 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/google/uuid v1.3.0 github.com/kyokomi/emoji v2.2.4+incompatible github.com/lib/pq v1.10.7 + github.com/sirupsen/logrus v1.9.0 github.com/spf13/cobra v1.6.1 github.com/stretchr/testify v1.8.2 golang.org/x/oauth2 v0.6.0 diff --git a/go.sum b/go.sum index 49ed167a..930896f8 100644 --- a/go.sum +++ b/go.sum @@ -80,6 +80,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -88,6 +90,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= @@ -114,6 +117,7 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= diff --git a/pkg/config/config.go b/pkg/config/config.go index 47366455..bbfdb2c0 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1,10 +1,12 @@ -// Package config read and validate config file +// Package logginConfig read and validate logginConfig file package config import ( "fmt" "io/ioutil" + "github.com/shahariaazam/teredix/pkg/util" + "github.com/shahariaazam/teredix/pkg" "gopkg.in/yaml.v3" @@ -67,6 +69,11 @@ type Relation struct { RelationCriteria []RelationCriteria `yaml:"criteria"` } +type Logging struct { + Format string `yaml:"format"` + Level string `yaml:"level"` +} + // AppConfig provides configuration for the tools type AppConfig struct { Organization Organization `yaml:"organization"` @@ -74,6 +81,7 @@ type AppConfig struct { Storage Storage `yaml:"storage"` Sources map[string]Source `yaml:"source"` Relation Relation `yaml:"relations"` + Logging Logging `yaml:"logging"` } // Load loads configuration file @@ -133,6 +141,11 @@ func Validate(c *AppConfig) error { return err } + err = c.validateLoggingConfiguration(c.Logging) + if err != nil { + return err + } + return nil } @@ -326,3 +339,17 @@ func (c *AppConfig) validateRelationCriteria(criteria RelationCriteria) error { } return nil } + +func (c *AppConfig) validateLoggingConfiguration(loggingConfig Logging) error { + validFormat := []string{"text", "json"} + if !util.IsExist(loggingConfig.Format, validFormat) { + return fmt.Errorf("'%s' log format is not supported", loggingConfig.Format) + } + + validLevel := []string{"info", "debug", "warning", "error"} + if !util.IsExist(loggingConfig.Level, validLevel) { + return fmt.Errorf("'%s' log level is not supported", loggingConfig.Level) + } + + return nil +} diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 2bf89f02..a4cd40d9 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -88,6 +88,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -123,6 +127,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Sources: map[string]Source{ "source1": { Type: pkg.SourceTypeFileSystem, @@ -166,6 +174,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Sources: map[string]Source{ "source1": { Type: pkg.SourceTypeFileSystem, @@ -211,6 +223,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -249,6 +265,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Sources: map[string]Source{ "source1": { Type: pkg.SourceTypeFileSystem, @@ -299,6 +319,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -343,6 +367,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -387,6 +415,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -430,6 +462,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -486,6 +522,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -530,6 +570,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -572,6 +616,10 @@ func TestValidate(t *testing.T) { Configuration: map[string]string{}, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -616,6 +664,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -659,6 +711,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -699,6 +755,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -775,6 +835,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -815,6 +879,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -852,6 +920,10 @@ func TestValidate(t *testing.T) { }, }, Sources: map[string]Source{}, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -896,6 +968,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -956,6 +1032,10 @@ func TestValidate(t *testing.T) { }, }, }}, + Logging: Logging{ + Format: "json", + Level: "info", + }, }, wantErr: true, }, @@ -1001,6 +1081,10 @@ func TestValidate(t *testing.T) { }, }, }}, + Logging: Logging{ + Format: "json", + Level: "info", + }, }, wantErr: true, }, @@ -1030,6 +1114,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, }, wantErr: true, }, @@ -1051,6 +1139,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Sources: map[string]Source{ "source1": { Type: pkg.SourceTypeFileSystem, @@ -1080,6 +1172,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Sources: map[string]Source{ "source1": { Type: pkg.SourceTypeFileSystem, @@ -1118,6 +1214,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Source: RelationCriteriaNode{ @@ -1161,6 +1261,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1205,6 +1309,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1248,6 +1356,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1291,6 +1403,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1334,6 +1450,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1377,6 +1497,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1420,6 +1544,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1464,6 +1592,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1509,6 +1641,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1554,6 +1690,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1600,6 +1740,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1647,6 +1791,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1694,6 +1842,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1741,6 +1893,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1802,6 +1958,10 @@ func TestValidate(t *testing.T) { }, }}, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, }, wantErr: true, }, @@ -1834,6 +1994,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1878,6 +2042,10 @@ func TestValidate(t *testing.T) { }, }, }, + Logging: Logging{ + Format: "json", + Level: "info", + }, Relation: Relation{RelationCriteria: []RelationCriteria{ { Name: "name", @@ -1907,3 +2075,109 @@ func TestValidate(t *testing.T) { }) } } + +func TestValidateLogging(t *testing.T) { + testCases := []struct { + name string + loggingConfig Logging + wantErr bool + }{ + { + name: "valid logging config", + loggingConfig: Logging{ + Format: "json", + Level: "info", + }, + wantErr: false, + }, + { + name: "invalid logging format", + loggingConfig: Logging{ + Format: "invalid", + Level: "info", + }, + wantErr: true, + }, + { + name: "invalid logging level", + loggingConfig: Logging{ + Format: "json", + Level: "invalid", + }, + wantErr: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + conf := AppConfig{ + Organization: Organization{Name: "My Org", Logo: "http://example.com"}, + Discovery: Discovery{Name: "My Discovery", Description: "Discovery description"}, + Storage: Storage{ + BatchSize: 2, + DefaultEngine: "postgresql", + Engines: map[string]interface{}{ + "postgresql": map[string]interface{}{ + "host": "localhost", + "port": 5432, + "user": "myuser", + "password": "mypassword", + "db": "mydb", + }, + }, + }, + Sources: map[string]Source{ + "source1": { + Type: pkg.SourceTypeFileSystem, + Configuration: map[string]string{ + "root_directory": "/root/path", + }, + }, + "source2": { + Type: pkg.SourceTypeGitHubRepository, + Configuration: map[string]string{ + "token": "mytoken", + "user_or_org": "myuser", + "repository": "myrepo", + "branch": "mybranch", + "path": "mypath", + "file_patterns": "*.yaml", + }, + }, + "source3": { + Type: pkg.SourceTypeAWSS3, + Configuration: map[string]string{ + "access_key": "access_key", + "secret_key": "secret_key", + "session_token": "session_token", + "region": "x", + "account_id": "account_id", + }, + }, + }, + Relation: Relation{RelationCriteria: []RelationCriteria{ + { + Name: "name", + Source: RelationCriteriaNode{ + Kind: "kind", + MetaKey: "source_kind-key1", + MetaValue: "source-kind-value1", + }, + Target: RelationCriteriaNode{ + Kind: "related-kind", + MetaKey: "related-metadata-key", + MetaValue: "related-metadata-value", + }, + }, + }}, + } + + conf.Logging = tc.loggingConfig + + err := Validate(&conf) + if (err != nil) != tc.wantErr { + t.Errorf("Validate() error = %v, wantErr %v", err, tc.wantErr) + } + }) + } +} diff --git a/pkg/config/testdata/valid_config.yaml b/pkg/config/testdata/valid_config.yaml index 097eb476..4d80684c 100644 --- a/pkg/config/testdata/valid_config.yaml +++ b/pkg/config/testdata/valid_config.yaml @@ -56,4 +56,7 @@ relations: target: kind: "FilePath" meta_key: "Root-Directory" - meta_value: "/some/path" \ No newline at end of file + meta_value: "/some/path" +logging: + format: "json" + level: "info" \ No newline at end of file diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go new file mode 100644 index 00000000..6dbcd06d --- /dev/null +++ b/pkg/logging/logging.go @@ -0,0 +1,41 @@ +// Package logging to configure logging +package logging + +import ( + "github.com/shahariaazam/teredix/pkg/config" + "github.com/sirupsen/logrus" +) + +// Logging holds logging configuration +type Logging struct { + appConfig *config.AppConfig +} + +// NewLogger builds a new logging system +func NewLogger(appConfig *config.AppConfig) *logrus.Logger { + logger := logrus.New() + logger.SetReportCaller(true) + + loggingCfg := appConfig.Logging + switch loggingCfg.Format { + case "json": + logger.SetFormatter(&logrus.JSONFormatter{}) + case "text": + logger.SetFormatter(&logrus.TextFormatter{}) + default: + logger.SetFormatter(&logrus.TextFormatter{}) + } + + switch loggingCfg.Level { + case "debug": + logger.SetLevel(logrus.DebugLevel) + case "warning": + logger.SetLevel(logrus.WarnLevel) + case "error": + logger.SetLevel(logrus.ErrorLevel) + default: + logger.SetLevel(logrus.InfoLevel) + } + + return logger +} diff --git a/pkg/util/util.go b/pkg/util/util.go index 98d8b213..30da5bd2 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -4,6 +4,8 @@ package util import ( "context" "fmt" + "math" + "reflect" "time" "github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi" @@ -68,3 +70,48 @@ func GetAWSResourceTagByARN(ctx context.Context, resourceTaggingService Resource return tags, nil } + +const epsilon = 1e-6 + +func IsExist(what interface{}, in interface{}) bool { + s := reflect.ValueOf(in) + + if s.Kind() != reflect.Slice { + panic("IsExist: Second argument must be a slice") + } + + for i := 0; i < s.Len(); i++ { + if s.Index(i).Kind() != reflect.TypeOf(what).Kind() { + continue + } + + switch s.Index(i).Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if s.Index(i).Int() == reflect.ValueOf(what).Int() { + return true + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if s.Index(i).Uint() == reflect.ValueOf(what).Uint() { + return true + } + case reflect.Float32, reflect.Float64: + if math.Abs(s.Index(i).Float()-reflect.ValueOf(what).Float()) < epsilon { + return true + } + case reflect.String: + if s.Index(i).String() == reflect.ValueOf(what).String() { + return true + } + case reflect.Bool: + if s.Index(i).Bool() == reflect.ValueOf(what).Bool() { + return true + } + default: + if reflect.DeepEqual(what, s.Index(i).Interface()) { + return true + } + } + } + + return false +} From 1d4284b44762c3223d4c7a9b42f0cdd4dcb833f5 Mon Sep 17 00:00:00 2001 From: Shaharia Azam Date: Sat, 8 Apr 2023 03:03:01 +0200 Subject: [PATCH 2/4] Added tests for NewLogging() --- pkg/logging/logging_test.go | 71 +++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 pkg/logging/logging_test.go diff --git a/pkg/logging/logging_test.go b/pkg/logging/logging_test.go new file mode 100644 index 00000000..ac5752b1 --- /dev/null +++ b/pkg/logging/logging_test.go @@ -0,0 +1,71 @@ +package logging + +import ( + "testing" + + "github.com/shahariaazam/teredix/pkg/config" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" +) + +func TestNewLogger(t *testing.T) { + tests := []struct { + name string + format string + level string + expectedFmt logrus.Formatter + expectedLvl logrus.Level + }{ + { + name: "test json format and debug level", + format: "json", + level: "debug", + expectedFmt: &logrus.JSONFormatter{}, + expectedLvl: logrus.DebugLevel, + }, + { + name: "test json format and warning level", + format: "json", + level: "warning", + expectedFmt: &logrus.JSONFormatter{}, + expectedLvl: logrus.WarnLevel, + }, + { + name: "test text format and error level", + format: "text", + level: "error", + expectedFmt: &logrus.TextFormatter{}, + expectedLvl: logrus.ErrorLevel, + }, + { + name: "test text format and info level", + format: "text", + level: "info", + expectedFmt: &logrus.TextFormatter{}, + expectedLvl: logrus.InfoLevel, + }, + { + name: "test unknown format and level", + format: "unknown", + level: "unknown", + expectedFmt: &logrus.TextFormatter{}, + expectedLvl: logrus.InfoLevel, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + appConfig := &config.AppConfig{ + Logging: config.Logging{ + Format: tt.format, + Level: tt.level, + }, + } + + logger := NewLogger(appConfig) + + assert.Equal(t, tt.expectedFmt, logger.Formatter) + assert.Equal(t, tt.expectedLvl, logger.Level) + }) + } +} From 2a6851921d4bab703c3c015c694babfdc95867db Mon Sep 17 00:00:00 2001 From: Shaharia Azam Date: Sat, 8 Apr 2023 03:05:57 +0200 Subject: [PATCH 3/4] Added test for IsExists() util method --- pkg/util/util.go | 1 + pkg/util/util_test.go | 67 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/pkg/util/util.go b/pkg/util/util.go index 30da5bd2..e3b535be 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -73,6 +73,7 @@ func GetAWSResourceTagByARN(ctx context.Context, resourceTaggingService Resource const epsilon = 1e-6 +// IsExist check whether the given value exists in a slice func IsExist(what interface{}, in interface{}) bool { s := reflect.ValueOf(in) diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go index a3920713..1ae7c6d8 100644 --- a/pkg/util/util_test.go +++ b/pkg/util/util_test.go @@ -145,3 +145,70 @@ func TestGetAWSResourceTagByARN(t *testing.T) { t.Errorf("Unexpected tags: got %v, expected %v", tags, expectedTags) } } + +func TestIsExist(t *testing.T) { + testCases := []struct { + name string + what interface{} + in interface{} + want bool + panic bool + }{ + { + name: "int in int slice", + what: 1, + in: []int{1, 2, 3}, + want: true, + }, + { + name: "int not in int slice", + what: 4, + in: []int{1, 2, 3}, + want: false, + }, + { + name: "float in float slice", + what: 1.234, + in: []float64{1.234, 2.345, 3.456}, + want: true, + }, + { + name: "string in string slice", + what: "hello", + in: []string{"hello", "world", "foo", "bar"}, + want: true, + }, + { + name: "bool in bool slice", + what: true, + in: []bool{true, false}, + want: true, + }, + { + name: "panic with non-slice", + what: "foo", + in: "bar", + panic: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + defer func() { + if r := recover(); r != nil { + if !tc.panic { + t.Errorf("unexpected panic: %v", r) + } + } else if tc.panic { + t.Errorf("expected panic but did not occur") + } + }() + + got := IsExist(tc.what, tc.in) + + if got != tc.want { + t.Errorf("IsExist(%v, %v) = %v; want %v", tc.what, tc.in, got, tc.want) + } + }) + } +} From 191dee6a1f0fc9fb8776a34860d7d2c7f04843eb Mon Sep 17 00:00:00 2001 From: Shaharia Azam Date: Sat, 8 Apr 2023 03:08:02 +0200 Subject: [PATCH 4/4] Reduced un-necessary code in util function --- pkg/util/util.go | 19 ------------------- pkg/util/util_test.go | 24 ------------------------ 2 files changed, 43 deletions(-) diff --git a/pkg/util/util.go b/pkg/util/util.go index e3b535be..ce002452 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -4,7 +4,6 @@ package util import ( "context" "fmt" - "math" "reflect" "time" @@ -71,8 +70,6 @@ func GetAWSResourceTagByARN(ctx context.Context, resourceTaggingService Resource return tags, nil } -const epsilon = 1e-6 - // IsExist check whether the given value exists in a slice func IsExist(what interface{}, in interface{}) bool { s := reflect.ValueOf(in) @@ -87,26 +84,10 @@ func IsExist(what interface{}, in interface{}) bool { } switch s.Index(i).Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - if s.Index(i).Int() == reflect.ValueOf(what).Int() { - return true - } - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - if s.Index(i).Uint() == reflect.ValueOf(what).Uint() { - return true - } - case reflect.Float32, reflect.Float64: - if math.Abs(s.Index(i).Float()-reflect.ValueOf(what).Float()) < epsilon { - return true - } case reflect.String: if s.Index(i).String() == reflect.ValueOf(what).String() { return true } - case reflect.Bool: - if s.Index(i).Bool() == reflect.ValueOf(what).Bool() { - return true - } default: if reflect.DeepEqual(what, s.Index(i).Interface()) { return true diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go index 1ae7c6d8..bfb20bf1 100644 --- a/pkg/util/util_test.go +++ b/pkg/util/util_test.go @@ -154,36 +154,12 @@ func TestIsExist(t *testing.T) { want bool panic bool }{ - { - name: "int in int slice", - what: 1, - in: []int{1, 2, 3}, - want: true, - }, - { - name: "int not in int slice", - what: 4, - in: []int{1, 2, 3}, - want: false, - }, - { - name: "float in float slice", - what: 1.234, - in: []float64{1.234, 2.345, 3.456}, - want: true, - }, { name: "string in string slice", what: "hello", in: []string{"hello", "world", "foo", "bar"}, want: true, }, - { - name: "bool in bool slice", - what: true, - in: []bool{true, false}, - want: true, - }, { name: "panic with non-slice", what: "foo",