devops.go 26.5 KB
Newer Older
S
sunzhu 已提交
1
/*
S
shaowenchen 已提交
2
Copyright 2020 The KubeSphere Authors.
S
sunzhu 已提交
3

S
shaowenchen 已提交
4 5 6
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
S
sunzhu 已提交
7

S
shaowenchen 已提交
8
    http://www.apache.org/licenses/LICENSE-2.0
S
sunzhu 已提交
9

S
shaowenchen 已提交
10 11 12 13 14
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.
R
update  
runzexia 已提交
15
*/
S
shaowenchen 已提交
16

R
runzexia 已提交
17
package v1alpha2
S
sunzhu 已提交
18 19

import (
20 21 22
	"encoding/json"
	"errors"
	"fmt"
S
shaowenchen 已提交
23 24 25
	"net/http"
	"strings"

S
sunzhu 已提交
26
	"github.com/emicklei/go-restful"
27
	"k8s.io/apiserver/pkg/authentication/user"
J
Jeff 已提交
28
	log "k8s.io/klog"
29
	"k8s.io/klog/v2"
R
runzexia 已提交
30
	"kubesphere.io/kubesphere/pkg/api"
31
	"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3"
32
	"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
33
	"kubesphere.io/kubesphere/pkg/apiserver/request"
34
	"kubesphere.io/kubesphere/pkg/constants"
S
sunzhu 已提交
35
	"kubesphere.io/kubesphere/pkg/models/devops"
LinuxSuRen's avatar
LinuxSuRen 已提交
36
	"kubesphere.io/kubesphere/pkg/server/params"
37
	clientDevOps "kubesphere.io/kubesphere/pkg/simple/client/devops"
LinuxSuRen's avatar
LinuxSuRen 已提交
38
	"kubesphere.io/kubesphere/pkg/simple/client/devops/jenkins"
S
sunzhu 已提交
39 40
)

S
soulseen 已提交
41
const jenkinsHeaderPre = "X-"
S
soulseen 已提交
42

R
runzexia 已提交
43
func (h *ProjectPipelineHandler) GetPipeline(req *restful.Request, resp *restful.Response) {
R
runzexia 已提交
44
	projectName := req.PathParameter("devops")
45
	pipelineName := req.PathParameter("pipeline")
S
sunzhu 已提交
46

R
runzexia 已提交
47
	res, err := h.devopsOperator.GetPipeline(projectName, pipelineName, req.Request)
S
sunzhu 已提交
48 49 50 51 52
	if err != nil {
		parseErr(err, resp)
		return
	}

53
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
54
	resp.WriteAsJson(res)
S
sunzhu 已提交
55 56
}

57 58 59
func (h *ProjectPipelineHandler) getPipelinesByRequest(req *restful.Request) (api.ListResult, error) {
	// this is a very trick way, but don't have a better solution for now
	var (
LinuxSuRen's avatar
LinuxSuRen 已提交
60 61 62 63
		start      int
		limit      int
		namespace  string
		nameFilter string
64 65 66 67 68 69
	)

	// parse query from the request
	query := req.QueryParameter("q")
	for _, val := range strings.Split(query, ";") {
		if strings.HasPrefix(val, "pipeline:") {
LinuxSuRen's avatar
LinuxSuRen 已提交
70 71 72 73 74 75 76 77 78 79
			nsAndName := strings.TrimLeft(val, "pipeline:")
			filterMeta := strings.Split(nsAndName, "/")
			if len(filterMeta) >= 2 {
				namespace = filterMeta[0]
				nameFilter = filterMeta[1] // the format is '*keyword*'
				nameFilter = strings.TrimSuffix(nameFilter, "*")
				nameFilter = strings.TrimPrefix(nameFilter, "*")
			} else if len(filterMeta) > 0 {
				namespace = filterMeta[0]
			}
80 81 82
		}
	}

LinuxSuRen's avatar
LinuxSuRen 已提交
83 84
	pipelineFilter := func(pipeline *v1alpha3.Pipeline) bool {
		return strings.Contains(pipeline.Name, nameFilter)
85
	}
LinuxSuRen's avatar
LinuxSuRen 已提交
86 87
	if nameFilter == "" {
		pipelineFilter = nil
88 89
	}

LinuxSuRen's avatar
LinuxSuRen 已提交
90 91 92
	// make sure we have an appropriate value
	limit, start = params.ParsePaging(req)
	return h.devopsOperator.ListPipelineObj(namespace, pipelineFilter, func(list []*v1alpha3.Pipeline, i int, j int) bool {
93
		return strings.Compare(strings.ToUpper(list[i].Name), strings.ToUpper(list[j].Name)) < 0
94 95 96
	}, limit, start)
}

