diff --git a/jenkins/client.go b/jenkins/client.go new file mode 100644 index 00000000..e599b9f7 --- /dev/null +++ b/jenkins/client.go @@ -0,0 +1,64 @@ +package jenkins + +import ( + "bytes" + "encoding/json" + "io" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + +func Create(jenkinsURL string, username string, apiKey string) (*View, error) { + const apiSuffix = "api/json?pretty=true" + parsedSuffix, err := url.Parse(apiSuffix) + if err != nil { + return &View{}, err + } + + parsedJenkinsURL, err := url.Parse(ensureLastSlash(jenkinsURL)) + if err != nil { + return &View{}, err + } + jenkinsAPIURL := parsedJenkinsURL.ResolveReference(parsedSuffix) + + req, err := http.NewRequest("GET", jenkinsAPIURL.String(), nil) + req.SetBasicAuth(username, apiKey) + + httpClient := &http.Client{} + resp, err := httpClient.Do(req) + + if err != nil { + return &View{}, err + } + + view := &View{} + parseJson(view, resp.Body) + + return view, nil +} + +func ensureLastSlash(URL string) string { + return strings.TrimRight(URL, "/") + "/" +} + +/* -------------------- Unexported Functions -------------------- */ + + +func parseJson(obj interface{}, text io.Reader) { + jsonStream, err := ioutil.ReadAll(text) + if err != nil { + panic(err) + } + + decoder := json.NewDecoder(bytes.NewReader(jsonStream)) + + for { + if err := decoder.Decode(obj); err == io.EOF { + break + } else if err != nil { + panic(err) + } + } +} diff --git a/jenkins/job.go b/jenkins/job.go new file mode 100644 index 00000000..e360e0f6 --- /dev/null +++ b/jenkins/job.go @@ -0,0 +1,8 @@ +package jenkins + +type Job struct { + Class string `json:"_class"` + Name string `json:"name"` + Url string `json:"url"` + Color string `json:"color"` +} diff --git a/jenkins/view.go b/jenkins/view.go new file mode 100644 index 00000000..9041b297 --- /dev/null +++ b/jenkins/view.go @@ -0,0 +1,10 @@ +package jenkins + +type View struct { + Class string `json:"_class"` + Description string `json:"description"` + Jobs []Job `json:"jobs"` + Name string `json:"name"` + Property []string `json:"property"` + url string `json:"url"` +} diff --git a/jenkins/widget.go b/jenkins/widget.go new file mode 100644 index 00000000..a922fbbf --- /dev/null +++ b/jenkins/widget.go @@ -0,0 +1,83 @@ +package jenkins + +import ( + "fmt" + "github.com/olebedev/config" + "github.com/senorprogrammer/wtf/wtf" + "os" +) + +// Config is a pointer to the global config object +var Config *config.Config + +type Widget struct { + wtf.TextWidget +} + +func NewWidget() *Widget { + widget := Widget{ + TextWidget: wtf.NewTextWidget("Jenkins", "jenkins", false), + } + + return &widget +} + +/* -------------------- Exported Functions -------------------- */ + +func (widget *Widget) Refresh() { + if widget.Disabled() { + return + } + + view, err := Create(Config.UString("wtf.mods.jenkins.url"), + Config.UString("wtf.mods.jenkins.user"), os.Getenv("WTF_JENKINS_API_KEY")) + + widget.UpdateRefreshedAt() + widget.View.Clear() + + if err != nil { + widget.View.SetWrap(true) + widget.View.SetTitle(fmt.Sprintf(" %s ", widget.Name)) + fmt.Fprintf(widget.View, "%v", err) + } else { + widget.View.SetWrap(false) + widget.View.SetTitle( + fmt.Sprintf( + " %s: [green] ", + widget.Name, + ), + ) + fmt.Fprintf(widget.View, "%s", widget.contentFrom(view)) + } +} + +/* -------------------- Unexported Functions -------------------- */ + +func (widget *Widget) contentFrom(view *View) string { + str := fmt.Sprintf(" [red]%s[white]\n", view.Name); + + for _, job := range view.Jobs { + str = str + fmt.Sprintf( + " [%s]%-6s[white]\n", + widget.jobColor(&job), + job.Name, + ) + } + + return str +} + +func (widget *Widget) jobColor(job *Job) string { + var color string + + switch job.Color { + case "blue": + color = "green" + case "red": + color = "red" + default: + color = "white" + } + + return color +} diff --git a/wtf.go b/wtf.go index 2c27fb13..5822eb6b 100644 --- a/wtf.go +++ b/wtf.go @@ -23,6 +23,7 @@ import ( "github.com/senorprogrammer/wtf/gspreadsheets" "github.com/senorprogrammer/wtf/help" "github.com/senorprogrammer/wtf/ipinfo" + "github.com/senorprogrammer/wtf/jenkins" "github.com/senorprogrammer/wtf/jira" "github.com/senorprogrammer/wtf/newrelic" "github.com/senorprogrammer/wtf/opsgenie" @@ -191,6 +192,8 @@ func addWidget(app *tview.Application, pages *tview.Pages, widgetName string) { Widgets = append(Widgets, gspreadsheets.NewWidget()) case "ipinfo": Widgets = append(Widgets, ipinfo.NewWidget()) + case "jenkins": + Widgets = append(Widgets, jenkins.NewWidget()) case "jira": Widgets = append(Widgets, jira.NewWidget()) case "newrelic": @@ -232,6 +235,7 @@ func makeWidgets(app *tview.Application, pages *tview.Pages) { github.Config = Config gspreadsheets.Config = Config ipinfo.Config = Config + jenkins.Config = Config jira.Config = Config newrelic.Config = Config opsgenie.Config = Config