remove err struct

This commit is contained in:
Kelvin Wang 2018-06-25 15:43:10 -07:00
parent e7ff7d506b
commit 3457c98eb1
2 changed files with 48 additions and 163 deletions

View File

@ -82,52 +82,10 @@ const (
measurementJob = "jenkins_job" measurementJob = "jenkins_job"
) )
// Error base type of error. func badFormatErr(url string, field interface{}, want string, fieldName string) error {
type Error struct { return fmt.Errorf("error bad format[%s]: fieldName: %s, want %s, got %T", url, fieldName, want, field)
err error
reference string
url string
} }
func newError(err error, ref, url string) *Error {
return &Error{
err: err,
reference: ref,
url: url,
}
}
func (e *Error) Error() string {
if e == nil {
return ""
}
return fmt.Sprintf("error %s[%s]: %v", e.reference, e.url, e.err)
}
func badFormatErr(url string, field interface{}, want string, fieldName string) *Error {
return &Error{
err: fmt.Errorf("fieldName: %s, want %s, got %T", fieldName, want, field),
reference: errBadFormat,
url: url,
}
}
// err references
const (
errParseConfig = "parse jenkins config"
errJobFilterCompile = "compile job filters"
errNodeFilterCompile = "compile node filters"
errConnectJenkins = "connect jenkins instance"
errInitJenkins = "init jenkins instance"
errRetrieveNode = "retrieving nodes"
errRetrieveJobs = "retrieving jobs"
errEmptyNodeName = "empty node name"
errEmptyMonitorData = "empty monitor data"
errBadFormat = "bad format"
errRetrieveInnerJobs = "retrieving inner jobs"
errRetrieveLatestBuild = "retrieving latest build"
)
// SampleConfig implements telegraf.Input interface // SampleConfig implements telegraf.Input interface
func (j *Jenkins) SampleConfig() string { func (j *Jenkins) SampleConfig() string {
return sampleConfig return sampleConfig
@ -156,38 +114,39 @@ func (j *Jenkins) Gather(acc telegraf.Accumulator) error {
return nil return nil
} }
func (j *Jenkins) initClient() (*http.Client, *Error) { func (j *Jenkins) initClient() (*http.Client, error) {
tlsCfg, err := j.ClientConfig.TLSConfig() tlsCfg, err := j.ClientConfig.TLSConfig()
if err != nil { if err != nil {
return nil, newError(err, errParseConfig, j.URL) return nil, fmt.Errorf("error parse jenkins config[%s]: %v", j.URL, err)
} }
return &http.Client{ return &http.Client{
Transport: &http.Transport{ Transport: &http.Transport{
TLSClientConfig: tlsCfg, TLSClientConfig: tlsCfg,
MaxIdleConns: j.MaxConnections,
}, },
Timeout: j.ResponseTimeout.Duration, Timeout: j.ResponseTimeout.Duration,
}, nil }, nil
} }
// seperate the client as dependency to use httptest Client for mocking // seperate the client as dependency to use httptest Client for mocking
func (j *Jenkins) newInstance(client *http.Client) *Error { func (j *Jenkins) newInstance(client *http.Client) error {
// create instance // create instance
var err error var err error
j.instance, err = gojenkins.CreateJenkins(client, j.URL, j.Username, j.Password).Init() j.instance, err = gojenkins.CreateJenkins(client, j.URL, j.Username, j.Password).Init()
if err != nil { if err != nil {
return newError(err, errConnectJenkins, j.URL) return fmt.Errorf("error connect jenkins instance[%s]: %v", j.URL, err)
} }
// init job filter // init job filter
j.jobFilter, err = filter.Compile(j.JobExclude) j.jobFilter, err = filter.Compile(j.JobExclude)
if err != nil { if err != nil {
return newError(err, errJobFilterCompile, j.URL) return fmt.Errorf("error compile job filters[%s]: %v", j.URL, err)
} }
// init node filter // init node filter
j.nodeFilter, err = filter.Compile(j.NodeExclude) j.nodeFilter, err = filter.Compile(j.NodeExclude)
if err != nil { if err != nil {
return newError(err, errNodeFilterCompile, j.URL) return fmt.Errorf("error compile node filters[%s]: %v", j.URL, err)
} }
// init tcp pool with default value // init tcp pool with default value
@ -203,7 +162,7 @@ func (j *Jenkins) newInstance(client *http.Client) *Error {
return nil return nil
} }
func (j *Jenkins) gatherNodeData(node *gojenkins.Node, url string, acc telegraf.Accumulator) *Error { func (j *Jenkins) gatherNodeData(node *gojenkins.Node, url string, acc telegraf.Accumulator) error {
tags := map[string]string{} tags := map[string]string{}
fields := make(map[string]interface{}) fields := make(map[string]interface{})
@ -211,7 +170,7 @@ func (j *Jenkins) gatherNodeData(node *gojenkins.Node, url string, acc telegraf.
// detect the parsing error, since gojenkins lib won't do it // detect the parsing error, since gojenkins lib won't do it
if info == nil || info.DisplayName == "" { if info == nil || info.DisplayName == "" {
return newError(nil, errEmptyNodeName, url) return fmt.Errorf("error empty node name[%s]: ", j.URL)
} }
tags["node_name"] = info.DisplayName tags["node_name"] = info.DisplayName
@ -222,7 +181,7 @@ func (j *Jenkins) gatherNodeData(node *gojenkins.Node, url string, acc telegraf.
} }
if info.MonitorData.Hudson_NodeMonitors_ArchitectureMonitor == nil { if info.MonitorData.Hudson_NodeMonitors_ArchitectureMonitor == nil {
return newError(fmt.Errorf("maybe check your permission"), errEmptyMonitorData, url) return fmt.Errorf("error empty monitor data[%s]: ", j.URL)
} }
tags["arch"], ok = info.MonitorData.Hudson_NodeMonitors_ArchitectureMonitor.(string) tags["arch"], ok = info.MonitorData.Hudson_NodeMonitors_ArchitectureMonitor.(string)
if !ok { if !ok {
@ -292,7 +251,7 @@ func (j *Jenkins) gatherNodesData(acc telegraf.Accumulator) {
// since gojenkins lib will never return error // since gojenkins lib will never return error
// returns error for len(nodes) is 0 // returns error for len(nodes) is 0
if err != nil || len(nodes) == 0 { if err != nil || len(nodes) == 0 {
acc.AddError(newError(err, errRetrieveNode, url)) acc.AddError(fmt.Errorf("error retrieving nodes[%s]: %v", j.URL, err))
return return
} }
// get node data // get node data
@ -308,7 +267,7 @@ func (j *Jenkins) gatherNodesData(acc telegraf.Accumulator) {
func (j *Jenkins) gatherJobs(acc telegraf.Accumulator) { func (j *Jenkins) gatherJobs(acc telegraf.Accumulator) {
jobs, err := j.instance.GetAllJobNames() jobs, err := j.instance.GetAllJobNames()
if err != nil { if err != nil {
acc.AddError(newError(err, errRetrieveJobs, j.URL)) acc.AddError(fmt.Errorf("error retrieving jobs[%s]: %v", j.URL, err))
return return
} }
jobsC := make(chan jobRequest, j.MaxConnections) jobsC := make(chan jobRequest, j.MaxConnections)
@ -336,7 +295,7 @@ func (j *Jenkins) gatherJobs(acc telegraf.Accumulator) {
wg.Wait() wg.Wait()
} }
func (j *Jenkins) getJobDetail(sj jobRequest, jobsC chan<- jobRequest, wg *sync.WaitGroup, acc telegraf.Accumulator) *Error { func (j *Jenkins) getJobDetail(sj jobRequest, jobsC chan<- jobRequest, wg *sync.WaitGroup, acc telegraf.Accumulator) error {
defer wg.Done() defer wg.Done()
if j.MaxSubJobDepth > 0 && sj.layer == j.MaxSubJobDepth { if j.MaxSubJobDepth > 0 && sj.layer == j.MaxSubJobDepth {
return nil return nil
@ -348,7 +307,7 @@ func (j *Jenkins) getJobDetail(sj jobRequest, jobsC chan<- jobRequest, wg *sync.
url := j.URL + "/job/" + strings.Join(sj.combined(), "/job/") + "/api/json" url := j.URL + "/job/" + strings.Join(sj.combined(), "/job/") + "/api/json"
jobDetail, err := j.instance.GetJob(sj.name, sj.parents...) jobDetail, err := j.instance.GetJob(sj.name, sj.parents...)
if err != nil { if err != nil {
return newError(err, errRetrieveInnerJobs, url) return fmt.Errorf("error retrieving inner jobs[%s]: ", url)
} }
for k, innerJob := range jobDetail.Raw.Jobs { for k, innerJob := range jobDetail.Raw.Jobs {
@ -385,7 +344,7 @@ func (j *Jenkins) getJobDetail(sj jobRequest, jobsC chan<- jobRequest, wg *sync.
if err == nil && status != 200 { if err == nil && status != 200 {
err = fmt.Errorf("status code %d", status) err = fmt.Errorf("status code %d", status)
} }
return newError(err, errRetrieveLatestBuild, j.URL+baseURL+"/api/json") return fmt.Errorf("error retrieving inner jobs[%s]: %v", j.URL+baseURL+"/api/json", err)
} }
if build.Raw.Building { if build.Raw.Building {

View File

@ -2,7 +2,6 @@ package jenkins
import ( import (
"encoding/json" "encoding/json"
"errors"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"sort" "sort"
@ -15,40 +14,6 @@ import (
"github.com/kelwang/gojenkins" "github.com/kelwang/gojenkins"
) )
func TestErr(t *testing.T) {
tests := []struct {
err *Error
output string
}{
{
nil,
"",
},
{
&Error{
reference: errConnectJenkins,
url: "http://badurl.com",
err: errors.New("unknown error"),
},
"error connect jenkins instance[http://badurl.com]: unknown error",
},
{
newError(errors.New("2"), errEmptyMonitorData, "http://badurl.com"),
"error empty monitor data[http://badurl.com]: 2",
},
{
badFormatErr("http://badurl.com", 20.12, "string", "arch"),
"error bad format[http://badurl.com]: fieldName: arch, want string, got float64",
},
}
for _, test := range tests {
output := test.err.Error()
if output != test.output {
t.Errorf("Expected %s, got %s\n", test.output, output)
}
}
}
func TestJobRequest(t *testing.T) { func TestJobRequest(t *testing.T) {
tests := []struct { tests := []struct {
input jobRequest input jobRequest
@ -132,7 +97,7 @@ func TestGatherNodeData(t *testing.T) {
name string name string
input mockHandler input mockHandler
output *testutil.Accumulator output *testutil.Accumulator
oe *Error wantErr bool
}{ }{
{ {
name: "bad endpoint", name: "bad endpoint",
@ -142,9 +107,7 @@ func TestGatherNodeData(t *testing.T) {
"/computer/api/json": nil, "/computer/api/json": nil,
}, },
}, },
oe: &Error{ wantErr: true,
reference: errRetrieveNode,
},
}, },
{ {
name: "bad node data", name: "bad node data",
@ -160,9 +123,7 @@ func TestGatherNodeData(t *testing.T) {
}, },
}, },
}, },
oe: &Error{ wantErr: true,
reference: errEmptyNodeName,
},
}, },
{ {
name: "bad empty monitor data", name: "bad empty monitor data",
@ -177,9 +138,7 @@ func TestGatherNodeData(t *testing.T) {
}, },
}, },
}, },
oe: &Error{ wantErr: true,
reference: errEmptyMonitorData,
},
}, },
{ {
name: "bad monitor data format", name: "bad monitor data format",
@ -195,9 +154,7 @@ func TestGatherNodeData(t *testing.T) {
}, },
}, },
}, },
oe: &Error{ wantErr: true,
reference: errBadFormat,
},
}, },
{ {
name: "filtered nodes", name: "filtered nodes",
@ -286,22 +243,13 @@ func TestGatherNodeData(t *testing.T) {
acc := new(testutil.Accumulator) acc := new(testutil.Accumulator)
j.gatherNodesData(acc) j.gatherNodesData(acc)
if err := acc.FirstError(); err != nil { if err := acc.FirstError(); err != nil {
te = err.(*Error) te = err
} }
if test.oe == nil && te != nil { if !test.wantErr && te != nil {
t.Fatalf("%s: failed %s, expected to be nil", test.name, te.Error()) t.Fatalf("%s: failed %s, expected to be nil", test.name, te.Error())
} else if test.oe != nil { } else if test.wantErr && te == nil {
test.oe.url = ts.URL + "/computer/api/json" t.Fatalf("%s: expected err, got nil", test.name)
if te == nil {
t.Fatalf("%s: want err: %s, got nil", test.name, test.oe.Error())
}
if test.oe.reference != te.reference {
t.Fatalf("%s: bad error msg Expected %s, got %s\n", test.name, test.oe.reference, te.reference)
}
if test.oe.url != te.url {
t.Fatalf("%s: bad error url Expected %s, got %s\n", test.name, test.oe.url, te.url)
}
} }
if test.output == nil && len(acc.Metrics) > 0 { if test.output == nil && len(acc.Metrics) > 0 {
t.Fatalf("%s: collected extra data", test.name) t.Fatalf("%s: collected extra data", test.name)
@ -334,7 +282,7 @@ func TestNewInstance(t *testing.T) {
name string name string
input *Jenkins input *Jenkins
output *Jenkins output *Jenkins
oe *Error wantErr bool
}{ }{
{ {
name: "bad jenkins config", name: "bad jenkins config",
@ -342,10 +290,7 @@ func TestNewInstance(t *testing.T) {
URL: "http://a bad url", URL: "http://a bad url",
ResponseTimeout: internal.Duration{Duration: time.Microsecond}, ResponseTimeout: internal.Duration{Duration: time.Microsecond},
}, },
oe: &Error{ wantErr: true,
url: "http://a bad url",
reference: errConnectJenkins,
},
}, },
{ {
name: "has filter", name: "has filter",
@ -370,15 +315,10 @@ func TestNewInstance(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
te := test.input.newInstance(mockClient) te := test.input.newInstance(mockClient)
if test.oe == nil && te != nil { if !test.wantErr && te != nil {
t.Fatalf("%s: failed %s, expected to be nil", test.name, te.Error()) t.Fatalf("%s: failed %s, expected to be nil", test.name, te.Error())
} else if test.oe != nil { } else if test.wantErr && te == nil {
if test.oe.reference != te.reference { t.Fatalf("%s: expected err, got nil", test.name)
t.Fatalf("%s: bad error msg Expected %s, got %s\n", test.name, test.oe.reference, te.reference)
}
if test.oe.url != te.url {
t.Fatalf("%s: bad error url Expected %s, got %s\n", test.name, test.oe.url, te.url)
}
} }
if test.output != nil { if test.output != nil {
if test.input.instance == nil { if test.input.instance == nil {
@ -397,7 +337,7 @@ func TestGatherJobs(t *testing.T) {
name string name string
input mockHandler input mockHandler
output *testutil.Accumulator output *testutil.Accumulator
oe *Error wantErr bool
}{ }{
{ {
name: "empty job", name: "empty job",
@ -414,10 +354,7 @@ func TestGatherJobs(t *testing.T) {
}, },
}, },
}, },
oe: &Error{ wantErr: true,
reference: errRetrieveInnerJobs,
url: "/job/job1/api/json",
},
}, },
{ {
name: "jobs has no build", name: "jobs has no build",
@ -448,10 +385,7 @@ func TestGatherJobs(t *testing.T) {
}, },
}, },
}, },
oe: &Error{ wantErr: true,
url: "/job/job1/1/api/json",
reference: errRetrieveLatestBuild,
},
}, },
{ {
name: "ignore building job", name: "ignore building job",
@ -671,22 +605,14 @@ func TestGatherJobs(t *testing.T) {
acc := new(testutil.Accumulator) acc := new(testutil.Accumulator)
j.gatherJobs(acc) j.gatherJobs(acc)
if err := acc.FirstError(); err != nil { if err := acc.FirstError(); err != nil {
te = err.(*Error) te = err
} }
if test.oe == nil && te != nil { if !test.wantErr && te != nil {
t.Fatalf("%s: failed %s, expected to be nil", test.name, te.Error()) t.Fatalf("%s: failed %s, expected to be nil", test.name, te.Error())
} else if test.oe != nil { } else if test.wantErr && te == nil {
test.oe.url = ts.URL + test.oe.url t.Fatalf("%s: expected err, got nil", test.name)
if te == nil {
t.Fatalf("%s: want err: %s, got nil", test.name, test.oe.Error())
}
if test.oe.reference != te.reference {
t.Fatalf("%s: bad error msg Expected %s, got %s\n", test.name, test.oe.reference, te.reference)
}
if test.oe.url != te.url {
t.Fatalf("%s: bad error url Expected %s, got %s\n", test.name, test.oe.url, te.url)
}
} }
if test.output != nil && len(test.output.Metrics) > 0 { if test.output != nil && len(test.output.Metrics) > 0 {
// sort metrics // sort metrics
sort.Slice(acc.Metrics, func(i, j int) bool { sort.Slice(acc.Metrics, func(i, j int) bool {