R
runzexia 已提交
97
func (h *ProjectPipelineHandler) ListPipelines(req *restful.Request, resp *restful.Response) {
98
	objs, err := h.getPipelinesByRequest(req)
S
sunzhu 已提交
99 100 101 102 103
	if err != nil {
		parseErr(err, resp)
		return
	}

104 105 106
	// get all pipelines which come from ks
	pipelineList := &clientDevOps.PipelineList{
		Total: objs.TotalItems,
107
		Items: make([]clientDevOps.Pipeline, len(objs.Items)),
108
	}
LinuxSuRen's avatar
LinuxSuRen 已提交
109 110 111 112 113 114 115
	pipelineMap := make(map[string]int, pipelineList.Total)
	for i, _ := range objs.Items {
		if pipeline, ok := objs.Items[i].(v1alpha3.Pipeline); !ok {
			continue
		} else {
			pipelineMap[pipeline.Name] = i
			pipelineList.Items[i] = clientDevOps.Pipeline{
116 117
				Name:        pipeline.Name,
				Annotations: pipeline.Annotations,
118 119
			}
		}
LinuxSuRen's avatar
LinuxSuRen 已提交
120
	}
121

LinuxSuRen's avatar
LinuxSuRen 已提交
122 123 124 125 126 127 128 129 130 131 132 133 134
	// get all pipelines which come from Jenkins
	// fill out the rest fields
	if query, err := jenkins.ParseJenkinsQuery(req.Request.URL.RawQuery); err == nil {
		query.Set("limit", "10000")
		query.Set("start", "0")
		req.Request.URL.RawQuery = query.Encode()
	}
	res, err := h.devopsOperator.ListPipelines(req.Request)
	if err != nil {
		log.Error(err)
	} else {
		for i, _ := range res.Items {
			if index, ok := pipelineMap[res.Items[i].Name]; ok {
S
shaowenchen 已提交
135 136
				// keep annotations field of pipelineList
				annotations := pipelineList.Items[index].Annotations
LinuxSuRen's avatar
LinuxSuRen 已提交
137
				pipelineList.Items[index] = res.Items[i]
S
shaowenchen 已提交
138
				pipelineList.Items[index].Annotations = annotations
139 140 141 142
			}
		}
	}

Z
Zhuxiaoyang 已提交
143
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
144
	resp.WriteAsJson(pipelineList)
S
sunzhu 已提交
145 146
}

R
runzexia 已提交
147
func (h *ProjectPipelineHandler) GetPipelineRun(req *restful.Request, resp *restful.Response) {
148 149
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
R
runzexia 已提交
150
	runId := req.PathParameter("run")
S
sunzhu 已提交
151

R
runzexia 已提交
152
	res, err := h.devopsOperator.GetPipelineRun(projectName, pipelineName, runId, req.Request)
S
sunzhu 已提交
153 154 155 156 157
	if err != nil {
		parseErr(err, resp)
		return
	}

Z
Zhuxiaoyang 已提交
158
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
159
	resp.WriteAsJson(res)
S
sunzhu 已提交
160 161
}

R
runzexia 已提交
162
func (h *ProjectPipelineHandler) ListPipelineRuns(req *restful.Request, resp *restful.Response) {
163 164
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
S
sunzhu 已提交
165

R
runzexia 已提交
166
	res, err := h.devopsOperator.ListPipelineRuns(projectName, pipelineName, req.Request)
S
sunzhu 已提交
167 168 169 170 171
	if err != nil {
		parseErr(err, resp)
		return
	}

Z
Zhuxiaoyang 已提交
172
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
173
	resp.WriteAsJson(res)
S
sunzhu 已提交
174 175
}

R
runzexia 已提交
176
func (h *ProjectPipelineHandler) StopPipeline(req *restful.Request, resp *restful.Response) {
177 178 179
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
	runId := req.PathParameter("run")
S
sunzhu 已提交
180

R
runzexia 已提交
181
	res, err := h.devopsOperator.StopPipeline(projectName, pipelineName, runId, req.Request)
S
sunzhu 已提交
182 183 184 185 186
	if err != nil {
		parseErr(err, resp)
		return
	}

Z
Zhuxiaoyang 已提交
187
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
188
	resp.WriteAsJson(res)
S
sunzhu 已提交
189 190
}

R
runzexia 已提交
191
func (h *ProjectPipelineHandler) ReplayPipeline(req *restful.Request, resp *restful.Response) {
192 193 194
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
	runId := req.PathParameter("run")
S
soulseen 已提交
195

R
runzexia 已提交
196
	res, err := h.devopsOperator.ReplayPipeline(projectName, pipelineName, runId, req.Request)
Z
Zhuxiaoyang 已提交
197 198 199 200
	if err != nil {
		parseErr(err, resp)
		return
	}
R
runzexia 已提交
201 202 203

	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
204 205
}

R
runzexia 已提交
206
func (h *ProjectPipelineHandler) RunPipeline(req *restful.Request, resp *restful.Response) {
207 208
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
Z
Zhuxiaoyang 已提交
209

R
runzexia 已提交
210
	res, err := h.devopsOperator.RunPipeline(projectName, pipelineName, req.Request)
S
sunzhu 已提交
211 212 213 214
	if err != nil {
		parseErr(err, resp)
		return
	}
R
runzexia 已提交
215 216 217

	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
	resp.WriteAsJson(res)
S
soulseen 已提交
218 219
}

