update check pipeline script & cronjob script
Signed-off-by: soulseen <sunzhu@yunify.com>
This commit is contained in:
@@ -633,30 +633,30 @@ The last one is encrypted info, such as the password of the username-password ty
|
|||||||
Param(webservice.PathParameter("file", "the name of binary file")).
|
Param(webservice.PathParameter("file", "the name of binary file")).
|
||||||
Returns(http.StatusOK, RespOK, nil))
|
Returns(http.StatusOK, RespOK, nil))
|
||||||
|
|
||||||
// TODO are not used in this version. will be added in 2.1.0
|
webservice.Route(webservice.POST("/devops/{devops}/pipelines/{pipeline}/checkScriptCompile").
|
||||||
//// match /job/init-job/descriptorByName/org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition/checkScriptCompile
|
To(devopsapi.CheckScriptCompile).
|
||||||
//webservice.Route(webservice.POST("/devops/check/scriptcompile").
|
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsPipelineTag}).
|
||||||
// To(devopsapi.CheckScriptCompile).
|
Param(webservice.PathParameter("devops", "DevOps project's ID, e.g. project-RRRRAzLBlLEm")).
|
||||||
// Metadata(restfulspec.KeyOpenAPITags, tags).
|
Param(webservice.QueryParameter("pipeline", "the name of the CI/CD pipeline").
|
||||||
// Consumes("application/x-www-form-urlencoded", "charset=utf-8").
|
Required(false).
|
||||||
// Produces("application/json", "charset=utf-8").
|
DataFormat("pipeline=%s")).
|
||||||
// Doc("Check pipeline script compile.").
|
Consumes("application/x-www-form-urlencoded", "charset=utf-8").
|
||||||
// Reads(devops.ReqScript{}).
|
Produces("application/json", "charset=utf-8").
|
||||||
// Returns(http.StatusOK, RespOK, devops.CheckScript{}).
|
Doc("Check pipeline script compile.").
|
||||||
// Writes(devops.CheckScript{}))
|
Reads(devops.ReqScript{}).
|
||||||
|
Returns(http.StatusOK, RespOK, devops.CheckScript{}).
|
||||||
|
Writes(devops.CheckScript{}))
|
||||||
|
|
||||||
// match /job/init-job/descriptorByName/hudson.triggers.TimerTrigger/checkSpec
|
webservice.Route(webservice.POST("/devops/{devops}/checkCron").
|
||||||
//webservice.Route(webservice.GET("/devops/check/cron").
|
To(devopsapi.CheckCron).
|
||||||
// To(devopsapi.CheckCron).
|
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsPipelineTag}).
|
||||||
// Metadata(restfulspec.KeyOpenAPITags, tags).
|
Param(webservice.PathParameter("devops", "DevOps project's ID, e.g. project-RRRRAzLBlLEm")).
|
||||||
// Produces("application/json", "charset=utf-8").
|
Param(webservice.PathParameter("pipeline", "the name of the CI/CD pipeline")).
|
||||||
// Doc("Check cron script compile.").
|
Produces("application/json", "charset=utf-8").
|
||||||
// Param(webservice.QueryParameter("value", "string of cron script.").
|
Doc("Check cron script compile.").
|
||||||
// Required(true).
|
Reads(devops.CronData{}).
|
||||||
// DataFormat("value=%s")).
|
Returns(http.StatusOK, RespOK, devops.CheckCronRes{}).
|
||||||
// Returns(http.StatusOK, RespOK, []devops.QueuedBlueRun{}).
|
Writes(devops.CheckCronRes{}))
|
||||||
// Returns(http.StatusOK, RespOK, devops.CheckCronRes{}).
|
|
||||||
// Writes(devops.CheckCronRes{}))
|
|
||||||
|
|
||||||
// match /blue/rest/organizations/jenkins/pipelines/{devops}/{pipeline}/runs/{run}/
|
// match /blue/rest/organizations/jenkins/pipelines/{devops}/{pipeline}/runs/{run}/
|
||||||
webservice.Route(webservice.GET("/devops/{devops}/pipelines/{pipeline}/runs/{run}").
|
webservice.Route(webservice.GET("/devops/{devops}/pipelines/{pipeline}/runs/{run}").
|
||||||
|
|||||||
@@ -443,7 +443,10 @@ func GetCrumb(req *restful.Request, resp *restful.Response) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CheckScriptCompile(req *restful.Request, resp *restful.Response) {
|
func CheckScriptCompile(req *restful.Request, resp *restful.Response) {
|
||||||
resBody, err := devops.CheckScriptCompile(req.Request)
|
projectName := req.PathParameter("devops")
|
||||||
|
pipelineName := req.PathParameter("pipeline")
|
||||||
|
|
||||||
|
resBody, err := devops.CheckScriptCompile(projectName, pipelineName, req.Request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
parseErr(err, resp)
|
parseErr(err, resp)
|
||||||
return
|
return
|
||||||
@@ -467,7 +470,9 @@ func CheckScriptCompile(req *restful.Request, resp *restful.Response) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CheckCron(req *restful.Request, resp *restful.Response) {
|
func CheckCron(req *restful.Request, resp *restful.Response) {
|
||||||
res, err := devops.CheckCron(req.Request)
|
projectName := req.PathParameter("devops")
|
||||||
|
|
||||||
|
res, err := devops.CheckCron(projectName, req.Request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
parseErr(err, resp)
|
parseErr(err, resp)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -30,11 +30,15 @@ import (
|
|||||||
"kubesphere.io/kubesphere/pkg/simple/client/admin_jenkins"
|
"kubesphere.io/kubesphere/pkg/simple/client/admin_jenkins"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const channelMaxCapacity = 100
|
const (
|
||||||
|
channelMaxCapacity = 100
|
||||||
|
cronJobLayout = "Monday, January 2, 2006 15:04:05 PM"
|
||||||
|
)
|
||||||
|
|
||||||
var jenkins *gojenkins.Jenkins
|
var jenkins *gojenkins.Jenkins
|
||||||
|
|
||||||
@@ -485,10 +489,9 @@ func GetCrumb(req *http.Request) ([]byte, error) {
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckScriptCompile(req *http.Request) ([]byte, error) {
|
func CheckScriptCompile(projectName, pipelineName string, req *http.Request) ([]byte, error) {
|
||||||
baseUrl := jenkins.Server + CheckScriptCompileUrl
|
baseUrl := fmt.Sprintf(jenkins.Server+CheckScriptCompileUrl, projectName, pipelineName)
|
||||||
log.Info("Jenkins-url: " + baseUrl)
|
log.Info("Jenkins-url: " + baseUrl)
|
||||||
req.SetBasicAuth(jenkins.Requester.BasicAuth.Username, jenkins.Requester.BasicAuth.Password)
|
|
||||||
|
|
||||||
resBody, err := sendJenkinsRequest(baseUrl, req)
|
resBody, err := sendJenkinsRequest(baseUrl, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -499,38 +502,96 @@ func CheckScriptCompile(req *http.Request) ([]byte, error) {
|
|||||||
return resBody, err
|
return resBody, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckCron(req *http.Request) (*CheckCronRes, error) {
|
func CheckCron(projectName string, req *http.Request) (*CheckCronRes, error) {
|
||||||
newurl, err := url.Parse(jenkins.Server + CheckCronUrl + req.URL.RawQuery)
|
var res = new(CheckCronRes)
|
||||||
|
var cron = new(CronData)
|
||||||
|
var reader io.ReadCloser
|
||||||
|
var baseUrl string
|
||||||
|
|
||||||
|
reader = req.Body
|
||||||
|
cronData, err := ioutil.ReadAll(reader)
|
||||||
|
json.Unmarshal(cronData, cron)
|
||||||
|
|
||||||
|
if cron.PipelineName != "" {
|
||||||
|
baseUrl = fmt.Sprintf(jenkins.Server+CheckPipelienCronUrl, projectName, cron.PipelineName, cron.Cron)
|
||||||
|
} else {
|
||||||
|
baseUrl = fmt.Sprintf(jenkins.Server+CheckCronUrl, projectName, cron.Cron)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Jenkins-url: " + baseUrl)
|
||||||
|
newurl, err := url.Parse(baseUrl)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
newurl.RawQuery = newurl.Query().Encode()
|
||||||
|
|
||||||
reqJenkins := &http.Request{
|
reqJenkins := &http.Request{
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
URL: newurl,
|
URL: newurl,
|
||||||
Header: http.Header{},
|
Header: req.Header,
|
||||||
}
|
}
|
||||||
var res = new(CheckCronRes)
|
|
||||||
client := &http.Client{Timeout: 30 * time.Second}
|
client := &http.Client{Timeout: 30 * time.Second}
|
||||||
|
|
||||||
reqJenkins.SetBasicAuth(jenkins.Requester.BasicAuth.Username, jenkins.Requester.BasicAuth.Password)
|
|
||||||
|
|
||||||
resp, err := client.Do(reqJenkins)
|
resp, err := client.Do(reqJenkins)
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
resBody, _ := getRespBody(resp)
|
||||||
|
return &CheckCronRes{
|
||||||
|
Result: "error",
|
||||||
|
Message: string(resBody),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
return res, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
doc, err := goquery.NewDocumentFromReader(resp.Body)
|
doc, err := goquery.NewDocumentFromReader(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
return res, err
|
return nil, err
|
||||||
}
|
}
|
||||||
doc.Find("div").Each(func(i int, selection *goquery.Selection) {
|
doc.Find("div").Each(func(i int, selection *goquery.Selection) {
|
||||||
res.Message = selection.Text()
|
res.Message = selection.Text()
|
||||||
res.Result, _ = selection.Attr("class")
|
res.Result, _ = selection.Attr("class")
|
||||||
})
|
})
|
||||||
|
if res.Result == "ok" {
|
||||||
|
res.LastTime, res.NextTime, err = parseCronJobTime(res.Message)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseCronJobTime(msg string) (string, string, error) {
|
||||||
|
times := strings.Split(msg, ";")
|
||||||
|
|
||||||
|
lastTmp := strings.SplitN(times[0], " ", 2)
|
||||||
|
lastTime := strings.SplitN(lastTmp[1], " UTC", 2)
|
||||||
|
lastUinx, err := time.Parse(cronJobLayout, lastTime[0])
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return "","",err
|
||||||
|
}
|
||||||
|
last := lastUinx.Format(time.RFC3339)
|
||||||
|
|
||||||
|
nextTmp := strings.SplitN(times[1], " ", 3)
|
||||||
|
nextTime := strings.SplitN(nextTmp[2], " UTC", 2)
|
||||||
|
nextUinx, err := time.Parse(cronJobLayout, nextTime[0])
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return "","",err
|
||||||
|
}
|
||||||
|
next := nextUinx.Format(time.RFC3339)
|
||||||
|
|
||||||
|
return last, next, nil
|
||||||
|
}
|
||||||
|
|
||||||
func GetPipelineRun(projectName, pipelineName, runId string, req *http.Request) ([]byte, error) {
|
func GetPipelineRun(projectName, pipelineName, runId string, req *http.Request) ([]byte, error) {
|
||||||
baseUrl := fmt.Sprintf(jenkins.Server+GetPipelineRunUrl, projectName, pipelineName, runId)
|
baseUrl := fmt.Sprintf(jenkins.Server+GetPipelineRunUrl, projectName, pipelineName, runId)
|
||||||
log.Info("Jenkins-url: " + baseUrl)
|
log.Info("Jenkins-url: " + baseUrl)
|
||||||
|
|||||||
36
pkg/models/devops/devops_test.go
Normal file
36
pkg/models/devops/devops_test.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package devops
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func Test_parseCronJobTime(t *testing.T) {
|
||||||
|
type Except struct {
|
||||||
|
Last string
|
||||||
|
Next string
|
||||||
|
}
|
||||||
|
|
||||||
|
Items := []struct {
|
||||||
|
Input string
|
||||||
|
Expected Except
|
||||||
|
}{
|
||||||
|
{"上次运行的时间 Tuesday, September 10, 2019 8:59:09 AM UTC; 下次运行的时间 Tuesday, September 10, 2019 9:14:09 AM UTC.", Except{Last: "2019-09-10T08:59:09Z", Next: "2019-09-10T09:14:09Z"}},
|
||||||
|
{"上次运行的时间 Thursday, January 3, 2019 11:56:30 PM UTC; 下次运行的时间 Friday, January 3, 2020 12:11:30 AM UTC.", Except{Last: "2019-01-03T23:56:30Z", Next: "2020-01-03T00:11:30Z"}},
|
||||||
|
{"上次运行的时间 Tuesday, September 10, 2019 8:41:34 AM UTC; 下次运行的时间 Tuesday, September 10, 2019 9:41:34 AM UTC.", Except{Last: "2019-09-10T08:41:34Z", Next: "2019-09-10T09:41:34Z"}},
|
||||||
|
{"上次运行的时间 Tuesday, September 10, 2019 9:15:26 AM UTC; 下次运行的时间 Tuesday, September 10, 2019 10:03:26 AM UTC.", Except{Last: "2019-09-10T09:15:26Z", Next: "2019-09-10T10:03:26Z"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item:=range Items {
|
||||||
|
last, next, err := parseCronJobTime(item.Input)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should not get error %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if last != item.Expected.Last {
|
||||||
|
t.Errorf("got %#v, expected %#v", last, item.Expected.Last)
|
||||||
|
}
|
||||||
|
|
||||||
|
if next != item.Expected.Next {
|
||||||
|
t.Errorf("got %#v, expected %#v", next, item.Expected.Next)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -755,14 +755,21 @@ type Crumb struct {
|
|||||||
type CheckScript struct {
|
type CheckScript struct {
|
||||||
Column int `json:"column,omitempty" description:"column e.g. 0"`
|
Column int `json:"column,omitempty" description:"column e.g. 0"`
|
||||||
Line int `json:"line,omitempty" description:"line e.g. 0"`
|
Line int `json:"line,omitempty" description:"line e.g. 0"`
|
||||||
Message string `json:"message,omitempty" description:"message e.g. success"`
|
Message string `json:"message,omitempty" description:"message e.g. unexpected char: '#'"`
|
||||||
Status string `json:"status,omitempty" description:"status e.g. success"`
|
Status string `json:"status,omitempty" description:"status e.g. fail"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckCron
|
// CheckCron
|
||||||
|
type CronData struct {
|
||||||
|
PipelineName string `json:"pipelineName,omitempty" description:"Pipeline name, if pipeline haven't created, not required'"`
|
||||||
|
Cron string `json:"cron" description:"Cron script data."`
|
||||||
|
}
|
||||||
|
|
||||||
type CheckCronRes struct {
|
type CheckCronRes struct {
|
||||||
Result string `json:"result,omitempty" description:"result"`
|
Result string `json:"result,omitempty" description:"result e.g. ok, error"`
|
||||||
Message string `json:"message,omitempty" description:"message"`
|
Message string `json:"message,omitempty" description:"message"`
|
||||||
|
LastTime string `json:"lastTime,omitempty" description:"last run time."`
|
||||||
|
NextTime string `json:"nextTime,omitempty" description:"next run time."`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPipelineRun
|
// GetPipelineRun
|
||||||
@@ -1035,7 +1042,7 @@ type NodeSteps struct {
|
|||||||
|
|
||||||
// CheckScriptCompile
|
// CheckScriptCompile
|
||||||
type ReqScript struct {
|
type ReqScript struct {
|
||||||
Value string `json:"value,omitempty" description:"check value"`
|
Value string `json:"value,omitempty" description:"Pipeline script data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJenkinsfile requests
|
// ToJenkinsfile requests
|
||||||
|
|||||||
@@ -52,10 +52,11 @@ const (
|
|||||||
GetConsoleLogUrl = "/job/%s/job/%s/indexing/consoleText"
|
GetConsoleLogUrl = "/job/%s/job/%s/indexing/consoleText"
|
||||||
ScanBranchUrl = "/job/%s/job/%s/build?"
|
ScanBranchUrl = "/job/%s/job/%s/build?"
|
||||||
GetCrumbUrl = "/crumbIssuer/api/json/"
|
GetCrumbUrl = "/crumbIssuer/api/json/"
|
||||||
CheckScriptCompileUrl = "/job/init-job/descriptorByName/org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition/checkScriptCompile"
|
|
||||||
CheckCronUrl = "/job/init-job/descriptorByName/hudson.triggers.TimerTrigger/checkSpec?"
|
|
||||||
ToJenkinsfileUrl = "/pipeline-model-converter/toJenkinsfile"
|
ToJenkinsfileUrl = "/pipeline-model-converter/toJenkinsfile"
|
||||||
ToJsonUrl = "/pipeline-model-converter/toJson"
|
ToJsonUrl = "/pipeline-model-converter/toJson"
|
||||||
GetNotifyCommitUrl = "/git/notifyCommit/?"
|
GetNotifyCommitUrl = "/git/notifyCommit/?"
|
||||||
GithubWebhookUrl = "/github-webhook/"
|
GithubWebhookUrl = "/github-webhook/"
|
||||||
|
CheckScriptCompileUrl = "/job/%s/job/%s/descriptorByName/org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition/checkScriptCompile"
|
||||||
|
CheckPipelienCronUrl = "/job/%s/job/%s/descriptorByName/hudson.triggers.TimerTrigger/checkSpec?value=%s"
|
||||||
|
CheckCronUrl = "/job/%s/descriptorByName/hudson.triggers.TimerTrigger/checkSpec?value=%s"
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user