diff --git a/artifact.go b/artifact.go index 1cd4746..a9e2daf 100644 --- a/artifact.go +++ b/artifact.go @@ -44,7 +44,7 @@ func (a Artifact) GetData(ctx context.Context) ([]byte, error) { code := response.StatusCode if code != 200 { - Error.Printf("Jenkins responded with StatusCode: %d", code) + Logger.Error("Jenkins responded with StatusCode: %d", code) return nil, errors.New("Could not get File Contents") } return []byte(data), nil @@ -59,7 +59,7 @@ func (a Artifact) Save(ctx context.Context, path string) (bool, error) { } if _, err = os.Stat(path); err == nil { - Warning.Println("Local Copy already exists, Overwriting...") + Logger.Warn("Local Copy already exists, Overwriting...") } err = ioutil.WriteFile(path, data, 0644) @@ -74,7 +74,7 @@ func (a Artifact) Save(ctx context.Context, path string) (bool, error) { // Save Artifact to directory using Artifact filename. func (a Artifact) SaveToDir(ctx context.Context, dir string) (bool, error) { if _, err := os.Stat(dir); err != nil { - Error.Printf("can't save artifact: directory %s does not exist", dir) + Logger.Error("can't save artifact: directory %s does not exist", dir) return false, fmt.Errorf("can't save artifact: directory %s does not exist", dir) } saved, err := a.Save(ctx, path.Join(dir, a.FileName)) diff --git a/jenkins.go b/jenkins.go index 86dc719..b183560 100644 --- a/jenkins.go +++ b/jenkins.go @@ -40,18 +40,14 @@ type Jenkins struct { Requester *Requester } -// Loggers -var ( - Info *log.Logger - Warning *log.Logger - Error *log.Logger -) +// Main Logger +var Logger LeveledLogger // Init Method. Should be called after creating a Jenkins Instance. // e.g jenkins,err := CreateJenkins("url").Init() // HTTP Client is set here, Connection to jenkins is tested here. func (j *Jenkins) Init(ctx context.Context) (*Jenkins, error) { - j.initLoggers() + j.initDefaultLogger() // Check Connection j.Raw = new(ExecutorResponse) @@ -68,18 +64,24 @@ func (j *Jenkins) Init(ctx context.Context) (*Jenkins, error) { return j, nil } -func (j *Jenkins) initLoggers() { - Info = log.New(os.Stdout, +func (j *Jenkins) initDefaultLogger() { + debug := log.New(os.Stdout, + "DEBUG: ", + log.Ldate|log.Ltime|log.Lshortfile) + + info := log.New(os.Stdout, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile) - Warning = log.New(os.Stdout, + warning := log.New(os.Stdout, "WARNING: ", log.Ldate|log.Ltime|log.Lshortfile) - Error = log.New(os.Stderr, + err := log.New(os.Stderr, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile) + + Logger = NewLeveledLogger(debug, info, warning, err) } // Get Basic Information About Jenkins diff --git a/job.go b/job.go index 1936af7..8814bed 100644 --- a/job.go +++ b/job.go @@ -420,15 +420,6 @@ func (j *Job) HasQueuedBuild() { } func (j *Job) InvokeSimple(ctx context.Context, params map[string]string) (int64, error) { - isQueued, err := j.IsQueued(ctx) - if err != nil { - return 0, err - } - if isQueued { - Error.Printf("%s is already running", j.GetName()) - return 0, nil - } - endpoint := "/build" parameters, err := j.GetParameters(ctx) if err != nil { @@ -469,14 +460,6 @@ func (j *Job) InvokeSimple(ctx context.Context, params map[string]string) (int64 } func (j *Job) Invoke(ctx context.Context, files []string, skipIfRunning bool, params map[string]string, cause string, securityToken string) (bool, error) { - isQueued, err := j.IsQueued(ctx) - if err != nil { - return false, err - } - if isQueued { - Error.Printf("%s is already running", j.GetName()) - return false, nil - } isRunning, err := j.IsRunning(ctx) if err != nil { return false, err diff --git a/logger.go b/logger.go new file mode 100644 index 0000000..2834a44 --- /dev/null +++ b/logger.go @@ -0,0 +1,71 @@ +// Copyright 2022 Dmitry Heraskou +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF interface{} KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +// Gojenkins is a Jenkins Client in Go, that exposes the jenkins REST api in a more developer friendly way. +package gojenkins + +import "log" + +// Logger interface used by jenkins for loging +type LeveledLogger interface { + Debug(format string, a ...interface{}) + Info(format string, a ...interface{}) + Warn(format string, a ...interface{}) + Error(format string, a ...interface{}) +} + +// Simple implementation using golang log library +type LeveledLoggerImpl struct { + debug *log.Logger + info *log.Logger + warning *log.Logger + err *log.Logger +} + +func NewLeveledLogger(debug, info, warn, err *log.Logger) LeveledLogger { + return &LeveledLoggerImpl{ + debug: debug, + info: info, + warning: warn, + err: err, + } +} + +func (l *LeveledLoggerImpl) Debug(format string, a ...interface{}) { + if l == nil || l.debug == nil { + return + } + l.debug.Printf(format, a) +} + +func (l *LeveledLoggerImpl) Info(format string, a ...interface{}) { + if l == nil || l.info == nil { + return + } + l.info.Printf(format, a) +} + +func (l *LeveledLoggerImpl) Warn(format string, a ...interface{}) { + if l == nil || l.warning == nil { + return + } + l.warning.Printf(format, a) +} + +func (l *LeveledLoggerImpl) Error(format string, a ...interface{}) { + if l == nil || l.err == nil { + return + } + l.err.Printf(format, a) +} diff --git a/request.go b/request.go index c67aab1..32fdccf 100644 --- a/request.go +++ b/request.go @@ -22,7 +22,6 @@ import ( "fmt" "io" "io/ioutil" - "log" "mime/multipart" "net/http" "net/http/httputil" @@ -146,7 +145,13 @@ func (r *Requester) redirectPolicyFunc(req *http.Request, via []*http.Request) e return nil } -func (r *Requester) Do(ctx context.Context, ar *APIRequest, responseStruct interface{}, options ...interface{}) (*http.Response, error) { +func (r *Requester) Do(ctx context.Context, ar *APIRequest, responseStruct interface{}, options ...interface{}) (resp *http.Response, err error) { + defer func() { + if err != nil { + Logger.Error("Error while performing '%s' request to endpoint '%s': %s", ar.Method, ar.Endpoint+ar.Suffix, err.Error()) + } + }() + if !strings.HasSuffix(ar.Endpoint, "/") && ar.Method != "POST" { ar.Endpoint += "/" } @@ -182,13 +187,13 @@ func (r *Requester) Do(ctx context.Context, ar *APIRequest, responseStruct inter for _, file := range files { fileData, err := os.Open(file) if err != nil { - Error.Println(err.Error()) + Logger.Error(err.Error()) return nil, err } part, err := writer.CreateFormFile("file", filepath.Base(file)) if err != nil { - Error.Println(err.Error()) + Logger.Error(err.Error()) return nil, err } if _, err = io.Copy(part, fileData); err != nil { @@ -227,25 +232,25 @@ func (r *Requester) Do(ctx context.Context, ar *APIRequest, responseStruct inter req.Header.Add(k, ar.Headers.Get(k)) } - if response, err := r.Client.Do(req); err != nil { + if resp, err = r.Client.Do(req); err != nil { return nil, err } else { if v := ctx.Value("debug"); v != nil { - dump, err := httputil.DumpResponse(response, true) + dump, err := httputil.DumpResponse(resp, true) if err != nil { - log.Fatal(err) + Logger.Error("Error while performing '%s' request to endpoint '%s': %s", ar.Method, ar.Endpoint+ar.Suffix, err.Error()) } - log.Printf("DEBUG %q\n", dump) + Logger.Debug("%q\n", dump) } - errorText := response.Header.Get("X-Error") + errorText := resp.Header.Get("X-Error") if errorText != "" { return nil, errors.New(errorText) } switch responseStruct.(type) { case *string: - return r.ReadRawResponse(response, responseStruct) + return r.ReadRawResponse(resp, responseStruct) default: - return r.ReadJSONResponse(response, responseStruct) + return r.ReadJSONResponse(resp, responseStruct) } }