R
runzexia 已提交
220 221 222 223
func (h *ProjectPipelineHandler) GetArtifacts(req *restful.Request, resp *restful.Response) {
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
	runId := req.PathParameter("run")
224

R
runzexia 已提交
225
	res, err := h.devopsOperator.GetArtifacts(projectName, pipelineName, runId, req.Request)
226 227 228 229 230
	if err != nil {
		parseErr(err, resp)
		return
	}
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
231
	resp.WriteAsJson(res)
232 233
}

R
runzexia 已提交
234 235 236 237
func (h *ProjectPipelineHandler) GetRunLog(req *restful.Request, resp *restful.Response) {
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
	runId := req.PathParameter("run")
238

R
runzexia 已提交
239
	res, err := h.devopsOperator.GetRunLog(projectName, pipelineName, runId, req.Request)
240 241 242 243 244 245 246 247
	if err != nil {
		parseErr(err, resp)
		return
	}

	resp.Write(res)
}

R
runzexia 已提交
248 249 250 251 252 253
func (h *ProjectPipelineHandler) GetStepLog(req *restful.Request, resp *restful.Response) {
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
	runId := req.PathParameter("run")
	nodeId := req.PathParameter("node")
	stepId := req.PathParameter("step")
S
soulseen 已提交
254

R
runzexia 已提交
255
	res, header, err := h.devopsOperator.GetStepLog(projectName, pipelineName, runId, nodeId, stepId, req.Request)
S
soulseen 已提交
256
	if err != nil {
R
runzexia 已提交
257
		parseErr(err, resp)
S
soulseen 已提交
258 259
		return
	}
R
runzexia 已提交
260 261 262 263 264
	for k, v := range header {
		if strings.HasPrefix(k, jenkinsHeaderPre) {
			resp.AddHeader(k, v[0])
		}
	}
Z
Zhuxiaoyang 已提交
265
	resp.Write(res)
S
soulseen 已提交
266 267
}

R
runzexia 已提交
268 269 270 271 272
func (h *ProjectPipelineHandler) GetNodeSteps(req *restful.Request, resp *restful.Response) {
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
	runId := req.PathParameter("run")
	nodeId := req.PathParameter("node")
S
soulseen 已提交
273

R
runzexia 已提交
274
	res, err := h.devopsOperator.GetNodeSteps(projectName, pipelineName, runId, nodeId, req.Request)
Z
Zhuxiaoyang 已提交
275 276 277 278
	if err != nil {
		parseErr(err, resp)
		return
	}
Z
Zhuxiaoyang 已提交
279
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
280
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
281 282
}

R
runzexia 已提交
283 284 285 286
func (h *ProjectPipelineHandler) GetPipelineRunNodes(req *restful.Request, resp *restful.Response) {
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
	runId := req.PathParameter("run")
Z
Zhuxiaoyang 已提交
287

R
runzexia 已提交
288
	res, err := h.devopsOperator.GetPipelineRunNodes(projectName, pipelineName, runId, req.Request)
Z
Zhuxiaoyang 已提交
289 290 291 292
	if err != nil {
		parseErr(err, resp)
		return
	}
Z
Zhuxiaoyang 已提交
293
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
294
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
295 296
}

297 298 299 300 301 302 303 304 305
// there're two situation here:
// 1. the particular submitters exist
// the users who are the owner of this Pipeline or the submitter of this Pipeline, or has the auth to create a DevOps project
// 2. no particular submitters
// only the owner of this Pipeline can approve or reject it
func (h *ProjectPipelineHandler) approvableCheck(nodes []clientDevOps.NodesDetail, pipe pipelineParam) {
	var userInfo user.Info
	var ok bool
	var isAdmin bool
306
	// check if current user belong to the admin group, grant it if it's true
307 308 309
	if userInfo, ok = request.UserFrom(pipe.Context); ok {
		createAuth := authorizer.AttributesRecord{
			User:            userInfo,
310
			Verb:            authorizer.VerbDelete,
311
			Workspace:       pipe.Workspace,
312
			DevOps:          pipe.ProjectName,
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
			Resource:        "devopsprojects",
			ResourceRequest: true,
			ResourceScope:   request.DevOpsScope,
		}

		if decision, _, err := h.authorizer.Authorize(createAuth); err == nil {
			isAdmin = decision == authorizer.DecisionAllow
		} else {
			// this is an expected case, printing the debug info for troubleshooting
			klog.V(8).Infof("authorize failed with '%v', error is '%v'",
				createAuth, err)
		}
	} else {
		klog.V(6).Infof("cannot get the current user when checking the approvable with pipeline '%s/%s'",
			pipe.ProjectName, pipe.Name)
		return
	}
330

331 332 333 334 335 336 337 338 339 340 341 342 343 344
	var createdByCurrentUser bool // indicate if the current user is the owner
	if pipeline, err := h.devopsOperator.GetPipelineObj(pipe.ProjectName, pipe.Name); err == nil {
		if creator, ok := pipeline.GetAnnotations()[constants.CreatorAnnotationKey]; ok {
			createdByCurrentUser = userInfo.GetName() == creator
		} else {
			klog.V(6).Infof("annotation '%s' is necessary but it is missing from '%s/%s'",
				constants.CreatorAnnotationKey, pipe.ProjectName, pipe.Name)
		}
	} else {
		klog.V(6).Infof("cannot find pipeline '%s/%s', error is '%v'", pipe.ProjectName, pipe.Name, err)
		return
	}

	// check every input steps if it's approvable
345 346 347 348 349 350 351 352 353 354
	for i, node := range nodes {
		if node.State != clientDevOps.StatePaused {
			continue
		}

		for j, step := range node.Steps {
			if step.State != clientDevOps.StatePaused || step.Input == nil {
				continue
			}

355
			nodes[i].Steps[j].Approvable = isAdmin || createdByCurrentUser || step.Input.Approvable(userInfo.GetName())
356 357 358 359
		}
	}
}

