Skip to content

Commit 353f62c

Browse files
Merge pull request #1069 from renyunkang/master
support to delete pipelinerun
2 parents 04a0842 + d5e51b6 commit 353f62c

File tree

4 files changed

+106
-6
lines changed

4 files changed

+106
-6
lines changed

controllers/jenkins/pipelinerun/pipelinerun_controller.go

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"fmt"
2323
"net/http"
2424
"reflect"
25+
"strconv"
2526
"strings"
2627
"time"
2728

@@ -43,6 +44,7 @@ import (
4344
cmstore "github.com/kubesphere/ks-devops/pkg/store/configmap"
4445
storeInter "github.com/kubesphere/ks-devops/pkg/store/store"
4546
"github.com/kubesphere/ks-devops/pkg/utils/k8sutil"
47+
"github.com/kubesphere/ks-devops/pkg/utils/sliceutil"
4648
)
4749

4850
// BuildNotExistMsg indicates the build with pipelinerun-id not exist in jenkins
@@ -86,16 +88,54 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
8688

8789
// DeletionTimestamp.IsZero() means copyPipeline has not been deleted.
8890
if !pipelineRunCopied.ObjectMeta.DeletionTimestamp.IsZero() {
89-
if err = jHandler.deleteJenkinsJobHistory(pipelineRunCopied); err != nil {
91+
// if the annotation value is true, we should keep the record in Jenkins
92+
if keep, err := strconv.ParseBool(pipelineRunCopied.Annotations[v1alpha3.PipelineRunKeepJenkinsRecordAnnoKey]); err == nil && keep {
93+
klog.V(4).Infof("try to delete PipelineRun: %s/%s, but need to keep Jenkins record",
94+
pipelineRunCopied.Namespace, pipelineRunCopied.Name)
95+
} else if err = jHandler.deleteJenkinsJobHistory(pipelineRunCopied); err != nil {
9096
klog.V(4).Infof("failed to delete Jenkins job history from PipelineRun: %s/%s, error: %v",
9197
pipelineRunCopied.Namespace, pipelineRunCopied.Name, err)
92-
} else {
93-
k8sutil.RemoveFinalizer(&pipelineRunCopied.ObjectMeta, v1alpha3.PipelineRunFinalizerName)
94-
err = r.Update(context.TODO(), pipelineRunCopied)
9598
}
99+
100+
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
101+
// Get the latest version of PipelineRun
102+
if err := r.Get(ctx, req.NamespacedName, pipelineRunCopied); err != nil {
103+
// ignore not found error
104+
return client.IgnoreNotFound(err)
105+
}
106+
107+
// Remove the finalizer
108+
pipelineRunCopied.ObjectMeta.Finalizers = sliceutil.RemoveString(pipelineRunCopied.ObjectMeta.Finalizers, func(item string) bool {
109+
return item == v1alpha3.PipelineRunFinalizerName
110+
})
111+
112+
// Try to update
113+
return r.Update(ctx, pipelineRunCopied)
114+
})
115+
96116
return ctrl.Result{}, err
97117
}
98118

