Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

job.Invoke() correctly passes parameters and files to Jenkins job #306

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 28 additions & 18 deletions job.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,52 +468,62 @@ func (j *Job) InvokeSimple(ctx context.Context, params map[string]string) (int64
return number, nil
}

func (j *Job) Invoke(ctx context.Context, files []string, skipIfRunning bool, params map[string]string, cause string, securityToken string) (bool, error) {
func (j *Job) Invoke(ctx context.Context, files map[string]string, skipIfRunning bool, params map[string]string, cause string, securityToken string) (int64, error) {
isQueued, err := j.IsQueued(ctx)
if err != nil {
return false, err
return 0, err
}
if isQueued {
Error.Printf("%s is already running", j.GetName())
return false, nil
return 0, nil
}
isRunning, err := j.IsRunning(ctx)
if err != nil {
return false, err
return 0, err
}
if isRunning && skipIfRunning {
return false, fmt.Errorf("Will not request new build because %s is already running", j.GetName())
return 0, 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 {
if params != nil || files != 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(ctx, j.Base+base, bytes.NewBuffer(b), nil, reqParams, files)
paramBytes, _ := json.Marshal(params)
resp, err := j.Jenkins.Requester.PostFiles(ctx, j.Base+base, bytes.NewBuffer(paramBytes), nil, reqParams, files)
if err != nil {
return false, err
return 0, err
}
if resp.StatusCode == 200 || resp.StatusCode == 201 {
return true, nil
if resp.StatusCode != 200 && resp.StatusCode != 201 {
return 0, fmt.Errorf("Could not invoke job %q: %s", j.GetName(), resp.Status)
}
return false, errors.New(strconv.Itoa(resp.StatusCode))

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) Poll(ctx context.Context) (int, error) {
Expand Down
110 changes: 48 additions & 62 deletions request.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,49 @@ func (r *Requester) Post(ctx context.Context, endpoint string, payload io.Reader
return r.Do(ctx, ar, &responseStruct, querystring)
}

func (r *Requester) PostFiles(ctx context.Context, endpoint string, payload io.Reader, responseStruct interface{}, querystring map[string]string, files []string) (*http.Response, error) {
func (r *Requester) PostFiles(ctx context.Context, endpoint string, payload io.Reader, responseStruct interface{}, querystring map[string]string, files map[string]string) (*http.Response, error) {
ar := NewAPIRequest("POST", endpoint, payload)
if err := r.SetCrumb(ctx, ar); err != nil {
return nil, err
}
return r.Do(ctx, ar, &responseStruct, querystring, files)

var err error
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
if files != nil || len(files) != 0 {
for fieldname, fileName := range files {
fileData, err := os.Open(fileName)
if err != nil {
Error.Println(err.Error())
return nil, err
}

part, err := writer.CreateFormFile(fieldname, filepath.Base(fileName))
if err != nil {
Error.Println(err.Error())
return nil, err
}
if _, err = io.Copy(part, fileData); err != nil {
return nil, err
}
defer fileData.Close()
}
}

var params map[string]string
json.NewDecoder(ar.Payload).Decode(&params)
for key, val := range params {
if err = writer.WriteField(key, val); err != nil {
return nil, err
}
}
if err = writer.Close(); err != nil {
return nil, err
}
ar.Payload = body
ar.Headers.Add("Content-Type", writer.FormDataContentType())

return r.Do(ctx, ar, &responseStruct, querystring)
}

func (r *Requester) PostXML(ctx context.Context, endpoint string, xml string, responseStruct interface{}, querystring map[string]string) (*http.Response, error) {
Expand Down Expand Up @@ -146,77 +183,26 @@ 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 map[string]string) (*http.Response, error) {
if !strings.HasSuffix(ar.Endpoint, "/") && ar.Method != "POST" {
ar.Endpoint += "/"
}

fileUpload := false
var files []string
URL, err := url.Parse(r.Base + ar.Endpoint + ar.Suffix)

if err != nil {
return nil, err
}

for _, o := range options {
switch v := o.(type) {
case map[string]string:

querystring := make(url.Values)
for key, val := range v {
querystring.Set(key, val)
}

URL.RawQuery = querystring.Encode()
case []string:
fileUpload = true
files = v
}
querystring := make(url.Values)
for key, val := range options {
querystring.Set(key, val)
}
var req *http.Request

if fileUpload {
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
for _, file := range files {
fileData, err := os.Open(file)
if err != nil {
Error.Println(err.Error())
return nil, err
}
URL.RawQuery = querystring.Encode()

part, err := writer.CreateFormFile("file", filepath.Base(file))
if err != nil {
Error.Println(err.Error())
return nil, err
}
if _, err = io.Copy(part, fileData); err != nil {
return nil, err
}
defer fileData.Close()
}
var params map[string]string
json.NewDecoder(ar.Payload).Decode(&params)
for key, val := range params {
if err = writer.WriteField(key, val); err != nil {
return nil, err
}
}
if err = writer.Close(); err != nil {
return nil, err
}
req, err = http.NewRequestWithContext(ctx, ar.Method, URL.String(), body)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", writer.FormDataContentType())
} else {

req, err = http.NewRequestWithContext(ctx, ar.Method, URL.String(), ar.Payload)
if err != nil {
return nil, err
}
var req *http.Request
req, err = http.NewRequestWithContext(ctx, ar.Method, URL.String(), ar.Payload)
if err != nil {
return nil, err
}

if r.BasicAuth != nil {
Expand Down