360 361 362 363 364 365
func (h *ProjectPipelineHandler) createdBy(projectName string, pipelineName string, currentUserName string) bool {
	if pipeline, err := h.devopsOperator.GetPipelineObj(projectName, pipelineName); err == nil {
		if creator, ok := pipeline.Annotations[constants.CreatorAnnotationKey]; ok {
			return creator == currentUserName
		}
	} else {
366
		log.V(4).Infof("cannot get pipeline %s/%s, error %#v", projectName, pipelineName, err)
367 368 369 370
	}
	return false
}

371
func (h *ProjectPipelineHandler) hasSubmitPermission(req *restful.Request) (hasPermit bool, err error) {
372
	pipeParam := parsePipelineParam(req)
373 374 375 376 377 378 379
	httpReq := &http.Request{
		URL:      req.Request.URL,
		Header:   req.Request.Header,
		Form:     req.Request.Form,
		PostForm: req.Request.PostForm,
	}

380
	runId := req.PathParameter("run")
R
runzexia 已提交
381 382
	nodeId := req.PathParameter("node")
	stepId := req.PathParameter("step")
383
	branchName := req.PathParameter("branch")
Z
Zhuxiaoyang 已提交
384

385
	// check if current user can approve this input
386
	var res []clientDevOps.NodesDetail
387 388 389 390 391 392 393 394

	if branchName == "" {
		res, err = h.devopsOperator.GetNodesDetail(pipeParam.ProjectName, pipeParam.Name, runId, httpReq)
	} else {
		res, err = h.devopsOperator.GetBranchNodesDetail(pipeParam.ProjectName, pipeParam.Name, branchName, runId, httpReq)
	}

	if err == nil {
395 396
		h.approvableCheck(res, parsePipelineParam(req))

397 398 399 400 401 402 403 404 405 406
		for _, node := range res {
			if node.ID != nodeId {
				continue
			}

			for _, step := range node.Steps {
				if step.ID != stepId || step.Input == nil {
					continue
				}

407
				hasPermit = step.Approvable
408 409 410 411 412
				break
			}
			break
		}
	} else {
413
		log.V(4).Infof("cannot get nodes detail, error: %v", err)
414
		err = errors.New("cannot get the submitters of current pipeline run")
Z
Zhuxiaoyang 已提交
415 416
		return
	}
417 418 419 420 421 422 423 424 425 426
	return
}

func (h *ProjectPipelineHandler) SubmitInputStep(req *restful.Request, resp *restful.Response) {
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
	runId := req.PathParameter("run")
	nodeId := req.PathParameter("node")
	stepId := req.PathParameter("step")

427 428 429
	var response []byte
	var err error
	var ok bool
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445

	if ok, err = h.hasSubmitPermission(req); !ok || err != nil {
		msg := map[string]string{
			"allow":   "false",
			"message": fmt.Sprintf("%v", err),
		}

		response, _ = json.Marshal(msg)
	} else {
		response, err = h.devopsOperator.SubmitInputStep(projectName, pipelineName, runId, nodeId, stepId, req.Request)
		if err != nil {
			parseErr(err, resp)
			return
		}
	}
	resp.Write(response)
Z
Zhuxiaoyang 已提交
446 447
}

R
runzexia 已提交
448
func (h *ProjectPipelineHandler) GetNodesDetail(req *restful.Request, resp *restful.Response) {
449 450 451
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
	runId := req.PathParameter("run")
Z
Zhuxiaoyang 已提交
452

R
runzexia 已提交
453
	res, err := h.devopsOperator.GetNodesDetail(projectName, pipelineName, runId, req.Request)
Z
Zhuxiaoyang 已提交
454 455 456 457
	if err != nil {
		parseErr(err, resp)
		return
	}
458
	h.approvableCheck(res, parsePipelineParam(req))
459

R
runzexia 已提交
460
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
461 462
}

