Add jenkins input plugin (#4289)
This commit is contained in:
156
plugins/inputs/jenkins/client.go
Normal file
156
plugins/inputs/jenkins/client.go
Normal file
@@ -0,0 +1,156 @@
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type client struct {
|
||||
baseURL string
|
||||
httpClient *http.Client
|
||||
username string
|
||||
password string
|
||||
sessionCookie *http.Cookie
|
||||
semaphore chan struct{}
|
||||
}
|
||||
|
||||
func newClient(httpClient *http.Client, url, username, password string, maxConnections int) *client {
|
||||
return &client{
|
||||
baseURL: url,
|
||||
httpClient: httpClient,
|
||||
username: username,
|
||||
password: password,
|
||||
semaphore: make(chan struct{}, maxConnections),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *client) init() error {
|
||||
// get session cookie
|
||||
req, err := http.NewRequest("GET", c.baseURL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c.username != "" && c.password != "" {
|
||||
// set auth
|
||||
req.SetBasicAuth(c.username, c.password)
|
||||
}
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
for _, cc := range resp.Cookies() {
|
||||
if strings.Contains(cc.Name, "JSESSIONID") {
|
||||
c.sessionCookie = cc
|
||||
break
|
||||
}
|
||||
}
|
||||
// first api fetch
|
||||
if err := c.doGet(context.Background(), jobPath, new(jobResponse)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *client) doGet(ctx context.Context, url string, v interface{}) error {
|
||||
req, err := createGetRequest(c.baseURL+url, c.username, c.password, c.sessionCookie)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
select {
|
||||
case c.semaphore <- struct{}{}:
|
||||
break
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
resp, err := c.httpClient.Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
<-c.semaphore
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
resp.Body.Close()
|
||||
<-c.semaphore
|
||||
}()
|
||||
// Clear invalid token if unauthorized
|
||||
if resp.StatusCode == http.StatusUnauthorized {
|
||||
c.sessionCookie = nil
|
||||
return APIError{
|
||||
URL: url,
|
||||
StatusCode: resp.StatusCode,
|
||||
Title: resp.Status,
|
||||
}
|
||||
}
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return APIError{
|
||||
URL: url,
|
||||
StatusCode: resp.StatusCode,
|
||||
Title: resp.Status,
|
||||
}
|
||||
}
|
||||
if resp.StatusCode == http.StatusNoContent {
|
||||
return APIError{
|
||||
URL: url,
|
||||
StatusCode: resp.StatusCode,
|
||||
Title: resp.Status,
|
||||
}
|
||||
}
|
||||
if err = json.NewDecoder(resp.Body).Decode(v); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type APIError struct {
|
||||
URL string
|
||||
StatusCode int
|
||||
Title string
|
||||
Description string
|
||||
}
|
||||
|
||||
func (e APIError) Error() string {
|
||||
if e.Description != "" {
|
||||
return fmt.Sprintf("[%s] %s: %s", e.URL, e.Title, e.Description)
|
||||
}
|
||||
return fmt.Sprintf("[%s] %s", e.URL, e.Title)
|
||||
}
|
||||
|
||||
func createGetRequest(url string, username, password string, sessionCookie *http.Cookie) (*http.Request, error) {
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if sessionCookie != nil {
|
||||
req.AddCookie(sessionCookie)
|
||||
} else if username != "" && password != "" {
|
||||
req.SetBasicAuth(username, password)
|
||||
}
|
||||
req.Header.Add("Accept", "application/json")
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (c *client) getJobs(ctx context.Context, jr *jobRequest) (js *jobResponse, err error) {
|
||||
js = new(jobResponse)
|
||||
url := jobPath
|
||||
if jr != nil {
|
||||
url = jr.URL()
|
||||
}
|
||||
err = c.doGet(ctx, url, js)
|
||||
return js, err
|
||||
}
|
||||
|
||||
func (c *client) getBuild(ctx context.Context, jr jobRequest, number int64) (b *buildResponse, err error) {
|
||||
b = new(buildResponse)
|
||||
url := jr.buildURL(number)
|
||||
err = c.doGet(ctx, url, b)
|
||||
return b, err
|
||||
}
|
||||
|
||||
func (c *client) getAllNodes(ctx context.Context) (nodeResp *nodeResponse, err error) {
|
||||
nodeResp = new(nodeResponse)
|
||||
err = c.doGet(ctx, nodePath, nodeResp)
|
||||
return nodeResp, err
|
||||
}
|
||||
Reference in New Issue
Block a user