119+
// add finalizer if it does not exist
120+
if !sliceutil.HasString(pipelineRunCopied.ObjectMeta.Finalizers, v1alpha3.PipelineRunFinalizerName) {
121+
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
122+
// Get the latest version of PipelineRun
123+
if err := r.Get(ctx, req.NamespacedName, pipelineRunCopied); err != nil {
124+
return err
125+
}
126+
// Add the finalizer if it's still not there
127+
if !sliceutil.HasString(pipelineRunCopied.ObjectMeta.Finalizers, v1alpha3.PipelineRunFinalizerName) {
128+
pipelineRunCopied.ObjectMeta.Finalizers = append(pipelineRunCopied.ObjectMeta.Finalizers, v1alpha3.PipelineRunFinalizerName)
129+
// Try to update
130+
return r.Update(ctx, pipelineRunCopied)
131+
}
132+
return nil // Finalizer was added by another process, no need to update
133+
})
134+
if err != nil {
135+
return ctrl.Result{}, err
136+
}
137+
}
138+
99139
// the PipelineRun cannot allow building
100140
if !pipelineRunCopied.Buildable() {
101141
return ctrl.Result{}, nil

pkg/api/devops/v1alpha3/pipelinerun_types.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,13 @@ import (
2424
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2525
)
2626

27-
// PipelineRunFinalizerName is the name of PipelineRun finalizer
28-
const PipelineRunFinalizerName = "pipelinerun.finalizers.kubesphere.io"
27+
const (
28+
// PipelineRunFinalizerName is the name of PipelineRun finalizer
29+
PipelineRunFinalizerName = "pipelinerun.finalizers.kubesphere.io"
30+
31+
// PipelineRunKeepJenkinsRecordAnnoKey is the annotation key of keeping Jenkins record
32+
PipelineRunKeepJenkinsRecordAnnoKey = "devops.kubesphere.io/keep-jenkins-record"
33+
)
2934

3035
// PipelineRunSpec defines the desired state of PipelineRun
3136
type PipelineRunSpec struct {

pkg/kapis/devops/v1alpha3/pipelinerun/handler.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"encoding/json"
2323
"fmt"
2424
"io"
25+
"net/http"
2526
"net/url"
2627
"strconv"
2728

@@ -286,3 +287,48 @@ func (h *apiHandler) downloadArtifact(request *restful.Request, response *restfu
286287
return
287288
}
288289
}
290+
291+
// deletePipelineRun deletes a specific PipelineRun of a Pipeline.
292+
func (h *apiHandler) deletePipelineRun(request *restful.Request, response *restful.Response) {
293+
nsName := request.PathParameter("namespace")
294+
runName := request.PathParameter("pipelinerun")
295+
keepJenkinsRecord := request.QueryParameter("keepJenkinsRecord")
296+
297+
ctx := request.Request.Context()
298+
// get the PipelineRun
299+
var pr v1alpha3.PipelineRun
300+
if err := h.client.Get(ctx, client.ObjectKey{Namespace: nsName, Name: runName}, &pr); err != nil {
301+
kapis.HandleError(request, response, err)
302+
return
303+
}
304+
305+
// check if the PipelineRun is in a final state
306+
switch pr.Status.Phase {
307+
case v1alpha3.Succeeded, v1alpha3.Failed, v1alpha3.Cancelled:
308+
// allow to delete
309+
default:
310+
// if the PipelineRun is still running, we should not delete it
311+
err := fmt.Errorf("cannot delete a running PipelineRun, please stop it first, current status is %s", pr.Status.Phase)
312+
kapis.HandleBadRequest(response, request, err)
313+
return
314+
}
315+
316+
// check if we need to keep the record in Jenkins
317+
if keep, err := strconv.ParseBool(keepJenkinsRecord); err == nil && keep {
318+
if pr.Annotations == nil {
319+
pr.Annotations = make(map[string]string)
320+
}
321+
pr.Annotations[v1alpha3.PipelineRunKeepJenkinsRecordAnnoKey] = "true"
322+
if err := h.client.Update(ctx, &pr); err != nil {
323+
kapis.HandleError(request, response, err)
324+
return
325+
}
326+
}
327+
328+
// delete the CR
329+
if err := h.client.Delete(ctx, &pr); err != nil {
330+
kapis.HandleError(request, response, err)
331+
return
332+
}
333+
response.WriteHeader(http.StatusOK)
334+
}

pkg/kapis/devops/v1alpha3/pipelinerun/register.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,13 @@ func RegisterRoutes(ws *restful.WebService, devopsClient dclient.Interface, c cl
8989
To(handler.downloadArtifact).
9090
Returns(http.StatusOK, api.StatusOK, nil).
9191
Metadata(restfulspec.KeyOpenAPITags, constants.DevOpsPipelineTags))
92+
93+
// delete a pipelinerun of a pipeline
94+
ws.Route(ws.DELETE("/namespaces/{namespace}/pipelineruns/{pipelinerun}").
95+
To(handler.deletePipelineRun).
96+
Doc("Delete a pipelinerun of a pipeline.").
97+
Param(ws.PathParameter("namespace", "The namespace of the pipeline.")).
98+
Param(ws.PathParameter("pipelinerun", "The name of the pipelinerun.")).
99+
Param(ws.QueryParameter("keepJenkinsRecord", "Whether to keep the record in Jenkins. Default is false.")).
100+
Returns(http.StatusOK, "OK", nil))
92101
}

0 commit comments

Comments
 (0)