R
runzexia 已提交
463
func (h *ProjectPipelineHandler) GetBranchPipeline(req *restful.Request, resp *restful.Response) {
464 465 466
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
	branchName := req.PathParameter("branch")
Z
Zhuxiaoyang 已提交
467

R
runzexia 已提交
468
	res, err := h.devopsOperator.GetBranchPipeline(projectName, pipelineName, branchName, req.Request)
Z
Zhuxiaoyang 已提交
469 470 471 472 473
	if err != nil {
		parseErr(err, resp)
		return
	}

Z
Zhuxiaoyang 已提交
474
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
475
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
476 477
}

R
runzexia 已提交
478
func (h *ProjectPipelineHandler) GetBranchPipelineRun(req *restful.Request, resp *restful.Response) {
479 480
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
R
runzexia 已提交
481
	branchName := req.PathParameter("branch")
482
	runId := req.PathParameter("run")
Z
Zhuxiaoyang 已提交
483

R
runzexia 已提交
484
	res, err := h.devopsOperator.GetBranchPipelineRun(projectName, pipelineName, branchName, runId, req.Request)
Z
Zhuxiaoyang 已提交
485 486 487 488 489
	if err != nil {
		parseErr(err, resp)
		return
	}

Z
Zhuxiaoyang 已提交
490
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
491
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
492 493
}

R
runzexia 已提交
494
func (h *ProjectPipelineHandler) StopBranchPipeline(req *restful.Request, resp *restful.Response) {
495 496 497 498
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
	branchName := req.PathParameter("branch")
	runId := req.PathParameter("run")
Z
Zhuxiaoyang 已提交
499

R
runzexia 已提交
500
	res, err := h.devopsOperator.StopBranchPipeline(projectName, pipelineName, branchName, runId, req.Request)
Z
Zhuxiaoyang 已提交
501 502 503 504 505
	if err != nil {
		parseErr(err, resp)
		return
	}

R
runzexia 已提交
506 507
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
508 509
}

R
runzexia 已提交
510
func (h *ProjectPipelineHandler) ReplayBranchPipeline(req *restful.Request, resp *restful.Response) {
511 512
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
R
runzexia 已提交
513
	branchName := req.PathParameter("branch")
514
	runId := req.PathParameter("run")
Z
Zhuxiaoyang 已提交
515

R
runzexia 已提交
516
	res, err := h.devopsOperator.ReplayBranchPipeline(projectName, pipelineName, branchName, runId, req.Request)
Z
Zhuxiaoyang 已提交
517 518 519 520 521
	if err != nil {
		parseErr(err, resp)
		return
	}

R
runzexia 已提交
522 523
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
524 525
}

R
runzexia 已提交
526
func (h *ProjectPipelineHandler) RunBranchPipeline(req *restful.Request, resp *restful.Response) {
527 528 529
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
	branchName := req.PathParameter("branch")
Z
Zhuxiaoyang 已提交
530

R
runzexia 已提交
531
	res, err := h.devopsOperator.RunBranchPipeline(projectName, pipelineName, branchName, req.Request)
Z
Zhuxiaoyang 已提交
532 533 534 535
	if err != nil {
		parseErr(err, resp)
		return
	}
R
runzexia 已提交
536

Z
Zhuxiaoyang 已提交
537
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
538
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
539 540
}

R
runzexia 已提交
541
func (h *ProjectPipelineHandler) GetBranchArtifacts(req *restful.Request, resp *restful.Response) {
542 543
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
R
runzexia 已提交
544
	branchName := req.PathParameter("branch")
545
	runId := req.PathParameter("run")
Z
Zhuxiaoyang 已提交
546

R
runzexia 已提交
547
	res, err := h.devopsOperator.GetBranchArtifacts(projectName, pipelineName, branchName, runId, req.Request)
Z
Zhuxiaoyang 已提交
548 549 550 551
	if err != nil {
		parseErr(err, resp)
		return
	}
Z
Zhuxiaoyang 已提交
552
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
553
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
554 555
}

R
runzexia 已提交
556
func (h *ProjectPipelineHandler) GetBranchRunLog(req *restful.Request, resp *restful.Response) {
557 558
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
R
runzexia 已提交
559 560
	branchName := req.PathParameter("branch")
	runId := req.PathParameter("run")
Z
Zhuxiaoyang 已提交
561

R
runzexia 已提交
562
	res, err := h.devopsOperator.GetBranchRunLog(projectName, pipelineName, branchName, runId, req.Request)
Z
Zhuxiaoyang 已提交
563 564 565 566
	if err != nil {
		parseErr(err, resp)
		return
	}
R
runzexia 已提交
567

Z
Zhuxiaoyang 已提交
568
	resp.Write(res)
Z
Zhuxiaoyang 已提交
569 570
}

