diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 4006a10..9627f4f 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -11,16 +11,13 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 2 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.21' - - name: Install dependencies - run: go mod download - - name: Install GolangCI Lint - run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.55.2 - + go-version-file: 'go.mod' - name: golangci-lint - run: golangci-lint run --timeout=30m --max-same-issues=0 --out-format=github-actions + uses: golangci/golangci-lint-action@v4 + with: + version: v1.55.2 test: name: Test diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..54504ea --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,16 @@ +run: + timeout: 30m + +linters: + enable: + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - unused + - zerologlint + +linters-settings: + issues: + max-same-issues: 0 diff --git a/go.mod b/go.mod index 4980751..a455c16 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,12 @@ go 1.21 toolchain go1.21.0 require ( - github.com/equinor/radix-common v1.7.1 + github.com/equinor/radix-common v1.9.2 github.com/equinor/radix-operator v1.50.2 github.com/go-git/go-git/v5 v5.11.0 github.com/golang/mock v1.6.0 github.com/pkg/errors v0.9.1 - github.com/sirupsen/logrus v1.9.3 + github.com/rs/zerolog v1.32.0 github.com/spf13/viper v1.18.2 github.com/stretchr/testify v1.8.4 github.com/tektoncd/pipeline v0.55.0 @@ -69,6 +69,8 @@ require ( github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -88,6 +90,7 @@ require ( github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/skeema/knownhosts v1.2.1 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect diff --git a/go.sum b/go.sum index c937356..a8f0d78 100644 --- a/go.sum +++ b/go.sum @@ -81,6 +81,7 @@ github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUK github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -97,8 +98,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/equinor/radix-common v1.7.1 h1:kl7Tuo2VEo2WHGm/vkvktrZ9t9S3Nht7Mob3CSIzcJI= -github.com/equinor/radix-common v1.7.1/go.mod h1:M6mhgHtFQ3rnjJnyOuECXiZOh7XQ5xVeHMyCAU+YPzQ= +github.com/equinor/radix-common v1.9.2 h1:pOYN/mSAoPe6KO/Nvudfd5DUETbLv4nLTLzFPr62ADw= +github.com/equinor/radix-common v1.9.2/go.mod h1:ekn86U68NT4ccSdt3GT+ukpiclzfuhr96a7zBJKv/jw= github.com/equinor/radix-operator v1.50.2 h1:xa5kPUN77QT6QJq9+DJzF/ic2c7AJcl4KKztky38sdc= github.com/equinor/radix-operator v1.50.2/go.mod h1:rl8Tbor0wvKfol67nd/p72MRh0iDTClGeQ2HcMRG/LQ= github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= @@ -145,6 +146,7 @@ github.com/go-openapi/swag v0.22.7/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmrid github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -273,6 +275,11 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= @@ -341,6 +348,9 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -568,10 +578,12 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc 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.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/main.go b/main.go index ce5ac7f..8e722ee 100644 --- a/main.go +++ b/main.go @@ -8,35 +8,36 @@ import ( "github.com/equinor/radix-tekton/pkg/models" "github.com/equinor/radix-tekton/pkg/models/env" "github.com/equinor/radix-tekton/pkg/pipeline" - log "github.com/sirupsen/logrus" + "github.com/equinor/radix-tekton/pkg/utils/logger" + "github.com/rs/zerolog/log" ) func main() { environment := env.NewEnvironment() - setLogLevel(environment) + level, err := environment.GetLogLevel() + if err != nil { + log.Fatal().Err(err).Msg("Failed to initialize log level") + } + + logger.InitializeLogger(level, true) kubeClient, radixClient, tektonClient, err := kubernetes.GetClients() if err != nil { - log.Fatal(err.Error()) + log.Fatal().Err(err).Msg("Failed to initialize kubeClient") } ctx := pipeline.NewPipelineContext(kubeClient, radixClient, tektonClient, environment) err = runAction(ctx) if err != nil { - log.Fatal(err.Error()) + log.Fatal().Err(err).Msg("Failed to run ") } - log.Infof("Completed") + log.Info().Msg("Completed") } -func setLogLevel(environment env.Env) { - logLevel := environment.GetLogLevel() - log.SetLevel(logLevel) - log.Debugf("log-level '%v'", logLevel) -} func runAction(ctx models.Context) error { action := ctx.GetEnv().GetPipelinesAction() - log.Debugf("execute an action %s", action) + log.Debug().Msgf("execute an action %s", action) switch action { case pipelineDefaults.RadixPipelineActionPrepare: return ctx.ProcessRadixAppConfig() diff --git a/pkg/internal/wait/pipelinerun.go b/pkg/internal/wait/pipelinerun.go index 2a8b4c4..41d2083 100644 --- a/pkg/internal/wait/pipelinerun.go +++ b/pkg/internal/wait/pipelinerun.go @@ -7,7 +7,7 @@ import ( "time" "github.com/equinor/radix-tekton/pkg/models/env" - log "github.com/sirupsen/logrus" + "github.com/rs/zerolog/log" pipelinev1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" tektonclient "github.com/tektoncd/pipeline/pkg/client/clientset/versioned" tektonInformerFactory "github.com/tektoncd/pipeline/pkg/client/informers/externalversions" @@ -70,18 +70,18 @@ func waitForCompletionOf(pipelineRuns map[string]*pipelinev1.PipelineRun, tekton switch { case lastCondition.Reason == pipelinev1.PipelineRunReasonCompleted.String(): - log.Infof("pipelineRun completed: %s", lastCondition.Message) + log.Info().Msgf("pipelineRun completed: %s", lastCondition.Message) case lastCondition.Reason == pipelinev1.PipelineRunReasonFailed.String(): errChan <- fmt.Errorf("PipelineRun failed: %s", lastCondition.Message) return default: - log.Infof("pipelineRun status %s: %s", lastCondition.Reason, lastCondition.Message) + log.Info().Msgf("pipelineRun status %s: %s", lastCondition.Reason, lastCondition.Message) } if len(pipelineRuns) == 0 { errChan <- nil } } else { - log.Debugf("Ongoing - PipelineRun has not completed yet") + log.Debug().Msgf("Ongoing - PipelineRun has not completed yet") } }, DeleteFunc: func(old interface{}) { diff --git a/pkg/models/env/env.go b/pkg/models/env/env.go index d9d77d7..e9a871a 100644 --- a/pkg/models/env/env.go +++ b/pkg/models/env/env.go @@ -11,7 +11,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/utils/git" tektonDefaults "github.com/equinor/radix-tekton/pkg/defaults" "github.com/equinor/radix-tekton/pkg/models/env/internal" - log "github.com/sirupsen/logrus" + "github.com/rs/zerolog" "github.com/spf13/viper" ) @@ -106,15 +106,13 @@ func (e *env) GetDNSConfig() *dnsalias.DNSConfig { } // GetLogLevel Log level: ERROR, INFO (default), DEBUG -func (e *env) GetLogLevel() log.Level { - switch viper.GetString(defaults.LogLevel) { - case "DEBUG": - return log.DebugLevel - case "ERROR": - return log.ErrorLevel - default: - return log.InfoLevel +func (e *env) GetLogLevel() (zerolog.Level, error) { + level := viper.GetString(defaults.LogLevel) + if level == "" { + return zerolog.InfoLevel, nil } + + return zerolog.ParseLevel(level) } // GetGitRepositoryWorkspace Path to the cloned GitHub repository @@ -143,7 +141,7 @@ type Env interface { GetRadixImageTag() string GetBranch() string GetPipelinesAction() string - GetLogLevel() log.Level + GetLogLevel() (zerolog.Level, error) GetGitRepositoryWorkspace() string GetSourceDeploymentGitCommitHash() string GetSourceDeploymentGitBranch() string diff --git a/pkg/models/env/env_mock.go b/pkg/models/env/env_mock.go index 06d1d0d..3f63a2c 100644 --- a/pkg/models/env/env_mock.go +++ b/pkg/models/env/env_mock.go @@ -10,7 +10,7 @@ import ( dnsalias "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" gomock "github.com/golang/mock/gomock" - logrus "github.com/sirupsen/logrus" + zerolog "github.com/rs/zerolog" ) // MockEnv is a mock of Env interface. @@ -121,11 +121,12 @@ func (mr *MockEnvMockRecorder) GetGitRepositoryWorkspace() *gomock.Call { } // GetLogLevel mocks base method. -func (m *MockEnv) GetLogLevel() logrus.Level { +func (m *MockEnv) GetLogLevel() (zerolog.Level, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetLogLevel") - ret0, _ := ret[0].(logrus.Level) - return ret0 + ret0, _ := ret[0].(zerolog.Level) + ret1, _ := ret[1].(error) + return ret0, ret1 } // GetLogLevel indicates an expected call of GetLogLevel. diff --git a/pkg/pipeline/pipeline_context.go b/pkg/pipeline/pipeline_context.go index 2f75bc6..3a10aa3 100644 --- a/pkg/pipeline/pipeline_context.go +++ b/pkg/pipeline/pipeline_context.go @@ -14,7 +14,7 @@ import ( "github.com/equinor/radix-tekton/pkg/models" "github.com/equinor/radix-tekton/pkg/models/env" ownerreferences "github.com/equinor/radix-tekton/pkg/utils/owner_references" - log "github.com/sirupsen/logrus" + "github.com/rs/zerolog/log" tektonclient "github.com/tektoncd/pipeline/pkg/client/clientset/versioned" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -67,7 +67,7 @@ func (ctx *pipelineContext) setPipelineRunParamsFromBuild(envVarsMap v1.EnvVarsM if ctx.radixApplication.Spec.Build == nil || ctx.radixApplication.Spec.Build.Variables == nil || len(ctx.radixApplication.Spec.Build.Variables) == 0 { - log.Debugln("No radixApplication build variables") + log.Debug().Msg("No radixApplication build variables") return } @@ -90,7 +90,7 @@ func (ctx *pipelineContext) setPipelineRunParamsFromEnvironmentBuilds(targetEnv // getGitHash return git commit to which the user repository should be reset before parsing sub-pipelines. func (ctx *pipelineContext) getGitHash() (string, error) { if ctx.env.GetRadixPipelineType() == v1.Build { - log.Infof("build job with no deployment, skipping sub-pipelines.") + log.Info().Msg("build job with no deployment, skipping sub-pipelines.") return "", nil } @@ -101,7 +101,7 @@ func (ctx *pipelineContext) getGitHash() (string, error) { return sourceRdHashFromAnnotation, nil } if sourceDeploymentGitBranch == "" { - log.Infof("source deployment has no git metadata, skipping sub-pipelines") + log.Info().Msg("source deployment has no git metadata, skipping sub-pipelines") return "", nil } sourceRdHashFromBranchHead, err := git.GetGitCommitHashFromHead(ctx.env.GetGitRepositoryWorkspace(), sourceDeploymentGitBranch) @@ -118,7 +118,7 @@ func (ctx *pipelineContext) getGitHash() (string, error) { pipelineJobBranch = re.Build.From } if pipelineJobBranch == "" { - log.Infof("deploy job with no build branch, skipping sub-pipelines.") + log.Info().Msg("deploy job with no build branch, skipping sub-pipelines.") return "", nil } gitHash, err := git.GetGitCommitHashFromHead(ctx.env.GetGitRepositoryWorkspace(), pipelineJobBranch) diff --git a/pkg/pipeline/prepare_pipelines.go b/pkg/pipeline/prepare_pipelines.go index 7c82115..1ff821c 100644 --- a/pkg/pipeline/prepare_pipelines.go +++ b/pkg/pipeline/prepare_pipelines.go @@ -24,7 +24,7 @@ import ( "github.com/equinor/radix-tekton/pkg/utils/git" "github.com/equinor/radix-tekton/pkg/utils/labels" "github.com/equinor/radix-tekton/pkg/utils/radix/deployment/commithash" - log "github.com/sirupsen/logrus" + "github.com/rs/zerolog/log" pipelinev1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -72,7 +72,7 @@ func (ctx *pipelineContext) getEnvironmentSubPipelinesToRun() ([]model.Environme var errs []error timestamp := time.Now().Format("20060102150405") for targetEnv := range ctx.targetEnvironments { - log.Debugf("create a sub-pipeline for the environment %s", targetEnv) + log.Debug().Msgf("create a sub-pipeline for the environment %s", targetEnv) runSubPipeline, pipelineFilePath, err := ctx.preparePipelinesJobForTargetEnv(targetEnv, timestamp) if err != nil { errs = append(errs, err) @@ -89,13 +89,13 @@ func (ctx *pipelineContext) getEnvironmentSubPipelinesToRun() ([]model.Environme return nil, err } if len(environmentSubPipelinesToRun) > 0 { - log.Infoln("Run sub-pipelines:") + log.Info().Msg("Run sub-pipelines:") for _, subPipelineToRun := range environmentSubPipelinesToRun { - log.Infof("- environment %s, pipeline file %s", subPipelineToRun.Environment, subPipelineToRun.PipelineFile) + log.Info().Msgf("- environment %s, pipeline file %s", subPipelineToRun.Environment, subPipelineToRun.PipelineFile) } return environmentSubPipelinesToRun, nil } - log.Infoln("No sub-pipelines to run") + log.Info().Msg("No sub-pipelines to run") return nil, nil } @@ -200,7 +200,7 @@ func (ctx *pipelineContext) preparePipelinesJobForTargetEnv(envName, timestamp s err = ctx.pipelineFileExists(pipelineFilePath) if err != nil { if os.IsNotExist(err) { - log.Infof("There is no Tekton pipeline file: %s. Skip Tekton pipeline", pipelineFilePath) + log.Info().Msgf("There is no Tekton pipeline file: %s. Skip Tekton pipeline", pipelineFilePath) return false, "", nil } return false, "", err @@ -210,13 +210,13 @@ func (ctx *pipelineContext) preparePipelinesJobForTargetEnv(envName, timestamp s if err != nil { return false, "", err } - log.Debugf("loaded a pipeline with %d tasks", len(pipeline.Spec.Tasks)) + log.Debug().Msgf("loaded a pipeline with %d tasks", len(pipeline.Spec.Tasks)) tasks, err := ctx.getPipelineTasks(pipelineFilePath, pipeline) if err != nil { return false, "", err } - log.Debug("all pipeline tasks found") + log.Debug().Msg("all pipeline tasks found") err = ctx.createPipeline(envName, pipeline, tasks, timestamp) if err != nil { return false, "", err @@ -263,7 +263,7 @@ func (ctx *pipelineContext) buildTasks(envName string, tasks []pipelinev1.Task, } ensureCorrectSecureContext(&task) taskMap[originalTaskName] = task - log.Debugf("created the task %s", task.Name) + log.Debug().Msgf("created the task %s", task.Name) } return taskMap, errors.Join(errs...) } @@ -362,7 +362,7 @@ func (ctx *pipelineContext) getPipelineTasks(pipelineFilePath string, pipeline * func (ctx *pipelineContext) getPipelineFilePath(pipelineFile string) (string, error) { if len(pipelineFile) == 0 { pipelineFile = defaults.DefaultPipelineFileName - log.Debugf("Tekton pipeline file name is not specified, using the default file name %s", defaults.DefaultPipelineFileName) + log.Debug().Msgf("Tekton pipeline file name is not specified, using the default file name %s", defaults.DefaultPipelineFileName) } pipelineFile = strings.TrimPrefix(pipelineFile, "/") // Tekton pipeline folder currently is relative to the Radix config file repository folder configFolder := filepath.Dir(ctx.env.GetRadixConfigFileName()) @@ -403,13 +403,13 @@ func (ctx *pipelineContext) createPipeline(envName string, pipeline *pipelinev1. if err != nil { return fmt.Errorf("tasks have not been created. Error: %w", err) } - log.Infof("creates %d tasks for the environment %s", len(taskMap), envName) + log.Info().Msgf("creates %d tasks for the environment %s", len(taskMap), envName) _, err = ctx.tektonClient.TektonV1().Pipelines(ctx.env.GetAppNamespace()).Create(context.Background(), pipeline, metav1.CreateOptions{}) if err != nil { return fmt.Errorf("pipeline %s has not been created. Error: %w", pipeline.Name, err) } - log.Infof("created the pipeline %s for the environment %s", pipeline.Name, envName) + log.Info().Msgf("created the pipeline %s for the environment %s", pipeline.Name, envName) return nil } @@ -450,7 +450,7 @@ func getPipeline(pipelineFileName string) (*pipelinev1.Pipeline, error) { hotfixForPipelineDefaultParamsWithBrokenValue(&pipeline) hotfixForPipelineTasksParamsWithBrokenValue(&pipeline) - log.Debugf("loaded pipeline %s", pipelineFileName) + log.Debug().Msgf("loaded pipeline %s", pipelineFileName) err = validation.ValidatePipeline(&pipeline) if err != nil { return nil, err @@ -509,7 +509,7 @@ func getTasks(pipelineFilePath string) (map[string]pipelinev1.Task, error) { return nil, fmt.Errorf("failed to read data from the file %s: %v", fileName, err) } if !taskIsValid(&task) { - log.Debugf("skip the file %s - not a Tekton task", fileName) + log.Debug().Msgf("skip the file %s - not a Tekton task", fileName) continue } addGitDeployKeyVolume(&task) diff --git a/pkg/pipeline/radix-application_config.go b/pkg/pipeline/radix-application_config.go index d60f820..f077bd4 100644 --- a/pkg/pipeline/radix-application_config.go +++ b/pkg/pipeline/radix-application_config.go @@ -12,7 +12,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/kube" v1 "github.com/equinor/radix-operator/pkg/apis/radix/v1" "github.com/equinor/radix-tekton/pkg/utils/configmap" - log "github.com/sirupsen/logrus" + "github.com/rs/zerolog/log" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/yaml" @@ -24,13 +24,13 @@ func (ctx *pipelineContext) ProcessRadixAppConfig() error { if err != nil { return fmt.Errorf("error reading the Radix config file %s: %v", ctx.GetEnv().GetRadixConfigFileName(), err) } - log.Debugf("Radix config file %s has been loaded", ctx.GetEnv().GetRadixConfigFileName()) + log.Debug().Msgf("Radix config file %s has been loaded", ctx.GetEnv().GetRadixConfigFileName()) ctx.radixApplication, err = ctx.createRadixApplicationFromContent(configFileContent) if err != nil { return err } - log.Debug("Radix Application has been loaded") + log.Debug().Msg("Radix Application has been loaded") err = ctx.setTargetEnvironments() if err != nil { @@ -72,12 +72,12 @@ func (ctx *pipelineContext) createConfigMap(configFileContent string, prepareBui if err != nil { return err } - log.Debugf("Created ConfigMap %s", env.GetRadixConfigMapName()) + log.Debug().Msgf("Created ConfigMap %s", env.GetRadixConfigMapName()) return nil } func (ctx *pipelineContext) setTargetEnvironments() error { - log.Debug("Set target environment") + log.Debug().Msg("Set target environment") if ctx.GetEnv().GetRadixPipelineType() == v1.Promote { return ctx.setTargetEnvironmentsForPromote() } @@ -90,11 +90,11 @@ func (ctx *pipelineContext) setTargetEnvironments() error { ctx.targetEnvironments[envName] = true } if len(ctx.targetEnvironments) > 0 { - log.Infof("Environment(s) %v are mapped to the branch %s.", getEnvironmentList(ctx.targetEnvironments), ctx.env.GetBranch()) + log.Info().Msgf("Environment(s) %v are mapped to the branch %s.", getEnvironmentList(ctx.targetEnvironments), ctx.env.GetBranch()) } else { - log.Infof("No environments are mapped to the branch %s.", ctx.env.GetBranch()) + log.Info().Msgf("No environments are mapped to the branch %s.", ctx.env.GetBranch()) } - log.Infof("pipeline type: %s", ctx.env.GetRadixPipelineType()) + log.Info().Msgf("pipeline type: %s", ctx.env.GetRadixPipelineType()) return nil } @@ -110,11 +110,11 @@ func (ctx *pipelineContext) setTargetEnvironmentsForPromote() error { errs = append(errs, fmt.Errorf("missing promote target environment name")) } if len(errs) > 0 { - log.Infoln("pipeline type: promote") + log.Info().Msg("pipeline type: promote") return errors.Join(errs...) } ctx.targetEnvironments = map[string]bool{ctx.env.GetRadixDeployToEnvironment(): true} // run Tekton pipelines for the promote target environment - log.Infof("promote the deployment %s from the environment %s to %s", ctx.env.GetRadixPromoteDeployment(), ctx.env.GetRadixPromoteFromEnvironment(), ctx.env.GetRadixDeployToEnvironment()) + log.Info().Msgf("promote the deployment %s from the environment %s to %s", ctx.env.GetRadixPromoteDeployment(), ctx.env.GetRadixPromoteFromEnvironment(), ctx.env.GetRadixDeployToEnvironment()) return nil } @@ -124,8 +124,8 @@ func (ctx *pipelineContext) setTargetEnvironmentsForDeploy() error { return fmt.Errorf("no target environment is specified for the deploy pipeline") } ctx.targetEnvironments = map[string]bool{targetEnvironment: true} - log.Infof("Target environment: %v", targetEnvironment) - log.Infof("pipeline type: %s", ctx.env.GetRadixPipelineType()) + log.Info().Msgf("Target environment: %v", targetEnvironment) + log.Info().Msgf("pipeline type: %s", ctx.env.GetRadixPipelineType()) return nil } diff --git a/pkg/pipeline/run_pipelines.go b/pkg/pipeline/run_pipelines.go index f0f7126..bd34db2 100644 --- a/pkg/pipeline/run_pipelines.go +++ b/pkg/pipeline/run_pipelines.go @@ -14,7 +14,7 @@ import ( "github.com/equinor/radix-tekton/pkg/defaults" "github.com/equinor/radix-tekton/pkg/utils/labels" "github.com/equinor/radix-tekton/pkg/utils/radix/applicationconfig" - log "github.com/sirupsen/logrus" + "github.com/rs/zerolog/log" "github.com/tektoncd/pipeline/pkg/apis/pipeline/pod" pipelinev1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" corev1 "k8s.io/api/core/v1" @@ -24,7 +24,7 @@ import ( // RunPipelinesJob Run the job, which creates Tekton PipelineRun-s for each preliminary prepared pipelines of the specified branch func (ctx *pipelineContext) RunPipelinesJob() error { if ctx.GetEnv().GetRadixPipelineType() == radixv1.Build { - log.Infof("pipeline type is build, skip Tekton pipeline run.") + log.Info().Msg("pipeline type is build, skip Tekton pipeline run.") return nil } namespace := ctx.env.GetAppNamespace() @@ -35,7 +35,7 @@ func (ctx *pipelineContext) RunPipelinesJob() error { return err } if len(pipelineList.Items) == 0 { - log.Infof("no pipelines exist, skip Tekton pipeline run.") + log.Info().Msg("no pipelines exist, skip Tekton pipeline run.") return nil } @@ -54,7 +54,7 @@ func (ctx *pipelineContext) RunPipelinesJob() error { re := applicationconfig.GetEnvironmentFromRadixApplication(ctx.radixApplication, ctx.env.GetRadixDeployToEnvironment()) tektonPipelineBranch = re.Build.From } - log.Infof("Run tekton pipelines for the branch %s", tektonPipelineBranch) + log.Info().Msgf("Run tekton pipelines for the branch %s", tektonPipelineBranch) pipelineRunMap, err := ctx.runPipelines(pipelineList.Items, namespace) @@ -101,7 +101,7 @@ func (ctx *pipelineContext) createPipelineRun(namespace string, pipeline *pipeli return nil, fmt.Errorf("missing target environment in labels of the pipeline %s", pipeline.Name) } - log.Debugf("run pipelinerun for the target environment %s", targetEnv) + log.Debug().Msgf("run pipelinerun for the target environment %s", targetEnv) if _, ok := ctx.targetEnvironments[targetEnv]; !ok { return nil, fmt.Errorf("missing target environment %s for the pipeline %s", targetEnv, pipeline.Name) } diff --git a/pkg/utils/configmap/configmap_util.go b/pkg/utils/configmap/configmap_util.go index e3f7fdf..d6a2496 100644 --- a/pkg/utils/configmap/configmap_util.go +++ b/pkg/utils/configmap/configmap_util.go @@ -8,7 +8,7 @@ import ( "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" "github.com/equinor/radix-tekton/pkg/models/env" - log "github.com/sirupsen/logrus" + "github.com/rs/zerolog/log" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,7 +49,7 @@ func CreateGitConfigFromGitRepository(env env.Env, kubeClient kubernetes.Interfa if err != nil { return err } - log.Debugf("Created ConfigMap %s", env.GetGitConfigMapName()) + log.Debug().Msgf("Created ConfigMap %s", env.GetGitConfigMapName()) return nil } diff --git a/pkg/utils/git/git.go b/pkg/utils/git/git.go index b0d91b1..6353211 100644 --- a/pkg/utils/git/git.go +++ b/pkg/utils/git/git.go @@ -18,7 +18,7 @@ import ( "github.com/go-git/go-git/v5/plumbing/filemode" "github.com/go-git/go-git/v5/plumbing/format/diff" "github.com/go-git/go-git/v5/plumbing/object" - log "github.com/sirupsen/logrus" + "github.com/rs/zerolog/log" ) // ResetGitHead alters HEAD of the git repository on file system to point to commitHashString @@ -27,7 +27,7 @@ func ResetGitHead(gitWorkspace, commitHashString string) error { if err != nil { return err } - log.Debugf("opened repositoryPath %s", gitWorkspace) + log.Debug().Msgf("opened repositoryPath %s", gitWorkspace) worktree, err := r.Worktree() if err != nil { @@ -42,7 +42,7 @@ func ResetGitHead(gitWorkspace, commitHashString string) error { if err != nil { return err } - log.Debugf("reset HEAD to %s", commitHashString) + log.Debug().Msgf("reset HEAD to %s", commitHashString) return nil } @@ -72,14 +72,14 @@ func GetGitCommitHashFromHead(gitWorkspace string, branchName string) (string, e if err != nil { return "", err } - log.Debugf("opened gitDir %s", gitDir) + log.Debug().Msgf("opened gitDir %s", gitDir) // Get branchName hash commitHash, err := getBranchCommitHash(r, branchName) if err != nil { return "", err } - log.Debugf("resolved branch %s", branchName) + log.Debug().Msgf("resolved branch %s", branchName) hashBytesString := hex.EncodeToString(commitHash[:]) return hashBytesString, nil @@ -105,7 +105,7 @@ func getGitAffectedResourcesBetweenCommits(gitWorkspace, configBranch, configFil return nil, false, err } - if strings.EqualFold(beforeCommitHash.String(), targetCommitString) { //targetCommit is the very first commit in the repo + if strings.EqualFold(beforeCommitHash.String(), targetCommitString) { // targetCommit is the very first commit in the repo return getChangedFoldersOfCommitFiles(beforeCommit, configBranch, currentBranch, configFile) } @@ -152,7 +152,7 @@ func getChangedFoldersOfCommitFiles(commit *object.Commit, configBranch string, } func getRepository(gitDir string) (*git.Repository, string, error) { - log.Debugf("opened gitDir %s", gitDir) + log.Debug().Msgf("opened gitDir %s", gitDir) repository, err := git.PlainOpen(gitDir) if err != nil { return nil, "", err @@ -201,7 +201,7 @@ func appendFolderToMap(changedFolderNamesMap map[string]bool, changedConfigFile if !*changedConfigFile && strings.EqualFold(configBranch, currentBranch) && strings.EqualFold(configFile, filePath) { *changedConfigFile = true } - log.Debugf("- file: %s", filePath) + log.Debug().Msgf("- file: %s", filePath) } if _, ok := changedFolderNamesMap[folderName]; !ok { changedFolderNamesMap[folderName] = true @@ -254,7 +254,7 @@ func getGitCommitTags(gitWorkspace string, commitHashString string) (string, err commitHash := plumbing.NewHash(commitHashString) - log.Debugf("getting all tags for repository") + log.Debug().Msgf("getting all tags for repository") tags, err := r.Tags() if err != nil { return "", err @@ -263,17 +263,17 @@ func getGitCommitTags(gitWorkspace string, commitHashString string) (string, err // List all tags, both lightweight tags and annotated tags and see if any tags point to HEAD reference. err = tags.ForEach(func(t *plumbing.Reference) error { - log.Debugf("resolving commit hash of tag %s", t.Name()) + log.Debug().Msgf("resolving commit hash of tag %s", t.Name()) // using workaround to circumvent tag resolution bug documented at https://github.com/go-git/go-git/issues/204 tagName := strings.TrimPrefix(string(t.Name()), "refs/tags/") tagRef, err := r.Tag(tagName) if err != nil { - log.Warnf("could not resolve commit hash of tag %s: %v", t.Name(), err) + log.Warn().Msgf("could not resolve commit hash of tag %s: %v", t.Name(), err) return nil } revHash, err := r.ResolveRevision(plumbing.Revision(tagRef.Hash().String())) if err != nil { - log.Warnf("could not resolve commit hash of tag %s: %v", t.Name(), err) + log.Warn().Msgf("could not resolve commit hash of tag %s: %v", t.Name(), err) return nil } if *revHash == commitHash { @@ -282,7 +282,7 @@ func getGitCommitTags(gitWorkspace string, commitHashString string) (string, err return nil }) if err != nil { - log.Warnf("could not resolve tags: %v", err) + log.Warn().Msgf("could not resolve tags: %v", err) return "", nil } @@ -296,13 +296,13 @@ func getGitCommitTags(gitWorkspace string, commitHashString string) (string, err func GetGitCommitHash(workspace string, e env.Env) (string, error) { webhookCommitId := e.GetWebhookCommitId() if webhookCommitId != "" { - log.Debugf("got git commit hash %s from env var %s", webhookCommitId, defaults.RadixGithubWebhookCommitId) + log.Debug().Msgf("got git commit hash %s from env var %s", webhookCommitId, defaults.RadixGithubWebhookCommitId) return webhookCommitId, nil } branchName := e.GetBranch() - log.Debugf("determining git commit hash of HEAD of branch %s", branchName) + log.Debug().Msgf("determining git commit hash of HEAD of branch %s", branchName) gitCommitHash, err := GetGitCommitHashFromHead(workspace, branchName) - log.Debugf("got git commit hash %s from HEAD of branch %s", gitCommitHash, branchName) + log.Debug().Msgf("got git commit hash %s from HEAD of branch %s", gitCommitHash, branchName) return gitCommitHash, err } @@ -311,13 +311,13 @@ func GetChangesFromGitRepository(gitWorkspace, radixConfigBranch, radixConfigFil radixConfigWasChanged := false envChanges := make(map[string][]string) if len(lastCommitHashesForEnvs) == 0 { - log.Infof("No changes in GitHub repository") + log.Info().Msgf("No changes in GitHub repository") return nil, false, nil } if strings.HasPrefix(radixConfigFileName, gitWorkspace) { radixConfigFileName = strings.TrimPrefix(strings.TrimPrefix(radixConfigFileName, gitWorkspace), "/") } - log.Infof("Changes in GitHub repository:") + log.Info().Msgf("Changes in GitHub repository:") for envName, radixDeploymentCommit := range lastCommitHashesForEnvs { changedFolders, radixConfigWasChangedInEnv, err := getGitAffectedResourcesBetweenCommits(gitWorkspace, radixConfigBranch, radixConfigFileName, targetCommitHash, radixDeploymentCommit.CommitHash) envChanges[envName] = changedFolders @@ -328,21 +328,20 @@ func GetChangesFromGitRepository(gitWorkspace, radixConfigBranch, radixConfigFil printEnvironmentChangedFolders(envName, radixDeploymentCommit, targetCommitHash, changedFolders) } if radixConfigWasChanged { - log.Infof("Radix config file was changed %s", radixConfigFileName) + log.Info().Msgf("Radix config file was changed %s", radixConfigFileName) } return envChanges, radixConfigWasChanged, nil } func printEnvironmentChangedFolders(envName string, radixDeploymentCommit commithash.RadixDeploymentCommit, targetCommitHash string, changedFolders []string) { - log.Infof("- for the environment %s", envName) + log.Info().Msgf("- for the environment %s", envName) if len(radixDeploymentCommit.RadixDeploymentName) == 0 { - log.Infof(" from initial commit to commit %s:", targetCommitHash) + log.Info().Msgf(" from initial commit to commit %s:", targetCommitHash) } else { - log.Infof(" after the commit %s (of the deployment %s) to the commit %s:", radixDeploymentCommit.CommitHash, radixDeploymentCommit.RadixDeploymentName, targetCommitHash) + log.Info().Msgf(" after the commit %s (of the deployment %s) to the commit %s:", radixDeploymentCommit.CommitHash, radixDeploymentCommit.RadixDeploymentName, targetCommitHash) } sort.Strings(changedFolders) for _, folder := range changedFolders { - log.Infof(" - %s", folder) + log.Info().Msgf(" - %s", folder) } - log.Infoln() } diff --git a/pkg/utils/git/git_test.go b/pkg/utils/git/git_test.go index 375126a..e1832d6 100644 --- a/pkg/utils/git/git_test.go +++ b/pkg/utils/git/git_test.go @@ -9,8 +9,8 @@ import ( "strings" "testing" - "github.com/equinor/radix-tekton/pkg/utils/test" - log "github.com/sirupsen/logrus" + "github.com/equinor/radix-tekton/pkg/utils/logger" + "github.com/rs/zerolog" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -396,6 +396,5 @@ func TestGetGitChangedFolders_DummyRepo(t *testing.T) { } func setupLog(t *testing.T) { - log.AddHook(test.NewTestLogHook(t, log.DebugLevel). - ModifyFormatter(func(f *log.TextFormatter) { f.DisableTimestamp = true })) + logger.InitializeLogger(zerolog.DebugLevel, true) } diff --git a/pkg/utils/logger/logger.go b/pkg/utils/logger/logger.go new file mode 100644 index 0000000..feaf0e9 --- /dev/null +++ b/pkg/utils/logger/logger.go @@ -0,0 +1,20 @@ +package logger + +import ( + "os" + "time" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" +) + +func InitializeLogger(logLevel zerolog.Level, prettyPrint bool) { + zerolog.SetGlobalLevel(logLevel) + zerolog.DurationFieldUnit = time.Millisecond + if prettyPrint { + log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.TimeOnly}) + } + + zerolog.DefaultContextLogger = &log.Logger + log.Debug().Msgf("log-level '%v'", logLevel.String()) +} diff --git a/pkg/utils/owner_references/owner_references.go b/pkg/utils/owner_references/owner_references.go index 72f54f7..ef7ce20 100644 --- a/pkg/utils/owner_references/owner_references.go +++ b/pkg/utils/owner_references/owner_references.go @@ -6,16 +6,16 @@ import ( "os" "strings" - log "github.com/sirupsen/logrus" + "github.com/rs/zerolog/log" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" ) -//GetOwnerReferenceOfJobFromLabels Created an OwnerReference from the DownwardAPI created file, if exist +// GetOwnerReferenceOfJobFromLabels Created an OwnerReference from the DownwardAPI created file, if exist func GetOwnerReferenceOfJobFromLabels() *metav1.OwnerReference { controllerUid, jobName, err := getOwnerReferencePropertiesFromDownwardsApiFile() if err != nil { - log.Debugf("%v", err) + log.Debug().Msgf("%v", err) return nil } return &metav1.OwnerReference{ @@ -28,7 +28,7 @@ func GetOwnerReferenceOfJobFromLabels() *metav1.OwnerReference { func getOwnerReferencePropertiesFromDownwardsApiFile() (string, string, error) { labelsFile := "/pod-labels/labels" - log.Debugf("read pod-labels from the file %s", labelsFile) + log.Debug().Msgf("read pod-labels from the file %s", labelsFile) if _, err := os.Stat(labelsFile); os.IsNotExist(err) { return "", "", fmt.Errorf("missing the file with labels %s - ownerReference is not set to the pod", labelsFile) } diff --git a/pkg/utils/test/test_log_hook.go b/pkg/utils/test/test_log_hook.go deleted file mode 100644 index 4966a08..0000000 --- a/pkg/utils/test/test_log_hook.go +++ /dev/null @@ -1,58 +0,0 @@ -package test - -/* The log hook to type logrus logs, written within the logic under test -Example: -func setupLog(t *testing.T) { - log.AddHook(test.NewTestLogHook(t, log.DebugLevel). - ModifyFormatter(func(f *log.TextFormatter) { f.DisableTimestamp = true })) -} - -func TestSomething(t *testing.T) { - setupLog(t) - //test is here -} -*/ - -import ( - log "github.com/sirupsen/logrus" - "testing" -) - -type testLogHook struct { - t *testing.T - levels []log.Level - formatter *log.TextFormatter -} - -func NewTestLogHook(t *testing.T, level log.Level) testLogHook { - var logLevels []log.Level - for _, logLevel := range log.AllLevels { - if logLevel <= level { - logLevels = append(logLevels, logLevel) - } - } - log.SetLevel(level) - formatter := log.TextFormatter{ - DisableColors: true, - } - log.SetFormatter(&formatter) - return testLogHook{t: t, levels: logLevels, formatter: &formatter} -} - -func (m testLogHook) ModifyFormatter(modify func(*log.TextFormatter)) testLogHook { - modify(m.formatter) - return m -} - -func (m testLogHook) DisableTimestamp(disable bool) testLogHook { - m.formatter.DisableTimestamp = disable - return m -} - -func (m testLogHook) Levels() []log.Level { - return m.levels -} - -func (m testLogHook) Fire(entry *log.Entry) error { - return nil -}