代码拉取完成,页面将自动刷新
// Copyright 2015 Vadim Kravcenko
//
// 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 ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package gojenkins
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/url"
"path"
"strconv"
"strings"
)
type Job struct {
Raw *JobResponse
Jenkins *Jenkins
Base string
}
type JobBuild struct {
Number int64
URL string
}
type InnerJob struct {
Class string `json:"_class"`
Name string `json:"name"`
Url string `json:"url"`
Color string `json:"color"`
}
type ParameterDefinition struct {
DefaultParameterValue struct {
Name string `json:"name"`
Value interface{} `json:"value"`
} `json:"defaultParameterValue"`
Description string `json:"description"`
Name string `json:"name"`
Type string `json:"type"`
}
type JobResponse struct {
Class string `json:"_class"`
Actions []generalObj
Buildable bool `json:"buildable"`
Builds []JobBuild
Color string `json:"color"`
ConcurrentBuild bool `json:"concurrentBuild"`
Description string `json:"description"`
DisplayName string `json:"displayName"`
DisplayNameOrNull interface{} `json:"displayNameOrNull"`
DownstreamProjects []InnerJob `json:"downstreamProjects"`
FirstBuild JobBuild
FullName string `json:"fullName"`
FullDisplayName string `json:"fullDisplayName"`
HealthReport []struct {
Description string `json:"description"`
IconClassName string `json:"iconClassName"`
IconUrl string `json:"iconUrl"`
Score int64 `json:"score"`
} `json:"healthReport"`
InQueue bool `json:"inQueue"`
KeepDependencies bool `json:"keepDependencies"`
LastBuild JobBuild `json:"lastBuild"`
LastCompletedBuild JobBuild `json:"lastCompletedBuild"`
LastFailedBuild JobBuild `json:"lastFailedBuild"`
LastStableBuild JobBuild `json:"lastStableBuild"`
LastSuccessfulBuild JobBuild `json:"lastSuccessfulBuild"`
LastUnstableBuild JobBuild `json:"lastUnstableBuild"`
LastUnsuccessfulBuild JobBuild `json:"lastUnsuccessfulBuild"`
Name string `json:"name"`
NextBuildNumber int64 `json:"nextBuildNumber"`
Property []struct {
ParameterDefinitions []ParameterDefinition `json:"parameterDefinitions"`
} `json:"property"`
QueueItem interface{} `json:"queueItem"`
Scm struct{} `json:"scm"`
UpstreamProjects []InnerJob `json:"upstreamProjects"`
URL string `json:"url"`
Jobs []InnerJob `json:"jobs"`
PrimaryView *ViewData `json:"primaryView"`
Views []ViewData `json:"views"`
}
func (j *Job) parentBase() string {
return j.Base[:strings.LastIndex(j.Base, "/job/")]
}
type History struct {
BuildDisplayName string
BuildNumber int
BuildStatus string
BuildTimestamp int64
}
func (j *Job) GetName() string {
return j.Raw.Name
}
func (j *Job) GetDescription() string {
return j.Raw.Description
}
func (j *Job) GetDetails() *JobResponse {
return j.Raw
}
func (j *Job) GetBuild(id int64) (*Build, error) {
// use job embedded URL to properly handle jobs in folders
jobURL := strings.Replace(j.Raw.URL, j.Jenkins.Server, "", -1)
build := Build{Jenkins: j.Jenkins, Job: j, Raw: new(BuildResponse), Depth: 1, Base: jobURL + "/" + strconv.FormatInt(id, 10)}
status, err := build.Poll()
if err != nil {
return nil, err
}
if status == 200 {
return &build, nil
}
return nil, errors.New(strconv.Itoa(status))
}
func (j *Job) getBuildByType(buildType string) (*Build, error) {
allowed := map[string]JobBuild{
"lastStableBuild": j.Raw.LastStableBuild,
"lastSuccessfulBuild": j.Raw.LastSuccessfulBuild,
"lastBuild": j.Raw.LastBuild,
"lastCompletedBuild": j.Raw.LastCompletedBuild,
"firstBuild": j.Raw.FirstBuild,
"lastFailedBuild": j.Raw.LastFailedBuild,
}
number := ""
if val, ok := allowed[buildType]; ok {
number = strconv.FormatInt(val.Number, 10)
} else {
panic("No Such Build")
}
build := Build{
Jenkins: j.Jenkins,
Depth: 1,
Job: j,
Raw: new(BuildResponse),
Base: j.Base + "/" + number}
status, err := build.Poll()
if err != nil {
return nil, err
}
if status == 200 {
return &build, nil
}
return nil, errors.New(strconv.Itoa(status))
}
func (j *Job) GetLastSuccessfulBuild() (*Build, error) {
return j.getBuildByType("lastSuccessfulBuild")
}
func (j *Job) GetFirstBuild() (*Build, error) {
return j.getBuildByType("firstBuild")
}
func (j *Job) GetLastBuild() (*Build, error) {
return j.getBuildByType("lastBuild")
}
func (j *Job) GetLastStableBuild() (*Build, error) {
return j.getBuildByType("lastStableBuild")
}
func (j *Job) GetLastFailedBuild() (*Build, error) {
return j.getBuildByType("lastFailedBuild")
}
func (j *Job) GetLastCompletedBuild() (*Build, error) {
return j.getBuildByType("lastCompletedBuild")
}
// Returns All Builds with Number and URL
func (j *Job) GetAllBuildIds() ([]JobBuild, error) {
var buildsResp struct {
Builds []JobBuild `json:"allBuilds"`
}
_, err := j.Jenkins.Requester.GetJSON(j.Base, &buildsResp, map[string]string{"tree": "allBuilds[number,url]"})
if err != nil {
return nil, err
}
return buildsResp.Builds, nil
}
func (j *Job) GetUpstreamJobsMetadata() []InnerJob {
return j.Raw.UpstreamProjects
}
func (j *Job) GetDownstreamJobsMetadata() []InnerJob {
return j.Raw.DownstreamProjects
}
func (j *Job) GetInnerJobsMetadata() []InnerJob {
return j.Raw.Jobs
}
func (j *Job) GetUpstreamJobs() ([]*Job, error) {
jobs := make([]*Job, len(j.Raw.UpstreamProjects))
for i, job := range j.Raw.UpstreamProjects {
ji, err := j.Jenkins.GetJob(job.Name)
if err != nil {
return nil, err
}
jobs[i] = ji
}
return jobs, nil
}
func (j *Job) GetDownstreamJobs() ([]*Job, error) {
jobs := make([]*Job, len(j.Raw.DownstreamProjects))
for i, job := range j.Raw.DownstreamProjects {
ji, err := j.Jenkins.GetJob(job.Name)
if err != nil {
return nil, err
}
jobs[i] = ji
}
return jobs, nil
}
func (j *Job) GetInnerJob(id string) (*Job, error) {
job := Job{Jenkins: j.Jenkins, Raw: new(JobResponse), Base: j.Base + "/job/" + id}
status, err := job.Poll()
if err != nil {
return nil, err
}
if status == 200 {
return &job, nil
}
return nil, errors.New(strconv.Itoa(status))
}
func (j *Job) GetInnerJobs() ([]*Job, error) {
jobs := make([]*Job, len(j.Raw.Jobs))
for i, job := range j.Raw.Jobs {
ji, err := j.GetInnerJob(job.Name)
if err != nil {
return nil, err
}
jobs[i] = ji
}
return jobs, nil
}
func (j *Job) Enable() (bool, error) {
resp, err := j.Jenkins.Requester.Post(j.Base+"/enable", nil, nil, nil)
if err != nil {
return false, err
}
if resp.StatusCode != 200 {
return false, errors.New(strconv.Itoa(resp.StatusCode))
}
return true, nil
}
func (j *Job) Disable() (bool, error) {
resp, err := j.Jenkins.Requester.Post(j.Base+"/disable", nil, nil, nil)
if err != nil {
return false, err
}
if resp.StatusCode != 200 {
return false, errors.New(strconv.Itoa(resp.StatusCode))
}
return true, nil
}
func (j *Job) Delete() (bool, error) {
resp, err := j.Jenkins.Requester.Post(j.Base+"/doDelete", nil, nil, nil)
if err != nil {
return false, err
}
if resp.StatusCode != 200 {
return false, errors.New(strconv.Itoa(resp.StatusCode))
}
return true, nil
}
func (j *Job) Rename(name string) (bool, error) {
data := url.Values{}
data.Set("newName", name)
_, err := j.Jenkins.Requester.Post(j.Base+"/doRename", bytes.NewBufferString(data.Encode()), nil, nil)
if err != nil {
return false, err
}
return true, nil
}
func (j *Job) Create(config string, qr ...interface{}) (*Job, error) {
var querystring map[string]string
if len(qr) > 0 {
querystring = qr[0].(map[string]string)
}
resp, err := j.Jenkins.Requester.PostXML(j.parentBase()+"/createItem", config, j.Raw, querystring)
if err != nil {
return nil, err
}
if resp.StatusCode == 200 {
j.Poll()
return j, nil
}
return nil, errors.New(strconv.Itoa(resp.StatusCode))
}
func (j *Job) Copy(destinationName string) (*Job, error) {
qr := map[string]string{"name": destinationName, "from": j.GetName(), "mode": "copy"}
resp, err := j.Jenkins.Requester.Post(j.parentBase()+"/createItem", nil, nil, qr)
if err != nil {
return nil, err
}
if resp.StatusCode == 200 {
newJob := &Job{Jenkins: j.Jenkins, Raw: new(JobResponse), Base: "/job/" + destinationName}
_, err := newJob.Poll()
if err != nil {
return nil, err
}
return newJob, nil
}
return nil, errors.New(strconv.Itoa(resp.StatusCode))
}
func (j *Job) UpdateConfig(config string) error {
var querystring map[string]string
resp, err := j.Jenkins.Requester.PostXML(j.Base+"/config.xml", config, nil, querystring)
if err != nil {
return err
}
if resp.StatusCode == 200 {
j.Poll()
return nil
}
return errors.New(strconv.Itoa(resp.StatusCode))
}
func (j *Job) GetConfig() (string, error) {
var data string
_, err := j.Jenkins.Requester.GetXML(j.Base+"/config.xml", &data, nil)
if err != nil {
return "", err
}
return data, nil
}
func (j *Job) GetParameters() ([]ParameterDefinition, error) {
_, err := j.Poll()
if err != nil {
return nil, err
}
var parameters []ParameterDefinition
for _, property := range j.Raw.Property {
parameters = append(parameters, property.ParameterDefinitions...)
}
return parameters, nil
}
func (j *Job) IsQueued() (bool, error) {
if _, err := j.Poll(); err != nil {
return false, err
}
return j.Raw.InQueue, nil
}
func (j *Job) IsRunning() (bool, error) {
if _, err := j.Poll(); err != nil {
return false, err
}
lastBuild, err := j.GetLastBuild()
if err != nil {
return false, err
}
return lastBuild.IsRunning(), nil
}
func (j *Job) IsEnabled() (bool, error) {
if _, err := j.Poll(); err != nil {
return false, err
}
return j.Raw.Color != "disabled", nil
}
func (j *Job) HasQueuedBuild() {
panic("Not Implemented yet")
}
func (j *Job) InvokeSimple(params map[string]string) (int64, error) {
isQueued, err := j.IsQueued()
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()
if err != nil {
return 0, err
}
if len(parameters) > 0 {
endpoint = "/buildWithParameters"
}
data := url.Values{}
for k, v := range params {
data.Set(k, v)
}
resp, err := j.Jenkins.Requester.Post(j.Base+endpoint, bytes.NewBufferString(data.Encode()), nil, nil)
if err != nil {
return 0, err
}
if resp.StatusCode != 200 && resp.StatusCode != 201 {
return 0, fmt.Errorf("Could not invoke job %q: %s", j.GetName(), resp.Status)
}
location := resp.Header.Get("Location")
if location == "" {
return 0, errors.New("Don't have key \"Location\" in response of header")
}
u, err := url.Parse(location)
if err != nil {
return 0, err
}
number, err := strconv.ParseInt(path.Base(u.Path), 10, 64)
if err != nil {
return 0, err
}
return number, nil
}
func (j *Job) Invoke(files []string, skipIfRunning bool, params map[string]string, cause string, securityToken string) (bool, error) {
isQueued, err := j.IsQueued()
if err != nil {
return false, err
}
if isQueued {
Error.Printf("%s is already running", j.GetName())
return false, nil
}
isRunning, err := j.IsRunning()
if err != nil {
return false, err
}
if isRunning && skipIfRunning {
return false, fmt.Errorf("Will not request new build because %s is already running", j.GetName())
}
base := "/build"
// If parameters are specified - url is /builWithParameters
if params != nil {
base = "/buildWithParameters"
} else {
params = make(map[string]string)
}
// If files are specified - url is /build
if files != nil {
base = "/build"
}
reqParams := map[string]string{}
buildParams := map[string]string{}
if securityToken != "" {
reqParams["token"] = securityToken
}
buildParams["json"] = string(makeJson(params))
b, _ := json.Marshal(buildParams)
resp, err := j.Jenkins.Requester.PostFiles(j.Base+base, bytes.NewBuffer(b), nil, reqParams, files)
if err != nil {
return false, err
}
if resp.StatusCode == 200 || resp.StatusCode == 201 {
return true, nil
}
return false, errors.New(strconv.Itoa(resp.StatusCode))
}
func (j *Job) Poll() (int, error) {
response, err := j.Jenkins.Requester.GetJSON(j.Base, j.Raw, nil)
if err != nil {
return 0, err
}
return response.StatusCode, nil
}
func (j *Job) History() ([]*History, error) {
var s string
_, err := j.Jenkins.Requester.Get(j.Base+"/buildHistory/ajax", &s, nil)
if err != nil {
return nil, err
}
return parseBuildHistory(strings.NewReader(s)), nil
}
func (pr *PipelineRun) ProceedInput() (bool, error) {
actions, _ := pr.GetPendingInputActions()
data := url.Values{}
data.Set("inputId", actions[0].ID)
params := make(map[string]string)
data.Set("json", makeJson(params))
href := pr.Base + "/wfapi/inputSubmit"
resp, err := pr.Job.Jenkins.Requester.Post(href, bytes.NewBufferString(data.Encode()), nil, nil)
if err != nil {
return false, err
}
if resp.StatusCode != 200 {
return false, errors.New(strconv.Itoa(resp.StatusCode))
}
return true, nil
}
func (pr *PipelineRun) AbortInput() (bool, error) {
actions, _ := pr.GetPendingInputActions()
data := url.Values{}
params := make(map[string]string)
data.Set("json", makeJson(params))
href := pr.Base + "/input/" + actions[0].ID + "/abort"
resp, err := pr.Job.Jenkins.Requester.Post(href, bytes.NewBufferString(data.Encode()), nil, nil)
if err != nil {
return false, err
}
if resp.StatusCode != 200 {
return false, errors.New(strconv.Itoa(resp.StatusCode))
}
return true, nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。