未验证 提交 4074e73a 编写于 作者: K KubeSphere CI Bot 提交者: GitHub

Merge pull request #2072 from shaowenchen/fix_create_pipeline

fix pipeline bugs
......@@ -7,7 +7,7 @@ We use a special type of secret as a credential for DevOps.
This file will not contain CRD, but the credential type constants and their fields.
*/
const (
CredentialFinalizerName = "credential.finalizers.kubesphere.io"
CredentialFinalizerName = "finalizers.kubesphere.io/credential"
DevOpsCredentialPrefix = "credential.devops.kubesphere.io/"
// SecretTypeBasicAuth contains data needed for basic authentication.
//
......
......@@ -31,6 +31,7 @@ import (
clusterkapisv1alpha1 "kubesphere.io/kubesphere/pkg/kapis/cluster/v1alpha1"
configv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/config/v1alpha2"
devopsv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/devops/v1alpha2"
devopsv1alpha3 "kubesphere.io/kubesphere/pkg/kapis/devops/v1alpha3"
iamapi "kubesphere.io/kubesphere/pkg/kapis/iam/v1alpha2"
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/logging/v1alpha2"
monitoringv1alpha3 "kubesphere.io/kubesphere/pkg/kapis/monitoring/v1alpha3"
......@@ -179,6 +180,12 @@ func (s *APIServer) installKubeSphereAPIs() {
s.SonarClient,
s.KubernetesClient.KubeSphere(),
s.S3Client))
urlruntime.Must(devopsv1alpha3.AddToContainer(s.container,
s.DevopsClient,
s.KubernetesClient.Kubernetes(),
s.KubernetesClient.KubeSphere(),
s.InformerFactory.KubeSphereSharedInformerFactory(),
s.InformerFactory.KubernetesSharedInformerFactory()))
urlruntime.Must(notificationv1.AddToContainer(s.container, s.Config.NotificationOptions.Endpoint))
urlruntime.Must(alertingv1.AddToContainer(s.container, s.Config.AlertingOptions.Endpoint))
}
......
......@@ -21,7 +21,6 @@ import (
devopsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"net/http"
"reflect"
"strings"
"time"
......@@ -217,24 +216,15 @@ func (c *Controller) syncHandler(key string) error {
copySecret := secret.DeepCopy()
// DeletionTimestamp.IsZero() means copySecret has not been deleted.
if copySecret.ObjectMeta.DeletionTimestamp.IsZero() {
if secret.ObjectMeta.DeletionTimestamp.IsZero() {
// https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#finalizers
if !sliceutil.HasString(copySecret.ObjectMeta.Finalizers, devopsv1alpha3.CredentialFinalizerName) {
if !sliceutil.HasString(secret.ObjectMeta.Finalizers, devopsv1alpha3.CredentialFinalizerName) {
copySecret.ObjectMeta.Finalizers = append(copySecret.ObjectMeta.Finalizers, devopsv1alpha3.CredentialFinalizerName)
}
// Check secret config exists, otherwise we will create it.
// if secret exists, update config
_, err := c.devopsClient.GetCredentialInProject(nsName, secret.Name)
if err != nil && devopsClient.GetDevOpsStatusCode(err) != http.StatusNotFound {
klog.Error(err, fmt.Sprintf("failed to get secret %s ", key))
return err
} else if err != nil {
_, err := c.devopsClient.CreateCredentialInProject(nsName, copySecret)
if err != nil {
klog.Error(err, fmt.Sprintf("failed to create secret %s ", key))
return err
}
} else {
_, err := c.devopsClient.CreateCredentialInProject(nsName, copySecret)
if err != nil {
if _, ok := copySecret.Annotations[devopsv1alpha3.CredentialAutoSyncAnnoKey]; ok {
_, err := c.devopsClient.UpdateCredentialInProject(nsName, copySecret)
if err != nil {
......@@ -247,16 +237,9 @@ func (c *Controller) syncHandler(key string) error {
} else {
// Finalizers processing logic
if sliceutil.HasString(copySecret.ObjectMeta.Finalizers, devopsv1alpha3.CredentialFinalizerName) {
_, err := c.devopsClient.GetCredentialInProject(nsName, secret.Name)
if err != nil && devopsClient.GetDevOpsStatusCode(err) != http.StatusNotFound {
klog.Error(err, fmt.Sprintf("failed to get secret %s ", key))
if _, err := c.devopsClient.DeleteCredentialInProject(nsName, secret.Name); err != nil {
klog.Error(err, fmt.Sprintf("failed to delete secret %s in devops", key))
return err
} else if err != nil && devopsClient.GetDevOpsStatusCode(err) == http.StatusNotFound {
} else {
if _, err := c.devopsClient.DeleteCredentialInProject(nsName, secret.Name); err != nil {
klog.Error(err, fmt.Sprintf("failed to delete secret %s in devops", key))
return err
}
}
copySecret.ObjectMeta.Finalizers = sliceutil.RemoveString(copySecret.ObjectMeta.Finalizers, func(item string) bool {
return item == devopsv1alpha3.CredentialFinalizerName
......
package devopscredential
import (
v1 "k8s.io/api/core/v1"
"kubesphere.io/kubesphere/pkg/constants"
fakeDevOps "kubesphere.io/kubesphere/pkg/simple/client/devops/fake"
"reflect"
"testing"
"time"
v1 "k8s.io/api/core/v1"
"kubesphere.io/kubesphere/pkg/constants"
fakeDevOps "kubesphere.io/kubesphere/pkg/simple/client/devops/fake"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
......@@ -351,27 +352,6 @@ func TestDeleteCredential(t *testing.T) {
f.run(getKey(secret, t))
}
func TestDeleteNotExistCredential(t *testing.T) {
f := newFixture(t)
nsName := "test-123"
pipelineName := "test"
projectName := "test_project"
ns := newNamespace(nsName, projectName)
secret := newDeletingSecret(nsName, pipelineName)
expectSecret := secret.DeepCopy()
expectSecret.Finalizers = []string{}
f.secretLister = append(f.secretLister, secret)
f.namespaceLister = append(f.namespaceLister, ns)
f.kubeobjects = append(f.kubeobjects, secret)
f.initDevOpsProject = nsName
f.initCredential = []*v1.Secret{}
f.expectCredential = []*v1.Secret{}
f.expectUpdateSecretAction(expectSecret)
f.run(getKey(secret, t))
}
func TestUpdateCredential(t *testing.T) {
f := newFixture(t)
nsName := "test-123"
......
......@@ -23,7 +23,6 @@ import (
devopsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"net/http"
"reflect"
"time"
)
......@@ -225,13 +224,10 @@ func (c *Controller) syncHandler(key string) error {
return err
}
}
} else if devopsClient.GetDevOpsStatusCode(err) != http.StatusNotFound {
klog.Error(err, fmt.Sprintf("failed to get copyPipeline %s ", key))
return err
} else {
_, err := c.devopsClient.CreateProjectPipeline(nsName, copyPipeline)
if err != nil {
klog.Error(err, fmt.Sprintf("failed to get copyPipeline %s ", key))
klog.Error(err, fmt.Sprintf("failed to create copyPipeline %s ", key))
return err
}
}
......@@ -239,16 +235,8 @@ func (c *Controller) syncHandler(key string) error {
} else {
// Finalizers processing logic
if sliceutil.HasString(copyPipeline.ObjectMeta.Finalizers, devopsv1alpha3.PipelineFinalizerName) {
_, err := c.devopsClient.GetProjectPipelineConfig(nsName, pipeline.Name)
if err != nil && devopsClient.GetDevOpsStatusCode(err) != http.StatusNotFound {
klog.Error(err, fmt.Sprintf("failed to get pipeline %s ", key))
return err
} else if err != nil && devopsClient.GetDevOpsStatusCode(err) == http.StatusNotFound {
} else {
if _, err := c.devopsClient.DeleteProjectPipeline(nsName, pipeline.Name); err != nil {
klog.Error(err, fmt.Sprintf("failed to delete pipeline %s in devops", key))
return err
}
if _, err := c.devopsClient.DeleteProjectPipeline(nsName, pipeline.Name); err != nil {
klog.Error(err, fmt.Sprintf("failed to delete pipeline %s in devops", key))
}
copyPipeline.ObjectMeta.Finalizers = sliceutil.RemoveString(copyPipeline.ObjectMeta.Finalizers, func(item string) bool {
return item == devopsv1alpha3.PipelineFinalizerName
......
......@@ -225,7 +225,7 @@ func TestDeleteS3Object(t *testing.T) {
f.s2ibinaryLister = append(f.s2ibinaryLister, s2iBinary)
f.objects = append(f.objects, s2iBinary)
f.initS3Objects = []*fakes3.Object{&fakes3.Object{
f.initS3Objects = []*fakes3.Object{{
Key: "default-test",
}}
f.expectS3Objects = []*fakes3.Object{}
......
......@@ -20,7 +20,7 @@ type PipelineSonarHandler struct {
func NewProjectPipelineHandler(devopsClient devopsClient.Interface) ProjectPipelineHandler {
return ProjectPipelineHandler{
devopsOperator: devops.NewDevopsOperator(devopsClient),
devopsOperator: devops.NewDevopsOperator(devopsClient, nil, nil, nil, nil),
projectCredentialGetter: devops.NewProjectCredentialOperator(devopsClient),
}
}
......
/*
Copyright 2020 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 v1alpha3
import (
"github.com/emicklei/go-restful"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3"
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/devops"
servererr "kubesphere.io/kubesphere/pkg/server/errors"
devopsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
)
type devopsHandler struct {
devops devops.DevopsOperator
}
func newDevOpsHandler(devopsClient devopsClient.Interface, k8sclient kubernetes.Interface, ksclient kubesphere.Interface,
ksInformers externalversions.SharedInformerFactory,
k8sInformers informers.SharedInformerFactory) *devopsHandler {
return &devopsHandler{
devops: devops.NewDevopsOperator(devopsClient, k8sclient, ksclient, ksInformers, k8sInformers),
}
}
// devopsproject handler about get/list/post/put/delete
func (h *devopsHandler) GetDevOpsProject(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
projectName := request.PathParameter("projectName")
project, err := h.devops.GetDevOpsProject(workspace, projectName)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(project)
}
func (h *devopsHandler) ListDevOpsProject(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
projectList, err := h.devops.ListDevOpsProject(workspace)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(projectList)
}
func (h *devopsHandler) CreateDevOpsProject(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
var devOpsProject v1alpha3.DevOpsProject
err := request.ReadEntity(&devOpsProject)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
created, err := h.devops.CreateDevOpsProject(workspace, &devOpsProject)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(created)
}
func (h *devopsHandler) UpdateDevOpsProject(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
var devOpsProject v1alpha3.DevOpsProject
err := request.ReadEntity(&devOpsProject)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
project, err := h.devops.UpdateDevOpsProject(workspace, &devOpsProject)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(project)
}
func (h *devopsHandler) DeleteDevOpsProject(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
projectName := request.PathParameter("projectName")
err := h.devops.DeleteDevOpsProject(workspace, projectName)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(servererr.None)
}
// pipeline handler about get/list/post/put/delete
func (h *devopsHandler) GetPipeline(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
projectName := request.PathParameter("projectName")
pipelineName := request.PathParameter("pipelineName")
obj, err := h.devops.GetPipelineObj(workspace, projectName, pipelineName)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(obj)
}
func (h *devopsHandler) ListPipeline(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
projectName := request.PathParameter("projectName")
objs, err := h.devops.ListPipelineObj(workspace, projectName)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(objs)
}
func (h *devopsHandler) CreatePipeline(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
projectName := request.PathParameter("projectName")
var pipeline v1alpha3.Pipeline
err := request.ReadEntity(&pipeline)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
created, err := h.devops.CreatePipelineObj(workspace, projectName, &pipeline)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(created)
}
func (h *devopsHandler) UpdatePipeline(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
projectName := request.PathParameter("projectName")
var pipeline v1alpha3.Pipeline
err := request.ReadEntity(&pipeline)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
obj, err := h.devops.UpdatePipelineObj(workspace, projectName, &pipeline)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(obj)
}
func (h *devopsHandler) DeletePipeline(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
projectName := request.PathParameter("projectName")
pipelineName := request.PathParameter("pipelineName")
err := h.devops.DeletePipelineObj(workspace, projectName, pipelineName)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(servererr.None)
}
//credential handler about get/list/post/put/delete
func (h *devopsHandler) GetCredential(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
projectName := request.PathParameter("projectName")
credentialName := request.PathParameter("credentialName")
obj, err := h.devops.GetCredentialObj(workspace, projectName, credentialName)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(obj)
}
func (h *devopsHandler) ListCredential(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
projectName := request.PathParameter("projectName")
objs, err := h.devops.ListCredentialObj(workspace, projectName)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(objs)
}
func (h *devopsHandler) CreateCredential(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
projectName := request.PathParameter("projectName")
var obj v1.Secret
err := request.ReadEntity(&obj)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
created, err := h.devops.CreateCredentialObj(workspace, projectName, &obj)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(created)
}
func (h *devopsHandler) UpdateCredential(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
projectName := request.PathParameter("projectName")
var obj v1.Secret
err := request.ReadEntity(&obj)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
updated, err := h.devops.UpdateCredentialObj(workspace, projectName, &obj)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(updated)
}
func (h *devopsHandler) DeleteCredential(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
projectName := request.PathParameter("projectName")
credentialName := request.PathParameter("credentialName")
err := h.devops.DeleteCredentialObj(workspace, projectName, credentialName)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleBadRequest(response, request, err)
return
}
response.WriteEntity(servererr.None)
}
/*
Copyright 2020 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 v1alpha3
import (
"github.com/emicklei/go-restful"
restfulspec "github.com/emicklei/go-restful-openapi"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3"
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/constants"
devopsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
"net/http"
)
const (
GroupName = "devops.kubesphere.io"
RespOK = "ok"
)
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha3"}
func AddToContainer(container *restful.Container, devopsClient devopsClient.Interface,
k8sclient kubernetes.Interface, ksclient kubesphere.Interface,
ksInformers externalversions.SharedInformerFactory,
k8sInformers informers.SharedInformerFactory) error {
devopsEnable := devopsClient != nil
if devopsEnable {
ws := runtime.NewWebService(GroupVersion)
handler := newDevOpsHandler(devopsClient, k8sclient, ksclient, ksInformers, k8sInformers)
// credential
ws.Route(ws.GET("/workspaces/{workspace}/devopsprojects/{projectName}/credential/").
To(handler.ListCredential).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("projectName", "devops name")).
Doc("list the credential of the specified devops for the current user").
Returns(http.StatusOK, api.StatusOK, []v1alpha3.PipelineList{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectTag}))
ws.Route(ws.POST("/workspaces/{workspace}/devopsprojects/{projectName}/credential/").
To(handler.CreateCredential).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("projectName", "devops name")).
Doc("create the credential of the specified devops for the current user").
Returns(http.StatusOK, api.StatusOK, []v1alpha3.Pipeline{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectTag}))
ws.Route(ws.GET("/workspaces/{workspace}/devopsprojects/{projectName}/credential/{credentialName}/").
To(handler.GetCredential).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("projectName", "project name")).
Param(ws.PathParameter("credential", "pipeline name")).
Doc("get the credential of the specified devops for the current user").
Returns(http.StatusOK, api.StatusOK, []v1.Secret{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectTag}))
ws.Route(ws.PUT("/workspaces/{workspace}/devopsprojects/{projectName}/credential/{credentialName}/").
To(handler.UpdateCredential).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("projectName", "project name")).
Param(ws.PathParameter("credentialName", "credential name")).
Doc("put the credential of the specified devops for the current user").
Returns(http.StatusOK, api.StatusOK, []v1.Secret{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectTag}))
ws.Route(ws.DELETE("/workspaces/{workspace}/devopsprojects/{projectName}/credential/{credentialName}/").
To(handler.DeleteCredential).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("projectName", "project name")).
Param(ws.PathParameter("credentialName", "credential name")).
Doc("delete the credential of the specified devops for the current user").
Returns(http.StatusOK, api.StatusOK, []v1.Secret{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsPipelineTag}))
// pipeline
ws.Route(ws.GET("/workspaces/{workspace}/devopsprojects/{projectName}/pipelines/").
To(handler.ListPipeline).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("projectName", "devops name")).
Doc("list the pipeline of the specified devops for the current user").
Returns(http.StatusOK, api.StatusOK, []v1alpha3.PipelineList{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectTag}))
ws.Route(ws.POST("/workspaces/{workspace}/devopsprojects/{projectName}/pipelines/").
To(handler.CreatePipeline).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("projectName", "devops name")).
Doc("create the pipeline of the specified devops for the current user").
Returns(http.StatusOK, api.StatusOK, []v1alpha3.Pipeline{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectTag}))
ws.Route(ws.GET("/workspaces/{workspace}/devopsprojects/{projectName}/pipelines/{pipelineName}/").
To(handler.GetPipeline).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("projectName", "project name")).
Param(ws.PathParameter("pipelineName", "pipeline name")).
Doc("get the pipeline of the specified devops for the current user").
Returns(http.StatusOK, api.StatusOK, []v1alpha3.Pipeline{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectTag}))
ws.Route(ws.PUT("/workspaces/{workspace}/devopsprojects/{projectName}/pipelines/{pipelineName}/").
To(handler.UpdatePipeline).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("projectName", "project name")).
Param(ws.PathParameter("pipelineName", "pipeline name")).
Doc("put the pipeline of the specified devops for the current user").
Returns(http.StatusOK, api.StatusOK, []v1alpha3.Pipeline{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectTag}))
ws.Route(ws.DELETE("/workspaces/{workspace}/devopsprojects/{projectName}/pipelines/{pipelineName}/").
To(handler.DeletePipeline).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("projectName", "project name")).
Param(ws.PathParameter("pipelineName", "pipeline name")).
Doc("delete the pipeline of the specified devops for the current user").
Returns(http.StatusOK, api.StatusOK, []v1alpha3.Pipeline{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsPipelineTag}))
// devops
ws.Route(ws.GET("/workspaces/{workspace}/devopsprojects/").
To(handler.ListDevOpsProject).
Param(ws.PathParameter("workspace", "workspace name")).
Doc("List the devopsproject of the specified workspace for the current user").
Returns(http.StatusOK, api.StatusOK, []v1alpha3.DevOpsProjectList{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectTag}))
ws.Route(ws.POST("/workspaces/{workspace}/devopsprojects/").
To(handler.CreateDevOpsProject).
Param(ws.PathParameter("workspace", "workspace name")).
Doc("Create the devopsproject of the specified workspace for the current user").
Returns(http.StatusOK, api.StatusOK, []v1alpha3.DevOpsProject{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectTag}))
ws.Route(ws.GET("/workspaces/{workspace}/devopsprojects/{projectName}/").
To(handler.GetDevOpsProject).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("projectName", "project name")).
Doc("Get the devopsproject of the specified workspace for the current user").
Returns(http.StatusOK, api.StatusOK, []v1alpha3.DevOpsProject{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectTag}))
ws.Route(ws.PUT("/workspaces/{workspace}/devopsprojects/{projectName}/").
To(handler.UpdateDevOpsProject).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("projectName", "project name")).
Doc("Put the devopsproject of the specified workspace for the current user").
Returns(http.StatusOK, api.StatusOK, []v1alpha3.DevOpsProject{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectTag}))
ws.Route(ws.DELETE("/workspaces/{workspace}/devopsprojects/{projectName}/").
To(handler.DeleteDevOpsProject).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("projectName", "project name")).
Doc("Get the devopsproject of the specified workspace for the current user").
Returns(http.StatusOK, api.StatusOK, []v1alpha3.DevOpsProject{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectTag}))
container.Add(ws)
}
return nil
}
......@@ -23,7 +23,15 @@ import (
"fmt"
"io"
"io/ioutil"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3"
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/simple/client/devops"
"net/http"
"sync"
......@@ -34,6 +42,24 @@ const (
)
type DevopsOperator interface {
CreateDevOpsProject(workspace string, project *v1alpha3.DevOpsProject) (*v1alpha3.DevOpsProject, error)
GetDevOpsProject(workspace string, projectName string) (*v1alpha3.DevOpsProject, error)
DeleteDevOpsProject(workspace string, projectName string) error
UpdateDevOpsProject(workspace string, project *v1alpha3.DevOpsProject) (*v1alpha3.DevOpsProject, error)
ListDevOpsProject(workspace string) (*v1alpha3.DevOpsProjectList, error)
CreatePipelineObj(workspace string, projectName string, pipeline *v1alpha3.Pipeline) (*v1alpha3.Pipeline, error)
GetPipelineObj(workspace string, projectName string, pipelineName string) (*v1alpha3.Pipeline, error)
DeletePipelineObj(workspace string, projectName string, pipelineName string) error
UpdatePipelineObj(workspace string, projectName string, pipeline *v1alpha3.Pipeline) (*v1alpha3.Pipeline, error)
ListPipelineObj(workspace string, projectName string) (*v1alpha3.PipelineList, error)
CreateCredentialObj(workspace string, projectName string, s *v1.Secret) (*v1.Secret, error)
GetCredentialObj(workspace string, projectName string, secretName string) (*v1.Secret, error)
DeleteCredentialObj(workspace string, projectName string, secretName string) error
UpdateCredentialObj(workspace string, projectName string, secret *v1.Secret) (*v1.Secret, error)
ListCredentialObj(workspace string, projectName string) (*v1.SecretList, error)
GetPipeline(projectName, pipelineName string, req *http.Request) (*devops.Pipeline, error)
ListPipelines(req *http.Request) (*devops.PipelineList, error)
GetPipelineRun(projectName, pipelineName, runId string, req *http.Request) (*devops.PipelineRun, error)
......@@ -85,10 +111,21 @@ type DevopsOperator interface {
type devopsOperator struct {
devopsClient devops.Interface
k8sclient kubernetes.Interface
ksclient kubesphere.Interface
ksInformers externalversions.SharedInformerFactory
k8sInformers informers.SharedInformerFactory
}
func NewDevopsOperator(client devops.Interface) DevopsOperator {
return &devopsOperator{devopsClient: client}
func NewDevopsOperator(client devops.Interface, k8sclient kubernetes.Interface, ksclient kubesphere.Interface,
ksInformers externalversions.SharedInformerFactory, k8sInformers informers.SharedInformerFactory) DevopsOperator {
return &devopsOperator{
devopsClient: client,
k8sclient: k8sclient,
ksclient: ksclient,
ksInformers: ksInformers,
k8sInformers: k8sInformers,
}
}
func convertToHttpParameters(req *http.Request) *devops.HttpParameters {
......@@ -104,6 +141,111 @@ func convertToHttpParameters(req *http.Request) *devops.HttpParameters {
return &httpParameters
}
func (d devopsOperator) CreateDevOpsProject(workspace string, project *v1alpha3.DevOpsProject) (*v1alpha3.DevOpsProject, error) {
project.Annotations[tenantv1alpha1.WorkspaceLabel] = workspace
return d.ksclient.DevopsV1alpha3().DevOpsProjects().Create(project)
}
func (d devopsOperator) GetDevOpsProject(workspace string, projectName string) (*v1alpha3.DevOpsProject, error) {
return d.ksclient.DevopsV1alpha3().DevOpsProjects().Get(projectName, metav1.GetOptions{})
}
func (d devopsOperator) DeleteDevOpsProject(workspace string, projectName string) error {
return d.ksclient.DevopsV1alpha3().DevOpsProjects().Delete(projectName, metav1.NewDeleteOptions(0))
}
func (d devopsOperator) UpdateDevOpsProject(workspace string, project *v1alpha3.DevOpsProject) (*v1alpha3.DevOpsProject, error) {
project.Annotations[tenantv1alpha1.WorkspaceLabel] = workspace
return d.ksclient.DevopsV1alpha3().DevOpsProjects().Update(project)
}
func (d devopsOperator) ListDevOpsProject(workspace string) (*v1alpha3.DevOpsProjectList, error) {
return d.ksclient.DevopsV1alpha3().DevOpsProjects().List(metav1.ListOptions{})
}
// pipelineobj in crd
func (d devopsOperator) CreatePipelineObj(workspace string, projectName string, pipeline *v1alpha3.Pipeline) (*v1alpha3.Pipeline, error) {
projectObj, err := d.ksclient.DevopsV1alpha3().DevOpsProjects().Get(projectName, metav1.GetOptions{})
if err != nil {
return nil, err
}
return d.ksclient.DevopsV1alpha3().Pipelines(projectObj.Status.AdminNamespace).Create(pipeline)
}
func (d devopsOperator) GetPipelineObj(workspace string, projectName string, pipelineName string) (*v1alpha3.Pipeline, error) {
projectObj, err := d.ksclient.DevopsV1alpha3().DevOpsProjects().Get(projectName, metav1.GetOptions{})
if err != nil {
return nil, err
}
return d.ksclient.DevopsV1alpha3().Pipelines(projectObj.Status.AdminNamespace).Get(pipelineName, metav1.GetOptions{})
}
func (d devopsOperator) DeletePipelineObj(workspace string, projectName string, pipelineName string) error {
projectObj, err := d.ksclient.DevopsV1alpha3().DevOpsProjects().Get(projectName, metav1.GetOptions{})
if err != nil {
return err
}
return d.ksclient.DevopsV1alpha3().Pipelines(projectObj.Status.AdminNamespace).Delete(pipelineName, metav1.NewDeleteOptions(0))
}
func (d devopsOperator) UpdatePipelineObj(workspace string, projectName string, pipeline *v1alpha3.Pipeline) (*v1alpha3.Pipeline, error) {
projectObj, err := d.ksclient.DevopsV1alpha3().DevOpsProjects().Get(projectName, metav1.GetOptions{})
if err != nil {
return nil, err
}
return d.ksclient.DevopsV1alpha3().Pipelines(projectObj.Status.AdminNamespace).Update(pipeline)
}
func (d devopsOperator) ListPipelineObj(workspace string, projectName string) (*v1alpha3.PipelineList, error) {
projectObj, err := d.ksclient.DevopsV1alpha3().DevOpsProjects().Get(projectName, metav1.GetOptions{})
if err != nil {
return nil, err
}
return d.ksclient.DevopsV1alpha3().Pipelines(projectObj.Status.AdminNamespace).List(metav1.ListOptions{})
}
//credentialobj in crd
func (d devopsOperator) CreateCredentialObj(workspace string, projectName string, secret *v1.Secret) (*v1.Secret, error) {
projectObj, err := d.ksclient.DevopsV1alpha3().DevOpsProjects().Get(projectName, metav1.GetOptions{})
if err != nil {
return nil, err
}
return d.k8sclient.CoreV1().Secrets(projectObj.Status.AdminNamespace).Create(secret)
}
func (d devopsOperator) GetCredentialObj(workspace string, projectName string, secretName string) (*v1.Secret, error) {
projectObj, err := d.ksclient.DevopsV1alpha3().DevOpsProjects().Get(projectName, metav1.GetOptions{})
if err != nil {
return nil, err
}
return d.k8sclient.CoreV1().Secrets(projectObj.Status.AdminNamespace).Get(secretName, metav1.GetOptions{})
}
func (d devopsOperator) DeleteCredentialObj(workspace string, projectName string, secret string) error {
projectObj, err := d.ksclient.DevopsV1alpha3().DevOpsProjects().Get(projectName, metav1.GetOptions{})
if err != nil {
return err
}
return d.k8sclient.CoreV1().Secrets(projectObj.Status.AdminNamespace).Delete(secret, metav1.NewDeleteOptions(0))
}
func (d devopsOperator) UpdateCredentialObj(workspace string, projectName string, secret *v1.Secret) (*v1.Secret, error) {
projectObj, err := d.ksclient.DevopsV1alpha3().DevOpsProjects().Get(projectName, metav1.GetOptions{})
if err != nil {
return nil, err
}
return d.k8sclient.CoreV1().Secrets(projectObj.Status.AdminNamespace).Update(secret)
}
func (d devopsOperator) ListCredentialObj(workspace string, projectName string) (*v1.SecretList, error) {
projectObj, err := d.ksclient.DevopsV1alpha3().DevOpsProjects().Get(projectName, metav1.GetOptions{})
if err != nil {
return nil, err
}
return d.k8sclient.CoreV1().Secrets(projectObj.Status.AdminNamespace).List(metav1.ListOptions{})
}
// others
func (d devopsOperator) GetPipeline(projectName, pipelineName string, req *http.Request) (*devops.Pipeline, error) {
res, err := d.devopsClient.GetPipeline(projectName, pipelineName, convertToHttpParameters(req))
......
......@@ -44,7 +44,7 @@ func TestGetNodesDetail(t *testing.T) {
devopsClient := fake.NewFakeDevops(fakeData)
devopsOperator := NewDevopsOperator(devopsClient)
devopsOperator := NewDevopsOperator(devopsClient, nil, nil, nil, nil)
httpReq, _ := http.NewRequest(http.MethodGet, baseUrl+"devops/project1/pipelines/pipeline1/runs/run1/nodesdetail/?limit=10000", nil)
......@@ -96,7 +96,7 @@ func TestGetBranchNodesDetail(t *testing.T) {
devopsClient := fake.NewFakeDevops(fakeData)
devopsOperator := NewDevopsOperator(devopsClient)
devopsOperator := NewDevopsOperator(devopsClient, nil, nil, nil, nil)
httpReq, _ := http.NewRequest(http.MethodGet, baseUrl+"devops/project1/pipelines/pipeline1/branchs/branch1/runs/run1/nodesdetail/?limit=10000", nil)
......
......@@ -44,7 +44,7 @@ var node = &corev1.Node{
}
var pods = []*corev1.Pod{
&corev1.Pod{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "foo",
Name: "pod-with-resources",
......@@ -69,7 +69,7 @@ var pods = []*corev1.Pod{
Phase: corev1.PodRunning,
},
},
&corev1.Pod{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "foo2",
Name: "pod-with-resources",
......
......@@ -233,6 +233,7 @@ func (j *Jenkins) CreateCredentialInProject(projectId string, credential *v1.Sec
if err != nil {
return "", err
}
if response.StatusCode != http.StatusOK {
return "", errors.New(strconv.Itoa(response.StatusCode))
}
......
......@@ -407,7 +407,7 @@ func (j *Jenkins) ListPipelineRuns(projectName, pipelineName string, httpParamet
PipelineOjb := &Pipeline{
HttpParameters: httpParameters,
Jenkins: j,
Path: ListPipelineRunUrl + httpParameters.Url.RawQuery,
Path: fmt.Sprintf(ListPipelineRunUrl, projectName, pipelineName) + httpParameters.Url.RawQuery,
}
res, err := PipelineOjb.ListPipelineRuns()
return res, err
......
......@@ -145,7 +145,7 @@ func (p *Pipeline) ListPipelineRuns() (*devops.PipelineRunList, error) {
}
var pipelineRunList devops.PipelineRunList
err = json.Unmarshal(res, &pipelineRunList)
err = json.Unmarshal(res, &pipelineRunList.Items)
if err != nil {
klog.Error(err)
return nil, err
......
......@@ -80,86 +80,7 @@ type Pipeline struct {
// GetPipeBranchRun & SearchPipelineRuns
type PipelineRunList struct {
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability."`
Links struct {
PrevRun struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
} `json:"prevRun,omitempty"`
Parent struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
} `json:"parent,omitempty"`
Tests struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
} `json:"tests,omitempty"`
Nodes struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
} `json:"nodes,omitempty"`
Log struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
} `json:"log,omitempty"`
Self struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
} `json:"self,omitempty"`
BlueTestSummary struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
} `json:"blueTestSummary,omitempty"`
Actions struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
} `json:"actions,omitempty"`
Steps struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
} `json:"steps,omitempty"`
Artifacts struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
} `json:"artifacts,omitempty"`
NextRun struct {
Class string `json:"_class,omitempty"`
Href string `json:"href,omitempty"`
} `json:"nextRun,omitempty"`
} `json:"_links,omitempty" description:"references the reachable path to this resource"`
Actions []interface{} `json:"actions,omitempty" description:"the list of all actions"`
ArtifactsZipFile interface{} `json:"artifactsZipFile,omitempty" description:"the artifacts zip file"`
CauseOfBlockage interface{} `json:"causeOfBlockage,omitempty" description:"the cause of blockage"`
Causes []struct {
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability."`
ShortDescription string `json:"shortDescription,omitempty" description:"short description"`
UserID string `json:"userId,omitempty" description:"user id"`
UserName string `json:"userName,omitempty" description:"user name"`
} `json:"causes,omitempty"`
ChangeSet []interface{} `json:"changeSet,omitempty" description:"changeset information"`
Description interface{} `json:"description,omitempty" description:"description of resource"`
DurationInMillis int `json:"durationInMillis,omitempty" description:"duration time in millis"`
EnQueueTime string `json:"enQueueTime,omitempty" description:"the time of enter the queue"`
EndTime string `json:"endTime,omitempty" description:"the time of end"`
EstimatedDurationInMillis int `json:"estimatedDurationInMillis,omitempty" description:"estimated duration time, unit is millis"`
ID string `json:"id,omitempty" description:"id"`
Name interface{} `json:"name,omitempty" description:"name"`
Organization string `json:"organization,omitempty" description:"the name of organization"`
Pipeline string `json:"pipeline,omitempty" description:"pipeline name"`
Replayable bool `json:"replayable,omitempty" description:"replayable or not"`
Result string `json:"result,omitempty" description:"the result of pipeline run. e.g. SUCCESS"`
RunSummary string `json:"runSummary,omitempty" description:"pipeline run summary"`
StartTime string `json:"startTime,omitempty" description:"the time of start"`
State string `json:"state,omitempty" description:"run state. e.g. RUNNING"`
Type string `json:"type,omitempty" description:"source type, such as \"WorkflowRun\""`
Branch struct {
IsPrimary bool `json:"isPrimary,omitempty" description:"primary or not"`
Issues []interface{} `json:"issues,omitempty" description:"issues"`
URL string `json:"url,omitempty" description:"url"`
} `json:"branch,omitempty"`
CommitID string `json:"commitId,omitempty" description:"commit id"`
CommitURL interface{} `json:"commitUrl,omitempty" description:"commit url "`
PullRequest interface{} `json:"pullRequest,omitempty" description:"pull request"`
Items []PipelineRun `json:"items"`
}
// GetBranchPipeRunNodes
......@@ -462,7 +383,9 @@ type Artifacts struct {
}
// GetPipeBranch
type PipelineBranch struct {
type PipelineBranch []PipelineBranchItem
type PipelineBranchItem struct {
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability."`
Links struct {
Self struct {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册