R
runzexia 已提交
571
func (h *ProjectPipelineHandler) GetBranchStepLog(req *restful.Request, resp *restful.Response) {
572 573 574 575 576 577
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
	branchName := req.PathParameter("branch")
	runId := req.PathParameter("run")
	nodeId := req.PathParameter("node")
	stepId := req.PathParameter("step")
Z
Zhuxiaoyang 已提交
578

R
runzexia 已提交
579 580
	res, header, err := h.devopsOperator.GetBranchStepLog(projectName, pipelineName, branchName, runId, nodeId, stepId, req.Request)

Z
Zhuxiaoyang 已提交
581 582 583 584
	if err != nil {
		parseErr(err, resp)
		return
	}
R
runzexia 已提交
585 586 587 588 589
	for k, v := range header {
		if strings.HasPrefix(k, jenkinsHeaderPre) {
			resp.AddHeader(k, v[0])
		}
	}
Z
Zhuxiaoyang 已提交
590 591 592
	resp.Write(res)
}

R
runzexia 已提交
593
func (h *ProjectPipelineHandler) GetBranchNodeSteps(req *restful.Request, resp *restful.Response) {
594 595
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
R
runzexia 已提交
596
	branchName := req.PathParameter("branch")
597 598
	runId := req.PathParameter("run")
	nodeId := req.PathParameter("node")
Z
Zhuxiaoyang 已提交
599

R
runzexia 已提交
600
	res, err := h.devopsOperator.GetBranchNodeSteps(projectName, pipelineName, branchName, runId, nodeId, req.Request)
Z
Zhuxiaoyang 已提交
601 602 603 604
	if err != nil {
		parseErr(err, resp)
		return
	}
R
runzexia 已提交
605 606
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
607 608
}

R
runzexia 已提交
609
func (h *ProjectPipelineHandler) GetBranchPipelineRunNodes(req *restful.Request, resp *restful.Response) {
610 611
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
R
runzexia 已提交
612 613
	branchName := req.PathParameter("branch")
	runId := req.PathParameter("run")
Z
Zhuxiaoyang 已提交
614

R
runzexia 已提交
615
	res, err := h.devopsOperator.GetBranchPipelineRunNodes(projectName, pipelineName, branchName, runId, req.Request)
Z
Zhuxiaoyang 已提交
616 617 618 619 620
	if err != nil {
		parseErr(err, resp)
		return
	}

R
runzexia 已提交
621 622
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
623 624
}

R
runzexia 已提交
625
func (h *ProjectPipelineHandler) SubmitBranchInputStep(req *restful.Request, resp *restful.Response) {
626 627
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
R
runzexia 已提交
628 629 630 631
	branchName := req.PathParameter("branch")
	runId := req.PathParameter("run")
	nodeId := req.PathParameter("node")
	stepId := req.PathParameter("step")
Z
Zhuxiaoyang 已提交
632

633 634 635
	var response []byte
	var err error
	var ok bool
636

637 638 639 640
	if ok, err = h.hasSubmitPermission(req); !ok || err != nil {
		msg := map[string]string{
			"allow":   "false",
			"message": fmt.Sprintf("%v", err),
641 642
		}

643 644 645 646 647 648 649
		response, _ = json.Marshal(msg)
	} else {
		response, err = h.devopsOperator.SubmitBranchInputStep(projectName, pipelineName, branchName, runId, nodeId, stepId, req.Request)
		if err != nil {
			parseErr(err, resp)
			return
		}
Z
Zhuxiaoyang 已提交
650 651
	}

652
	resp.Write(response)
Z
Zhuxiaoyang 已提交
653 654
}

R
runzexia 已提交
655
func (h *ProjectPipelineHandler) GetBranchNodesDetail(req *restful.Request, resp *restful.Response) {
656 657 658
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
	branchName := req.PathParameter("branch")
R
runzexia 已提交
659
	runId := req.PathParameter("run")
Z
Zhuxiaoyang 已提交
660

R
runzexia 已提交
661
	res, err := h.devopsOperator.GetBranchNodesDetail(projectName, pipelineName, branchName, runId, req.Request)
Z
Zhuxiaoyang 已提交
662 663 664 665
	if err != nil {
		parseErr(err, resp)
		return
	}
666
	h.approvableCheck(res, parsePipelineParam(req))
R
runzexia 已提交
667
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
668 669
}

670 671 672 673 674 675 676 677 678
func parsePipelineParam(req *restful.Request) pipelineParam {
	return pipelineParam{
		Workspace:   req.PathParameter("workspace"),
		ProjectName: req.PathParameter("devops"),
		Name:        req.PathParameter("pipeline"),
		Context:     req.Request.Context(),
	}
}

