提交 e64e8bb9 编写于 作者: S sunzhu 提交者: zryfish

add jenkins api

Signed-off-by: Nsoulseen <sunzhu@yunify.com>
上级 addf11c3
......@@ -23,3 +23,4 @@ tmp/
# OSX trash
.DS_Store
api.json
......@@ -21,6 +21,7 @@ import (
"kubesphere.io/kubesphere/cmd/ks-apiserver/app"
"log"
// Install apis
_ "kubesphere.io/kubesphere/pkg/apis/devops/install"
_ "kubesphere.io/kubesphere/pkg/apis/logging/install"
_ "kubesphere.io/kubesphere/pkg/apis/metrics/install"
_ "kubesphere.io/kubesphere/pkg/apis/monitoring/install"
......
/*
Copyright 2019 The KubeSphere Authors.
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 install
import (
"github.com/emicklei/go-restful"
urlruntime "k8s.io/apimachinery/pkg/util/runtime"
devopsv1alpha2 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha2"
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
)
func init() {
Install(runtime.Container)
}
func Install(c *restful.Container) {
urlruntime.Must(devopsv1alpha2.AddToContainer(c))
}
\ No newline at end of file
/*
Copyright 2019 The KubeSphere Authors.
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 v1alpha2
import (
"github.com/emicklei/go-restful"
"github.com/emicklei/go-restful-openapi"
"k8s.io/apimachinery/pkg/runtime/schema"
"kubesphere.io/kubesphere/pkg/apiserver/devops"
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
)
const GroupName = "devops.kubesphere.io"
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
var (
WebServiceBuilder = runtime.NewContainerBuilder(addWebService)
AddToContainer = WebServiceBuilder.AddToContainer
)
func addWebService(c *restful.Container) error {
webservice := runtime.NewWebService(GroupVersion)
tags := []string{"devops"}
// match Jenkisn api "/blue/rest/organizations/jenkins/pipelines/{projectName}/{pipelineName}"
webservice.Route(webservice.GET("/devops/{projectName}/pipelines/{pipelineName}").
To(devops.GetPipeline).
Metadata(restfulspec.KeyOpenAPITags, tags).
Doc("Get DevOps Pipelines.").
Param(webservice.PathParameter("pipelineName", "pipeline name")).
Param(webservice.PathParameter("projectName", "devops project name")))
// match Jenkisn api: "jenkins_api/blue/rest/search"
webservice.Route(webservice.GET("/devops/search").
To(devops.SearchPipelines).
Metadata(restfulspec.KeyOpenAPITags, tags).
Doc("Search DevOps resource.").
Param(webservice.QueryParameter("q", "query pipelines").
Required(false)).
Param(webservice.QueryParameter("filter", "filter resource").
Required(false)).
Param(webservice.QueryParameter("start", "start page").
Required(false)).
Param(webservice.QueryParameter("limit", "limit count").
Required(false)))
// match Jenkisn api "/blue/rest/organizations/jenkins/pipelines/{projectName}/{pipelineName}/runs/"
webservice.Route(webservice.GET("/devops/{projectName}/pipelines/{pipelineName}/runs").
To(devops.SearchPipelineRuns).
Metadata(restfulspec.KeyOpenAPITags, tags).
Doc("Search DevOps Pipelines runs.").
Param(webservice.PathParameter("pipelineName", "pipeline name")).
Param(webservice.PathParameter("projectName", "devops project name")).
Param(webservice.QueryParameter("start", "start page").
Required(false)).
Param(webservice.QueryParameter("limit", "limit count").
Required(false)))
// match Jenkins api "/blue/rest/organizations/jenkins/pipelines/{projectName}/{pipelineName}/branches/{branchName}/runs/{runId}/"
webservice.Route(webservice.GET("/devops/{projectName}/pipelines/{pipelineName}/branches/{branchName}/runs/{runId}").
To(devops.GetPipelineRun).
Metadata(restfulspec.KeyOpenAPITags, tags).
Doc("Get DevOps Pipelines run.").
Param(webservice.PathParameter("pipelineName", "pipeline name")).
Param(webservice.PathParameter("projectName", "devops project name")).
Param(webservice.PathParameter("branchName", "pipeline branch name")).
Param(webservice.PathParameter("runId", "pipeline runs id")))
// match Jenkins api "/blue/rest/organizations/jenkins/pipelines/{projectName}/{pipelineName}/branches/{branchName}/runs/{runId}/nodes"
webservice.Route(webservice.GET("/devops/{projectName}/pipelines/{pipelineName}/branches/{branchName}/runs/{runId}/nodes").
To(devops.GetPipelineRunNodes).
Metadata(restfulspec.KeyOpenAPITags, tags).
Doc("Get node on DevOps Pipelines run.").
Param(webservice.PathParameter("projectName", "devops project name")).
Param(webservice.PathParameter("pipelineName", "pipeline name")).
Param(webservice.PathParameter("branchName", "pipeline branch name")).
Param(webservice.PathParameter("runId", "pipeline runs id")).
Param(webservice.QueryParameter("limit", "limit").
Required(false).
DataFormat("limit=%d").
DefaultValue("limit=10000")))
// match "/blue/rest/organizations/jenkins/pipelines/{projectName}/{pipelineName}/branches/{branchName}/runs/{runId}/nodes/{nodeId}/steps/{stepId}/log/?start=0"
webservice.Route(webservice.GET("/devops/{projectName}/pipelines/{pipelineName}/branches/{branchName}/runs/{runId}/nodes/{nodeId}/steps/{stepId}/log").
To(devops.GetStepLog).
Metadata(restfulspec.KeyOpenAPITags, tags).
Doc("Get Pipelines step log.").
Param(webservice.PathParameter("projectName", "devops project name")).
Param(webservice.PathParameter("pipelineName", "pipeline name")).
Param(webservice.PathParameter("branchName", "pipeline branch name")).
Param(webservice.PathParameter("runId", "pipeline runs id")).
Param(webservice.PathParameter("nodeId", "pipeline runs node id")).
Param(webservice.PathParameter("stepId", "pipeline runs step id")).
Param(webservice.QueryParameter("start", "start").
Required(true).
DataFormat("start=%d").
DefaultValue("start=0")))
c.Add(webservice)
return nil
}
/*
Copyright 2019 The KubeSphere Authors.
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 devops
import (
"github.com/emicklei/go-restful"
"kubesphere.io/kubesphere/pkg/errors"
"kubesphere.io/kubesphere/pkg/models/devops"
"net/http"
)
func GetPipeline(req *restful.Request, resp *restful.Response) {
projectName := req.PathParameter("projectName")
pipelineName := req.PathParameter("pipelineName")
res, err := devops.GetPipeline(projectName, pipelineName, req.Request)
if err != nil {
parseErr(err, resp)
return
}
_ = resp.WriteAsJson(res)
}
func SearchPipelines(req *restful.Request, resp *restful.Response) {
res, err := devops.SearchPipelines(req.Request)
if err != nil {
parseErr(err, resp)
return
}
_ = resp.WriteAsJson(res)
}
func SearchPipelineRuns(req *restful.Request, resp *restful.Response) {
projectName := req.PathParameter("projectName")
pipelineName := req.PathParameter("pipelineName")
res, err := devops.SearchPipelineRuns(projectName, pipelineName, req.Request)
if err != nil {
parseErr(err, resp)
return
}
_ = resp.WriteAsJson(res)
}
func GetPipelineRun(req *restful.Request, resp *restful.Response) {
projectName := req.PathParameter("projectName")
pipelineName := req.PathParameter("pipelineName")
branchName := req.PathParameter("branchName")
runId := req.PathParameter("runId")
res, err := devops.GetPipelineRun(projectName, pipelineName, branchName, runId, req.Request)
if err != nil {
parseErr(err, resp)
return
}
_ = resp.WriteAsJson(res)
}
func GetPipelineRunNodes(req *restful.Request, resp *restful.Response) {
projectName := req.PathParameter("projectName")
pipelineName := req.PathParameter("pipelineName")
branchName := req.PathParameter("branchName")
runId := req.PathParameter("runId")
res, err := devops.GetPipelineRunNodes(projectName, pipelineName, branchName, runId, req.Request)
if err != nil {
parseErr(err, resp)
return
}
_ = resp.WriteAsJson(res)
}
func GetStepLog(req *restful.Request, resp *restful.Response) {
projectName := req.PathParameter("projectName")
pipelineName := req.PathParameter("pipelineName")
branchName := req.PathParameter("branchName")
runId := req.PathParameter("runId")
nodeId := req.PathParameter("nodeId")
stepId := req.PathParameter("stepId")
res, err := devops.GetStepLog(projectName, pipelineName, branchName, runId, nodeId, stepId, req.Request)
if err != nil {
parseErr(err, resp)
return
}
_, _ = resp.Write(res)
}
func parseErr(err error, resp *restful.Response) {
if jErr, ok := err.(*devops.JkError); ok {
_ = resp.WriteHeaderAndEntity(jErr.Code, err)
} else {
_ = resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
}
return
}
/*
Copyright 2019 The KubeSphere Authors.
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 devops
import (
"compress/gzip"
"encoding/json"
"flag"
"fmt"
log "github.com/golang/glog"
"io"
"io/ioutil"
"net/http"
"net/url"
"time"
)
var JenkinsUrl string
func init() {
flag.StringVar(&JenkinsUrl, "jenkins-url", "http://ks-jenkins.kubesphere-devops-system.svc.cluster.local:80", "jenkins server host")
}
func GetPipeline(projectName, pipelineName string, req *http.Request) (*Pipeline, error) {
baseUrl := fmt.Sprintf(JenkinsUrl+GetPipelineUrl, projectName, pipelineName)
log.Infof("Jenkins-url: " + baseUrl)
resBody, err := jenkinsClient(baseUrl, req)
if err != nil {
return nil, err
}
var res = new(Pipeline)
err = json.Unmarshal(resBody, &res)
if err != nil {
log.Error(err)
return nil, err
}
return res, err
}
func SearchPipelines(req *http.Request) ([]interface{}, error) {
baseUrl := JenkinsUrl + SearchPipelineUrl + req.URL.RawQuery
log.Infof("Jenkins-url: " + baseUrl)
resBody, err := jenkinsClient(baseUrl, req)
if err != nil {
return nil, err
}
var res []interface{}
err = json.Unmarshal(resBody, &res)
if err != nil {
log.Error(err)
return nil, err
}
return res, err
}
func SearchPipelineRuns(projectName, pipelineName string, req *http.Request) ([]interface{}, error) {
baseUrl := fmt.Sprintf(JenkinsUrl+SearchPipelineRunUrl+req.URL.RawQuery, projectName, pipelineName)
log.Infof("Jenkins-url: " + baseUrl)
resBody, err := jenkinsClient(baseUrl, req)
if err != nil {
return nil, err
}
var res []interface{}
err = json.Unmarshal(resBody, &res)
if err != nil {
log.Error(err)
return nil, err
}
return res, err
}
func GetPipelineRun(projectName, pipelineName, branchName, runId string, req *http.Request) (*Pipeline, error) {
baseUrl := fmt.Sprintf(JenkinsUrl+GetPipelineRunUrl, projectName, pipelineName, branchName, runId)
log.Infof("Jenkins-url: " + baseUrl)
resBody, err := jenkinsClient(baseUrl, req)
if err != nil {
return nil, err
}
var res = new(Pipeline)
err = json.Unmarshal(resBody, &res)
if err != nil {
log.Error(err)
return nil, err
}
return res, err
}
func GetPipelineRunNodes(projectName, pipelineName, branchName, runId string, req *http.Request) ([]interface{}, error) {
baseUrl := fmt.Sprintf(JenkinsUrl+GetPipelineRunNodesUrl+req.URL.RawQuery, projectName, pipelineName, branchName, runId)
log.Infof("Jenkins-url: " + baseUrl)
resBody, err := jenkinsClient(baseUrl, req)
if err != nil {
return nil, err
}
var res []interface{}
err = json.Unmarshal(resBody, &res)
if err != nil {
log.Error(err)
return nil, err
}
return res, err
}
func GetStepLog(projectName, pipelineName, branchName, runId, nodeId, stepId string, req *http.Request) ([]byte, error) {
baseUrl := fmt.Sprintf(JenkinsUrl+GetStepLogUrl+req.URL.RawQuery, projectName, pipelineName, branchName, runId, nodeId, stepId)
log.Infof("Jenkins-url: " + baseUrl)
resBody, err := jenkinsClient(baseUrl, req)
if err != nil {
return nil, err
}
return resBody, err
}
// create jenkins request
func jenkinsClient(baseUrl string, req *http.Request) ([]byte, error) {
newReqUrl, err := url.Parse(baseUrl)
if err != nil {
log.Error(err)
return nil, err
}
client := &http.Client{Timeout: 30 * time.Second}
newRequest := &http.Request{
Method: req.Method,
URL: newReqUrl,
Header: req.Header,
Body: req.Body,
}
resp, err := client.Do(newRequest)
if err != nil {
log.Error(err)
return nil, err
}
defer resp.Body.Close()
resBody, _ := getRespBody(resp)
if resp.StatusCode >= http.StatusBadRequest {
jkerr := new(JkError)
_ = json.Unmarshal(resBody, jkerr)
log.Error(nil, jkerr)
return nil, jkerr
}
return resBody, err
}
// Decompress response.body of JenkinsAPIResponse
func getRespBody(resp *http.Response) ([]byte, error) {
var reader io.ReadCloser
if resp.Header.Get("Content-Encoding") == "gzip" {
reader, _ = gzip.NewReader(resp.Body)
} else {
reader = resp.Body
}
resBody, err := ioutil.ReadAll(reader)
if err != nil {
log.Error(err)
return nil, err
}
return resBody, err
}
/*
Copyright 2019 The KubeSphere Authors.
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 devops
type JkError struct {
Message string `json:"message"`
Code int `json:"code"`
Errors []Errors `json:"errors"`
}
type Errors struct {
Message string `json:"message"`
Code string `json:"code"`
Field string `json:"field"`
}
func (err *JkError) Error() string {
return err.Message
}
/*
Copyright 2019 The KubeSphere Authors.
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 devops
type Pipeline struct {
Class string `json:"_class,omitempty"`
Links Links `json:"_links,omitempty"`
Actions []interface{} `json:"actions,omitempty"`
DisplayName string `json:"displayName,omitempty"`
FullDisplayName string `json:"fullDisplayName,omitempty"`
FullName string `json:"fullName,omitempty"`
Name interface{} `json:"name,omitempty"`
Organization string `json:"organization,omitempty"`
Parameters interface{} `json:"parameters,omitempty"`
Permissions Permissions `json:"permissions,omitempty"`
EstimatedDurationInMillis int `json:"estimatedDurationInMillis,omitempty"`
NumberOfFolders int `json:"numberOfFolders,omitempty"`
NumberOfPipelines int `json:"numberOfPipelines,omitempty"`
PipelineFolderNames []interface{} `json:"pipelineFolderNames,omitempty"`
WeatherScore int `json:"weatherScore,omitempty"`
BranchNames []string `json:"branchNames,omitempty"`
NumberOfFailingBranches int `json:"numberOfFailingBranches,omitempty"`
NumberOfFailingPullRequests int `json:"numberOfFailingPullRequests,omitempty"`
NumberOfSuccessfulBranches int `json:"numberOfSuccessfulBranches,omitempty"`
NumberOfSuccessfulPullRequests int `json:"numberOfSuccessfulPullRequests,omitempty"`
ScmSource ScmSource `json:"scmSource,omitempty"`
TotalNumberOfBranches int `json:"totalNumberOfBranches,omitempty"`
TotalNumberOfPullRequests int `json:"totalNumberOfPullRequests,omitempty"`
ArtifactsZipFile interface{} `json:"artifactsZipFile,omitempty"`
CauseOfBlockage interface{} `json:"causeOfBlockage,omitempty"`
Causes []Causes `json:"causes,omitempty"`
ChangeSet []interface{} `json:"changeSet,omitempty"`
Description interface{} `json:"description,omitempty"`
DurationInMillis int `json:"durationInMillis,omitempty"`
EnQueueTime string `json:"enQueueTime,omitempty"`
EndTime string `json:"endTime,omitempty"`
ID string `json:"id,omitempty"`
Pipeline string `json:"pipeline,omitempty"`
Replayable bool `json:"replayable,omitempty"`
Result string `json:"result,omitempty"`
RunSummary string `json:"runSummary,omitempty"`
StartTime string `json:"startTime,omitempty"`
State string `json:"state,omitempty"`
Type string `json:"type,omitempty"`
Branch Branch `json:"branch,omitempty"`
CommitID string `json:"commitId,omitempty"`
CommitURL interface{} `json:"commitUrl,omitempty"`
PullRequest interface{} `json:"pullRequest,omitempty"`
}
type Self struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
}
type Scm struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
}
type Branches struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
}
type Actions struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
}
type Runs struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
}
type Trends struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
}
type Queue struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
}
type Links struct {
Self Self `json:"self,omitempty"`
Scm Scm `json:"scm,omitempty"`
Branches Branches `json:"branches,omitempty"`
Actions Actions `json:"actions,omitempty"`
Runs Runs `json:"runs,omitempty"`
Trends Trends `json:"trends,omitempty"`
Queue Queue `json:"queue,omitempty"`
PrevRun PrevRun `json:"prevRun"`
Parent Parent `json:"parent"`
Tests Tests `json:"tests"`
Nodes Nodes `json:"nodes"`
Log Log `json:"log"`
BlueTestSummary BlueTestSummary `json:"blueTestSummary"`
Steps Steps `json:"steps"`
Artifacts Artifacts `json:"artifacts"`
}
type Permissions struct {
Create bool `json:"create,omitempty"`
Configure bool `json:"configure,omitempty"`
Read bool `json:"read,omitempty"`
Start bool `json:"start,omitempty"`
Stop bool `json:"stop,omitempty"`
}
type ScmSource struct {
Class string `json:"_class,omitempty"`
APIURL interface{} `json:"apiUrl,omitempty"`
ID string `json:"id,omitempty"`
}
type PrevRun struct {
Class string `json:"_class"`
Href string `json:"href"`
}
type Parent struct {
Class string `json:"_class"`
Href string `json:"href"`
}
type Tests struct {
Class string `json:"_class"`
Href string `json:"href"`
}
type Nodes struct {
Class string `json:"_class"`
Href string `json:"href"`
}
type Log struct {
Class string `json:"_class"`
Href string `json:"href"`
}
type BlueTestSummary struct {
Class string `json:"_class"`
Href string `json:"href"`
}
type Steps struct {
Class string `json:"_class"`
Href string `json:"href"`
}
type Artifacts struct {
Class string `json:"_class"`
Href string `json:"href"`
}
type Causes struct {
Class string `json:"_class"`
ShortDescription string `json:"shortDescription"`
UserID string `json:"userId,omitempty"`
UserName string `json:"userName,omitempty"`
}
type Branch struct {
IsPrimary bool `json:"isPrimary"`
Issues []interface{} `json:"issues"`
URL string `json:"url"`
}
/*
Copyright 2019 The KubeSphere Authors.
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 devops
// Some apis for Jenkins.
const (
GetPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/%s/"
SearchPipelineUrl = "/blue/rest/search/?"
SearchPipelineRunUrl = "/blue/rest/organizations/jenkins/pipelines/%s/%s/runs/?"
GetPipelineRunUrl = "/blue/rest/organizations/jenkins/pipelines/%s/%s/branches/%s/runs/%s/"
GetPipelineRunNodesUrl = "/blue/rest/organizations/jenkins/pipelines/%s/%s/branches/%s/runs/%s/nodes/?"
GetStepLogUrl = "/blue/rest/organizations/jenkins/pipelines/%s/%s/branches/%s/runs/%s/nodes/%s/steps/%s/log/?"
)
......@@ -31,6 +31,7 @@ import (
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
"log"
// Install apis
_ "kubesphere.io/kubesphere/pkg/apis/devops/install"
_ "kubesphere.io/kubesphere/pkg/apis/metrics/install"
_ "kubesphere.io/kubesphere/pkg/apis/monitoring/install"
_ "kubesphere.io/kubesphere/pkg/apis/operations/install"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册