R
runzexia 已提交
679
func (h *ProjectPipelineHandler) GetPipelineBranch(req *restful.Request, resp *restful.Response) {
680 681
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")
Z
Zhuxiaoyang 已提交
682

R
runzexia 已提交
683
	res, err := h.devopsOperator.GetPipelineBranch(projectName, pipelineName, req.Request)
Z
Zhuxiaoyang 已提交
684 685 686 687
	if err != nil {
		parseErr(err, resp)
		return
	}
Z
Zhuxiaoyang 已提交
688
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
689
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
690 691
}

R
runzexia 已提交
692 693 694 695 696
func (h *ProjectPipelineHandler) ScanBranch(req *restful.Request, resp *restful.Response) {
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")

	res, err := h.devopsOperator.ScanBranch(projectName, pipelineName, req.Request)
S
soulseen 已提交
697 698 699 700 701
	if err != nil {
		parseErr(err, resp)
		return
	}

Z
Zhuxiaoyang 已提交
702 703 704
	resp.Write(res)
}

R
runzexia 已提交
705
func (h *ProjectPipelineHandler) GetConsoleLog(req *restful.Request, resp *restful.Response) {
706 707 708
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")

R
runzexia 已提交
709
	res, err := h.devopsOperator.GetConsoleLog(projectName, pipelineName, req.Request)
Z
Zhuxiaoyang 已提交
710 711 712 713 714
	if err != nil {
		parseErr(err, resp)
		return
	}

R
runzexia 已提交
715
	resp.Write(res)
Z
Zhuxiaoyang 已提交
716 717
}

R
runzexia 已提交
718 719
func (h *ProjectPipelineHandler) GetCrumb(req *restful.Request, resp *restful.Response) {
	res, err := h.devopsOperator.GetCrumb(req.Request)
Z
Zhuxiaoyang 已提交
720 721 722 723 724
	if err != nil {
		parseErr(err, resp)
		return
	}

Z
Zhuxiaoyang 已提交
725
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
Z
Zhuxiaoyang 已提交
726 727 728
	resp.WriteAsJson(res)
}

R
runzexia 已提交
729 730
func (h *ProjectPipelineHandler) GetSCMServers(req *restful.Request, resp *restful.Response) {
	scmId := req.PathParameter("scm")
Z
Zhuxiaoyang 已提交
731

R
runzexia 已提交
732
	res, err := h.devopsOperator.GetSCMServers(scmId, req.Request)
Z
Zhuxiaoyang 已提交
733 734 735 736 737
	if err != nil {
		parseErr(err, resp)
		return
	}

Z
Zhuxiaoyang 已提交
738
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
739
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
740 741
}

R
runzexia 已提交
742 743
func (h *ProjectPipelineHandler) GetSCMOrg(req *restful.Request, resp *restful.Response) {
	scmId := req.PathParameter("scm")
Z
Zhuxiaoyang 已提交
744

R
runzexia 已提交
745
	res, err := h.devopsOperator.GetSCMOrg(scmId, req.Request)
Z
Zhuxiaoyang 已提交
746 747 748 749 750
	if err != nil {
		parseErr(err, resp)
		return
	}

Z
Zhuxiaoyang 已提交
751
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
752
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
753 754
}

R
runzexia 已提交
755 756 757
func (h *ProjectPipelineHandler) GetOrgRepo(req *restful.Request, resp *restful.Response) {
	scmId := req.PathParameter("scm")
	organizationId := req.PathParameter("organization")
Z
Zhuxiaoyang 已提交
758

R
runzexia 已提交
759
	res, err := h.devopsOperator.GetOrgRepo(scmId, organizationId, req.Request)
Z
Zhuxiaoyang 已提交
760 761 762 763
	if err != nil {
		parseErr(err, resp)
		return
	}
R
runzexia 已提交
764

Z
Zhuxiaoyang 已提交
765
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
766
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
767 768
}

R
runzexia 已提交
769 770
func (h *ProjectPipelineHandler) CreateSCMServers(req *restful.Request, resp *restful.Response) {
	scmId := req.PathParameter("scm")
Z
Zhuxiaoyang 已提交
771

R
runzexia 已提交
772
	res, err := h.devopsOperator.CreateSCMServers(scmId, req.Request)
Z
Zhuxiaoyang 已提交
773 774 775 776
	if err != nil {
		parseErr(err, resp)
		return
	}
R
runzexia 已提交
777

Z
Zhuxiaoyang 已提交
778
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
779
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
780 781
}

R
runzexia 已提交
782 783
func (h *ProjectPipelineHandler) Validate(req *restful.Request, resp *restful.Response) {
	scmId := req.PathParameter("scm")
Z
Zhuxiaoyang 已提交
784

R
runzexia 已提交
785
	res, err := h.devopsOperator.Validate(scmId, req.Request)
Z
Zhuxiaoyang 已提交
786
	if err != nil {
R
runzexia 已提交
787 788 789 790 791 792 793 794 795 796
		log.Error(err)
		if jErr, ok := err.(*devops.JkError); ok {
			if jErr.Code != http.StatusUnauthorized {
				resp.WriteError(jErr.Code, err)
			} else {
				resp.WriteHeader(http.StatusPreconditionRequired)
			}
		} else {
			resp.WriteError(http.StatusInternalServerError, err)
		}
Z
Zhuxiaoyang 已提交
797 798
		return
	}
R
runzexia 已提交
799

Z
Zhuxiaoyang 已提交
800
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
R
runzexia 已提交
801
	resp.WriteAsJson(res)
Z
Zhuxiaoyang 已提交
802 803
}

R
runzexia 已提交
804 805
func (h *ProjectPipelineHandler) GetNotifyCommit(req *restful.Request, resp *restful.Response) {
	res, err := h.devopsOperator.GetNotifyCommit(req.Request)
Z
Zhuxiaoyang 已提交
806 807 808 809 810 811 812
	if err != nil {
		parseErr(err, resp)
		return
	}
	resp.Write(res)
}

R
runzexia 已提交
813 814
func (h *ProjectPipelineHandler) PostNotifyCommit(req *restful.Request, resp *restful.Response) {
	res, err := h.devopsOperator.GetNotifyCommit(req.Request)
Z
Zhuxiaoyang 已提交
815 816 817 818
	if err != nil {
		parseErr(err, resp)
		return
	}
Z
Zhuxiaoyang 已提交
819 820 821
	resp.Write(res)
}

R
runzexia 已提交
822 823
func (h *ProjectPipelineHandler) GithubWebhook(req *restful.Request, resp *restful.Response) {
	res, err := h.devopsOperator.GithubWebhook(req.Request)
Z
Zhuxiaoyang 已提交
824 825 826 827 828 829 830
	if err != nil {
		parseErr(err, resp)
		return
	}
	resp.Write(res)
}

R
runzexia 已提交
831 832 833 834 835
func (h *ProjectPipelineHandler) CheckScriptCompile(req *restful.Request, resp *restful.Response) {
	projectName := req.PathParameter("devops")
	pipelineName := req.PathParameter("pipeline")

	resBody, err := h.devopsOperator.CheckScriptCompile(projectName, pipelineName, req.Request)
R
runzexia 已提交
836 837 838 839
	if err != nil {
		parseErr(err, resp)
		return
	}
R
runzexia 已提交
840 841

	resp.WriteAsJson(resBody)
R
runzexia 已提交
842
}
R
runzexia 已提交
843 844 845 846 847

func (h *ProjectPipelineHandler) CheckCron(req *restful.Request, resp *restful.Response) {
	projectName := req.PathParameter("devops")

	res, err := h.devopsOperator.CheckCron(projectName, req.Request)
Z
Zhuxiaoyang 已提交
848 849 850 851
	if err != nil {
		parseErr(err, resp)
		return
	}
S
sunzhu 已提交
852

R
runzexia 已提交
853 854 855
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
	resp.WriteAsJson(res)
}
Z
Zhuxiaoyang 已提交
856

R
runzexia 已提交
857 858
func (h *ProjectPipelineHandler) ToJenkinsfile(req *restful.Request, resp *restful.Response) {
	res, err := h.devopsOperator.ToJenkinsfile(req.Request)
Z
Zhuxiaoyang 已提交
859 860 861 862
	if err != nil {
		parseErr(err, resp)
		return
	}
R
runzexia 已提交
863
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
Z
Zhuxiaoyang 已提交
864 865 866
	resp.WriteAsJson(res)
}

R
runzexia 已提交
867 868
func (h *ProjectPipelineHandler) ToJson(req *restful.Request, resp *restful.Response) {
	res, err := h.devopsOperator.ToJson(req.Request)
Z
Zhuxiaoyang 已提交
869 870 871 872
	if err != nil {
		parseErr(err, resp)
		return
	}
R
runzexia 已提交
873
	resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
Z
Zhuxiaoyang 已提交
874 875 876
	resp.WriteAsJson(res)
}

R
runzexia 已提交
877 878 879 880 881 882 883 884 885 886 887 888 889 890
func (h *ProjectPipelineHandler) GetProjectCredentialUsage(req *restful.Request, resp *restful.Response) {
	projectId := req.PathParameter("devops")
	credentialId := req.PathParameter("credential")
	response, err := h.projectCredentialGetter.GetProjectCredentialUsage(projectId, credentialId)
	if err != nil {
		log.Errorf("%+v", err)
		api.HandleInternalError(resp, nil, err)
		return
	}
	resp.WriteAsJson(response)
	return

}

S
sunzhu 已提交
891
func parseErr(err error, resp *restful.Response) {
S
soulseen 已提交
892
	log.Error(err)
S
sunzhu 已提交
893
	if jErr, ok := err.(*devops.JkError); ok {
Z
Zhuxiaoyang 已提交
894
		resp.WriteError(jErr.Code, err)
S
sunzhu 已提交
895
	} else {
Z
Zhuxiaoyang 已提交
896
		resp.WriteError(http.StatusInternalServerError, err)
S
sunzhu 已提交
897 898 899
	}
	return
}