Repository: kurator-dev/kurator
Pull request #552 (2024-01-10 03:05:08)

pipeline: update the api field json
**What type of PR is this?**


/kind api-change
/kind bug


**What this PR does / why we need it**:

The original field name and the content of the JSON are inconsistent, and here it is being corrected.



Patch:
diff --git a/docs/content/en/references/pipeline_v1alpha1_types.html b/docs/content/en/references/pipeline_v1alpha1_types.html
index 58054e8..fa300d1 100644
--- a/docs/content/en/references/pipeline_v1alpha1_types.html
+++ b/docs/content/en/references/pipeline_v1alpha1_types.html
@@ -204,7 +204,7 @@ Cannot be updated.</p>
 </tr>
 <tr>
 <td>
-<code>computeResources</code><br>
+<code>resourceRequirements</code><br>
 <em>
 <a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#resourcerequirements-v1-core">
 Kubernetes core/v1.ResourceRequirements
@@ -518,7 +518,7 @@ This affects how the volume can be mounted.
 </tr>
 <tr>
 <td>
-<code>requestsStorage</code><br>
+<code>storageRequest</code><br>
 <em>
 string
 </em>
diff --git a/manifests/charts/fleet-manager/crds/pipeline.kurator.dev_pipelines.yaml b/manifests/charts/fleet-manager/crds/pipeline.kurator.dev_pipelines.yaml
index fe14da7..b9378b5 100644
--- a/manifests/charts/fleet-manager/crds/pipeline.kurator.dev_pipelines.yaml
+++ b/manifests/charts/fleet-manager/crds/pipeline.kurator.dev_pipelines.yaml
@@ -58,17 +58,17 @@ spec:
                       exactly 1 pod, cannot be used in combination with other access
                       modes
                     type: string
-                  requestsStorage:
-                    description: StorageRequest defines the storage size required
-                      for this PVC, e.g., 1Gi, 100Mi. It specifies the storage capacity
-                      needed as part of ResourceRequirements.
-                    pattern: ^[0-9]+(\.[0-9]+)?(Gi|Mi)$
-                    type: string
                   storageClassName:
                     description: StorageClassName specifies the StorageClass name
                       to which this persistent volume belongs, e.g., manual. It allows
                       the PVC to use the characteristics defined by the StorageClass.
                     type: string
+                  storageRequest:
+                    description: StorageRequest defines the storage size required
+                      for this PVC, e.g., 1Gi, 100Mi. It specifies the storage capacity
+                      needed as part of ResourceRequirements.
+                    pattern: ^[0-9]+(\.[0-9]+)?(Gi|Mi)$
+                    type: string
                   volumeMode:
                     description: VolumeMode specifies whether the volume should be
                       used with a formatted filesystem (Filesystem) or remain in raw
@@ -107,57 +107,6 @@ spec:
                             type: string
                           type: array
                           x-kubernetes-list-type: atomic
-                        computeResources:
-                          description: 'ResourceRequirements required by this Step.
-                            Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
-                          properties:
-                            claims:
-                              description: "Claims lists the names of resources, defined
-                                in spec.resourceClaims, that are used by this container.
-                                \n This is an alpha field and requires enabling the
-                                DynamicResourceAllocation feature gate. \n This field
-                                is immutable. It can only be set for containers."
-                              items:
-                                description: ResourceClaim references one entry in
-                                  PodSpec.ResourceClaims.
-                                properties:
-                                  name:
-                                    description: Name must match the name of one entry
-                                      in pod.spec.resourceClaims of the Pod where
-                                      this field is used. It makes that resource available
-                                      inside a container.
-                                    type: string
-                                required:
-                                - name
-                                type: object
-                              type: array
-                              x-kubernetes-list-map-keys:
-                              - name
-                              x-kubernetes-list-type: map
-                            limits:
-                              additionalProperties:
-                                anyOf:
-                                - type: integer
-                                - type: string
-                                pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
-                                x-kubernetes-int-or-string: true
-                              description: 'Limits describes the maximum amount of
-                                compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
-                              type: object
-                            requests:
-                              additionalProperties:
-                                anyOf:
-                                - type: integer
-                                - type: string
-                                pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
-                                x-kubernetes-int-or-string: true
-                              description: 'Requests describes the minimum amount
-                                of compute resources required. If Requests is omitted
-                                for a container, it defaults to Limits if that is
-                                explicitly specified, otherwise to an implementation-defined
-                                value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
-                              type: object
-                          type: object
                         env:
                           description: List of environment variables to set in the
                             Step. Cannot be updated.
@@ -279,6 +228,57 @@ spec:
                           description: 'Image specifies the Docker image name. More
                             info: https://kubernetes.io/docs/concepts/containers/images'
                           type: string
+                        resourceRequirements:
+                          description: 'ResourceRequirements required by this Step.
+                            Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
+                          properties:
+                            claims:
+                              description: "Claims lists the names of resources, defined
+                                in spec.resourceClaims, that are used by this container.
+                                \n This is an alpha field and requires enabling the
+                                DynamicResourceAllocation feature gate. \n This field
+                                is immutable. It can only be set for containers."
+                              items:
+                                description: ResourceClaim references one entry in
+                                  PodSpec.ResourceClaims.
+                                properties:
+                                  name:
+                                    description: Name must match the name of one entry
+                                      in pod.spec.resourceClaims of the Pod where
+                                      this field is used. It makes that resource available
+                                      inside a container.
+                                    type: string
+                                required:
+                                - name
+                                type: object
+                              type: array
+                              x-kubernetes-list-map-keys:
+                              - name
+                              x-kubernetes-list-type: map
+                            limits:
+                              additionalProperties:
+                                anyOf:
+                                - type: integer
+                                - type: string
+                                pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                x-kubernetes-int-or-string: true
+                              description: 'Limits describes the maximum amount of
+                                compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
+                              type: object
+                            requests:
+                              additionalProperties:
+                                anyOf:
+                                - type: integer
+                                - type: string
+                                pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                x-kubernetes-int-or-string: true
+                              description: 'Requests describes the minimum amount
+                                of compute resources required. If Requests is omitted
+                                for a container, it defaults to Limits if that is
+                                explicitly specified, otherwise to an implementation-defined
+                                value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
+                              type: object
+                          type: object
                         script:
                           description: Script is the contents of an executable file
                             to execute. If Script is not empty, the CustomTask cannot
diff --git a/manifests/charts/fleet-manager/templates/rbac.yaml b/manifests/charts/fleet-manager/templates/rbac.yaml
index 3636921..50abbf8 100644
--- a/manifests/charts/fleet-manager/templates/rbac.yaml
+++ b/manifests/charts/fleet-manager/templates/rbac.yaml
@@ -162,7 +162,6 @@ rules:
       - create
       - delete
       - list
-      - update
   - apiGroups:
       - "source.toolkit.fluxcd.io"
     resources:
diff --git a/pkg/apis/pipeline/v1alpha1/type.go b/pkg/apis/pipeline/v1alpha1/type.go
index a487be7..e234b98 100644
--- a/pkg/apis/pipeline/v1alpha1/type.go
+++ b/pkg/apis/pipeline/v1alpha1/type.go
@@ -68,7 +68,7 @@ type VolumeClaimTemplate struct {
 	// StorageRequest defines the storage size required for this PVC, e.g., 1Gi, 100Mi.
 	// It specifies the storage capacity needed as part of ResourceRequirements.
 	// +kubebuilder:validation:Pattern="^[0-9]+(\\.[0-9]+)?(Gi|Mi)$"
-	StorageRequest string `json:"requestsStorage,omitempty"`
+	StorageRequest string `json:"storageRequest,omitempty"`
 
 	// StorageClassName specifies the StorageClass name to which this persistent volume belongs, e.g., manual.
 	// It allows the PVC to use the characteristics defined by the StorageClass.
@@ -214,7 +214,7 @@ type CustomTask struct {
 	// Cannot be updated.
 	// More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
 	// +optional
-	ResourceRequirements corev1.ResourceRequirements `json:"computeResources,omitempty"`
+	ResourceRequirements corev1.ResourceRequirements `json:"resourceRequirements,omitempty"`
 
 	// Script is the contents of an executable file to execute.
 	// If Script is not empty, the CustomTask cannot have a Command and the Args will be passed to the Script.
diff --git a/pkg/fleet-manager/application/helper.go b/pkg/fleet-manager/application/helper.go
index a2d427b..41574cb 100644
--- a/pkg/fleet-manager/application/helper.go
+++ b/pkg/fleet-manager/application/helper.go
@@ -41,9 +41,8 @@ import (
 
 // syncPolicyResource synchronizes the sync policy resources for a given application.
 func (a *ApplicationManager) syncPolicyResource(ctx context.Context, app *applicationapi.Application, fleet *fleetapi.Fleet, syncPolicy *applicationapi.ApplicationSyncPolicy, policyName string) (ctrl.Result, error) {
-	log := ctrl.LoggerFrom(ctx)
-
 	policyKind := getSyncPolicyKind(syncPolicy)
+
 	destination := getPolicyDestination(app, syncPolicy)
 
 	// fetch fleet cluster list that recorded in fleet and matches the destination's cluster selector
@@ -61,19 +60,6 @@ func (a *ApplicationManager) syncPolicyResource(ctx context.Context, app *applic
 		}
 	}
 
-	if syncPolicy.Rollout != nil {
-		// after finish application install, start handling rollout policy
-		rolloutClusters, err := a.fetchRolloutClusters(ctx, app, a.Client, fleet, syncPolicy)
-		if err != nil {
-			log.Error(err, "failed to fetch destination clusters for rollout")
-			return ctrl.Result{}, err
-		}
-
-		if result, err := a.syncRolloutPolicyForCluster(ctx, syncPolicy.Rollout, rolloutClusters, policyName); err != nil {
-			return result, errors.Wrapf(err, "failed to syncRolloutPolicy")
-		}
-	}
-
 	return ctrl.Result{}, nil
 }
 
diff --git a/pkg/fleet-manager/application/rollout_helper.go b/pkg/fleet-manager/application/rollout_helper.go
deleted file mode 100644
index c66d8a2..0000000
--- a/pkg/fleet-manager/application/rollout_helper.go
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
-Copyright Kurator 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 application
-
-import (
-	"context"
-	"fmt"
-	"time"
-
-	flaggerv1b1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
-	"github.com/pkg/errors"
-	appsv1 "k8s.io/api/apps/v1"
-	corev1 "k8s.io/api/core/v1"
-	apierrors "k8s.io/apimachinery/pkg/api/errors"
-	"k8s.io/apimachinery/pkg/types"
-	ctrl "sigs.k8s.io/controller-runtime"
-	"sigs.k8s.io/controller-runtime/pkg/client"
-
-	applicationapi "kurator.dev/kurator/pkg/apis/apps/v1alpha1"
-	fleetapi "kurator.dev/kurator/pkg/apis/fleet/v1alpha1"
-	fleetmanager "kurator.dev/kurator/pkg/fleet-manager"
-	render "kurator.dev/kurator/pkg/fleet-manager/application/manifests"
-	plugin "kurator.dev/kurator/pkg/fleet-manager/plugin"
-	"kurator.dev/kurator/pkg/infra/util"
-)
-
-const (
-	// kurator rollout labels
-	RolloutIdentifier = "kurator.dev/rollout"
-	sidecarInject     = "istio-injection"
-
-	// StatusSyncInterval specifies the interval for requeueing when synchronizing status. It determines how frequently the status should be checked and updated.
-	StatusSyncInterval = 30 * time.Second
-)
-
-func (a *ApplicationManager) fetchRolloutClusters(ctx context.Context,
-	app *applicationapi.Application,
-	kubeClient client.Client,
-	fleet *fleetapi.Fleet,
-	syncPolicy *applicationapi.ApplicationSyncPolicy,
-) (map[fleetmanager.ClusterKey]*fleetmanager.FleetCluster, error) {
-	log := ctrl.LoggerFrom(ctx)
-	destination := getPolicyDestination(app, syncPolicy)
-	ClusterInterfaceList, result, err := a.fetchFleetClusterList(ctx, fleet, destination.ClusterSelector)
-	if err != nil || result.RequeueAfter > 0 {
-		return nil, err
-	}
-
-	fleetclusters := make(map[fleetmanager.ClusterKey]*fleetmanager.FleetCluster, len(ClusterInterfaceList))
-	for _, cluster := range ClusterInterfaceList {
-		kclient, err := fleetmanager.ClientForCluster(kubeClient, fleet.Namespace, cluster)
-		if err != nil {
-			return nil, err
-		}
-
-		kind := cluster.GetObject().GetObjectKind().GroupVersionKind().Kind
-		fleetclusters[fleetmanager.ClusterKey{Kind: kind, Name: cluster.GetObject().GetName()}] = &fleetmanager.FleetCluster{
-			Secret:    cluster.GetSecretName(),
-			SecretKey: cluster.GetSecretKey(),
-			Client:    kclient,
-		}
-	}
-	log.Info("Successful to fetch destination clusters for Rollout")
-	return fleetclusters, nil
-}
-
-func (a *ApplicationManager) syncRolloutPolicyForCluster(ctx context.Context,
-	rolloutPolicy *applicationapi.RolloutConfig,
-	destinationClusters map[fleetmanager.ClusterKey]*fleetmanager.FleetCluster,
-	policyName string,
-) (ctrl.Result, error) {
-	log := ctrl.LoggerFrom(ctx)
-
-	serviceNamespaceName := types.NamespacedName{
-		Namespace: rolloutPolicy.Workload.Namespace,
-		Name:      rolloutPolicy.ServiceName,
-	}
-
-	testloaderNamespaceName := types.NamespacedName{
-		Namespace: rolloutPolicy.Workload.Namespace,
-		Name:      rolloutPolicy.Workload.Name + "-testloader",
-	}
-
-	annotation := map[string]string{
-		RolloutIdentifier: policyName,
-	}
-
-	for clusterKey, fleetCluster := range destinationClusters {
-		fleetClusterClient := fleetCluster.Client.CtrlRuntimeClient()
-
-		// If the trafficRoutingProvider is Istio, add the sidecar injection label to the workload's namespace.
-		if rolloutPolicy.TrafficRoutingProvider == "istio" {
-			err := enableIstioSidecarInjection(ctx, fleetClusterClient, rolloutPolicy.Workload.Namespace)
-			if err != nil {
-				return ctrl.Result{}, errors.Wrapf(err, "failed to set namespace %s istio-injection enable", rolloutPolicy.Workload.Namespace)
-			}
-		}
-
-		// if delete private testloader when rollout polity has changed
-		if rolloutPolicy.TestLoader == nil || !*rolloutPolicy.TestLoader {
-			testloaderDeploy := &appsv1.Deployment{}
-			if err := deleteResourceCreatedByKurator(ctx, testloaderNamespaceName, fleetClusterClient, testloaderDeploy); err != nil {
-				return ctrl.Result{}, err
-			}
-			testloaderSvc := &corev1.Service{}
-			if err := deleteResourceCreatedByKurator(ctx, testloaderNamespaceName, fleetClusterClient, testloaderSvc); err != nil {
-				return ctrl.Result{}, err
-			}
-		} else {
-			// Installation of private testloader if needed
-			if err := installPrivateTestloader(ctx, testloaderNamespaceName, RolloutIdentifier, policyName); err != nil {
-				return ctrl.Result{}, fmt.Errorf("failed to install private testloader for workload: %w", err)
-			}
-		}
-
-		// Get the configuration of the workload's service and generate a canaryService.
-		service := &corev1.Service{}
-		if err := fleetClusterClient.Get(ctx, serviceNamespaceName, service); err != nil {
-			if apierrors.IsNotFound(err) {
-				return ctrl.Result{RequeueAfter: StatusSyncInterval}, errors.Wrapf(err, "not found service %s in %s", rolloutPolicy.ServiceName, rolloutPolicy.Workload.Namespace)
-			}
-			return ctrl.Result{}, errors.Wrapf(err, "failed to get service %s in %s", rolloutPolicy.ServiceName, rolloutPolicy.Workload.Namespace)
-		}
-
-		canaryInCluster := &flaggerv1b1.Canary{}
-		getErr := fleetClusterClient.Get(ctx, serviceNamespaceName, canaryInCluster)
-		if getErr != nil && !apierrors.IsNotFound(getErr) {
-			return ctrl.Result{}, errors.Wrapf(getErr, "failed to get canary %s in %s", serviceNamespaceName.Name, serviceNamespaceName.Namespace)
-		}
-
-		canaryInCluster = renderCanary(*rolloutPolicy, canaryInCluster)
-		if canaryService, err := renderCanaryService(*rolloutPolicy, service); err != nil {
-			return ctrl.Result{}, errors.Wrapf(err, "failed rander canary configuration")
-		} else {
-			canaryInCluster.Spec.Service = *canaryService
-		}
-		canaryInCluster.Spec.Analysis = renderCanaryAnalysis(*rolloutPolicy, clusterKey.Name)
-		// Set up annotations to make sure it's a resource created by kurator
-		canaryInCluster.SetAnnotations(annotation)
-
-		if apierrors.IsNotFound(getErr) {
-			if err := fleetClusterClient.Create(ctx, canaryInCluster); err != nil {
-				return ctrl.Result{}, fmt.Errorf("failed to create rolloutPolicy: %v", err)
-			}
-		} else {
-			if err := fleetClusterClient.Update(ctx, canaryInCluster); err != nil {
-				return ctrl.Result{}, fmt.Errorf("failed to update rolloutPolicy: %v", err)
-			}
-		}
-
-		log.Info("sync rolloutPolicy successful")
-	}
-	return ctrl.Result{}, nil
-}
-
-func enableIstioSidecarInjection(ctx context.Context, kubeClient client.Client, namespace string) error {
-	log := ctrl.LoggerFrom(ctx)
-
-	ns := &corev1.Namespace{}
-	namespacedName := types.NamespacedName{
-		Namespace: namespace,
-		Name:      namespace,
-	}
-	if err := kubeClient.Get(ctx, namespacedName, ns); err != nil {
-		// if no found, create a namespace
-		if apierrors.IsNotFound(err) {
-			ns.SetName(namespace)
-			ns.SetLabels(map[string]string{
-				sidecarInject: "enabled",
-			})
-			if createErr := kubeClient.Create(ctx, ns); createErr != nil {
-				return errors.Wrapf(createErr, "failed to create namespace %s", namespacedName.Namespace)
-			}
-		}
-		ns := addLabels(ns, sidecarInject, "enabled")
-		if updateErr := kubeClient.Update(ctx, ns); updateErr != nil {
-			return errors.Wrapf(updateErr, "failed to update namespace %s", namespacedName.Namespace)
-		}
-	}
-	log.Info("Inject sidecar successful")
-	return nil
-}
-
-func installPrivateTestloader(ctx context.Context, namespacedName types.NamespacedName, annotationKey, annotationValue string) error {
-	log := ctrl.LoggerFrom(ctx)
-	// apply testloader deployment resource
-	testloaderDeploy, deployErr := render.RenderTestloaderConfig(render.TestlaoderDeployment, namespacedName, annotationKey, annotationValue)
-	if deployErr != nil {
-		return deployErr
-	}
-	if _, err := util.PatchResources(testloaderDeploy); err != nil {
-		return err
-	}
-
-	// apply testloader service resource
-	testloaderSvc, svcErr := render.RenderTestloaderConfig(render.TestlaoderService, namespacedName, annotationKey, annotationValue)
-	if svcErr != nil {
-		return svcErr
-	}
-	if _, err := util.PatchResources(testloaderSvc); err != nil {
-		return err
-	}
-
-	log.Info("install testloader successful")
-	return nil
-}
-
-func deleteResourceCreatedByKurator(ctx context.Context, namespaceName types.NamespacedName, kubeClient client.Client, obj client.Object) error {
-	if err := kubeClient.Get(ctx, namespaceName, obj); err != nil {
-		if !apierrors.IsNotFound(err) {
-			return errors.Wrapf(err, "falied to get resource %s in %s", namespaceName.Name, namespaceName.Namespace)
-		}
-	} else {
-		// verify if the deployment were created by kurator
-		annotations := obj.GetAnnotations()
-		if _, exist := annotations[RolloutIdentifier]; exist {
-			if deleteErr := kubeClient.Delete(ctx, obj); deleteErr != nil && !apierrors.IsNotFound(deleteErr) {
-				return errors.Wrapf(deleteErr, "failed to delete kubernetes resource")
-			}
-		}
-	}
-	return nil
-}
-
-// create/update canary configuration
-func renderCanary(rolloutPolicy applicationapi.RolloutConfig, canaryInCluster *flaggerv1b1.Canary) *flaggerv1b1.Canary {
-	canaryInCluster.ObjectMeta.Namespace = rolloutPolicy.Workload.Namespace
-	canaryInCluster.ObjectMeta.Name = rolloutPolicy.Workload.Name
-	canaryInCluster.TypeMeta.Kind = "Canary"
-	canaryInCluster.TypeMeta.APIVersion = "flagger.app/v1beta1"
-	canaryInCluster.Spec = flaggerv1b1.CanarySpec{
-		Provider: rolloutPolicy.TrafficRoutingProvider,
-		TargetRef: flaggerv1b1.LocalObjectReference{
-			APIVersion: rolloutPolicy.Workload.APIVersion,
-			Kind:       rolloutPolicy.Workload.Kind,
-			Name:       rolloutPolicy.Workload.Name,
-		},
-		ProgressDeadlineSeconds: rolloutPolicy.RolloutPolicy.RolloutTimeoutSeconds,
-		SkipAnalysis:            rolloutPolicy.RolloutPolicy.SkipTrafficAnalysis,
-		RevertOnDeletion:        rolloutPolicy.RolloutPolicy.RevertOnDeletion,
-		Suspend:                 rolloutPolicy.RolloutPolicy.Suspend,
-	}
-
-	return canaryInCluster
-}
-
-func renderCanaryService(rolloutPolicy applicationapi.RolloutConfig, service *corev1.Service) (*flaggerv1b1.CanaryService, error) {
-	if service == nil {
-		return nil, fmt.Errorf("service is nil, build canaryService configuration failed")
-	}
-	ports := service.Spec.Ports
-	canaryService := &flaggerv1b1.CanaryService{
-		Name:       rolloutPolicy.ServiceName,
-		Port:       rolloutPolicy.Port,
-		Gateways:   rolloutPolicy.RolloutPolicy.TrafficRouting.Gateways,
-		Hosts:      rolloutPolicy.RolloutPolicy.TrafficRouting.Hosts,
-		Retries:    rolloutPolicy.RolloutPolicy.TrafficRouting.Retries,
-		Headers:    rolloutPolicy.RolloutPolicy.TrafficRouting.Headers,
-		CorsPolicy: rolloutPolicy.RolloutPolicy.TrafficRouting.CorsPolicy,
-		Primary:    (*flaggerv1b1.CustomMetadata)(rolloutPolicy.Primary),
-		Canary:     (*flaggerv1b1.CustomMetadata)(rolloutPolicy.Preview),
-	}
-
-	Timeout := fmt.Sprintf("%d", rolloutPolicy.RolloutPolicy.TrafficRouting.TimeoutSeconds) + "s"
-	canaryService.Timeout = Timeout
-
-	for _, port := range ports {
-		if port.Port == rolloutPolicy.Port {
-			canaryService.TargetPort = port.TargetPort
-			break
-		}
-	}
-
-	return canaryService, nil
-}
-
-func renderCanaryAnalysis(rolloutPolicy applicationapi.RolloutConfig, clusterName string) *flaggerv1b1.CanaryAnalysis {
-	canaryAnalysis := flaggerv1b1.CanaryAnalysis{
-		Iterations:      rolloutPolicy.RolloutPolicy.TrafficRouting.AnalysisTimes,
-		Threshold:       *rolloutPolicy.RolloutPolicy.TrafficAnalysis.CheckFailedTimes,
-		Match:           rolloutPolicy.RolloutPolicy.TrafficRouting.Match,
-		SessionAffinity: (*flaggerv1b1.SessionAffinity)(rolloutPolicy.RolloutPolicy.TrafficAnalysis.SessionAffinity),
-	}
-
-	if rolloutPolicy.RolloutPolicy.TrafficRouting.CanaryStrategy != nil {
-		canaryAnalysis.MaxWeight = rolloutPolicy.RolloutPolicy.TrafficRouting.CanaryStrategy.MaxWeight
-		canaryAnalysis.StepWeight = rolloutPolicy.RolloutPolicy.TrafficRouting.CanaryStrategy.StepWeight
-		canaryAnalysis.StepWeights = rolloutPolicy.RolloutPolicy.TrafficRouting.CanaryStrategy.StepWeights
-		canaryAnalysis.StepWeightPromotion = rolloutPolicy.RolloutPolicy.TrafficRouting.CanaryStrategy.StepWeightPromotion
-	}
-
-	CheckInterval := fmt.Sprintf("%d", *rolloutPolicy.RolloutPolicy.TrafficAnalysis.CheckIntervalSeconds) + "s"
-	canaryAnalysis.Interval = CheckInterval
-
-	canaryMetric := []flaggerv1b1.CanaryMetric{}
-	for _, metric := range rolloutPolicy.RolloutPolicy.TrafficAnalysis.Metrics {
-		metricInterval := fmt.Sprintf("%d", *metric.IntervalSeconds) + "s"
-		templateMetric := flaggerv1b1.CanaryMetric{
-			Name:           string(metric.Name),
-			Interval:       metricInterval,
-			ThresholdRange: (*flaggerv1b1.CanaryThresholdRange)(metric.ThresholdRange),
-		}
-		canaryMetric = append(canaryMetric, templateMetric)
-	}
-	canaryAnalysis.Metrics = canaryMetric
-
-	// Trigger testloader to request service before analysis by webhook.
-	webhookTemplate := flaggerv1b1.CanaryWebhook{
-		Name:    "generated-testload",
-		Timeout: "60s",
-	}
-
-	if len(rolloutPolicy.RolloutPolicy.TrafficAnalysis.Webhooks.Commands) != 0 {
-		var url string
-		// if have private webhook, webhook url is private testloader url
-		// else is public testloader url
-		if rolloutPolicy.TestLoader != nil && *rolloutPolicy.TestLoader {
-			name := rolloutPolicy.ServiceName + "-testloader"
-			namespace := rolloutPolicy.Workload.Namespace
-			url = generateWebhookUrl(name, namespace)
-		} else if namespace, exist := plugin.ProviderNamespace[fleetapi.Provider(rolloutPolicy.TrafficRoutingProvider)]; exist {
-			name := namespace + "-testloader-" + clusterName + "-loadtester"
-			url = generateWebhookUrl(name, namespace)
-		}
-		webhookTemplate.URL = url
-
-		timeout := fmt.Sprintf("%d", *rolloutPolicy.RolloutPolicy.TrafficAnalysis.Webhooks.TimeoutSeconds) + "s"
-		webhookTemplate.Timeout = timeout
-
-		canaryWebhook := []flaggerv1b1.CanaryWebhook{}
-		bakName := webhookTemplate.Name
-		for index, command := range rolloutPolicy.RolloutPolicy.TrafficAnalysis.Webhooks.Commands {
-			metadata := map[string]string{
-				"type": "cmd",
-				"cmd":  command,
-			}
-			webhookTemplate.Metadata = &metadata
-			webhookTemplate.Name = bakName + "-" + fmt.Sprintf("%d", index)
-			canaryWebhook = append(canaryWebhook, webhookTemplate)
-		}
-
-		canaryAnalysis.Webhooks = canaryWebhook
-	}
-	return &canaryAnalysis
-}
-
-func generateWebhookUrl(name, namespace string) string {
-	url := "http://" + name + "." + namespace + "/"
-	return url
-}
-
-func addLabels(obj client.Object, key, value string) client.Object {
-	labels := obj.GetLabels()
-	// prevent nil pointer panic
-	if labels == nil {
-		obj.SetLabels(map[string]string{
-			key: value,
-		})
-		return obj
-	}
-	labels[key] = value
-	obj.SetLabels(labels)
-	return obj
-}
diff --git a/pkg/fleet-manager/pipeline/render/predefined_task.go b/pkg/fleet-manager/pipeline/render/predefined_task.go
deleted file mode 100644
index 9cedf00..0000000
--- a/pkg/fleet-manager/pipeline/render/predefined_task.go
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-Copyright Kurator 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 render
-
-import (
-	"fmt"
-
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
-	pipelineapi "kurator.dev/kurator/pkg/apis/pipeline/v1alpha1"
-)
-
-type PredefinedTaskConfig struct {
-	PipelineName string
-	Namespace    string
-	// TemplateName is set by user in `Pipeline.Tasks[i].PredefinedTask.Name`
-	TemplateName string
-	// Params is set by user in `Pipeline.Tasks[i].PredefinedTask.Params`
-	Params         map[string]string
-	OwnerReference *metav1.OwnerReference
-}
-
-// PredefinedTaskName is the name of Predefined task object, in case different pipeline have the same name task.
-func (cfg PredefinedTaskConfig) PredefinedTaskName() string {
-	return cfg.TemplateName + "-" + cfg.PipelineName
-}
-
-// RenderPredefinedTaskWithPipeline takes a Pipeline object and generates YAML byte array configuration representing the PredefinedTask configuration.
-func RenderPredefinedTaskWithPipeline(pipeline *pipelineapi.Pipeline, task *pipelineapi.PredefinedTask) ([]byte, error) {
-	cfg := PredefinedTaskConfig{
-		PipelineName:   pipeline.Name,
-		Namespace:      pipeline.Namespace,
-		TemplateName:   string(task.Name),
-		Params:         task.Params,
-		OwnerReference: GeneratePipelineOwnerRef(pipeline),
-	}
-
-	return RenderPredefinedTask(cfg)
-}
-
-// RenderPredefinedTask takes a PredefinedTaskConfig object and generates YAML byte array configuration representing the PredefinedTask configuration.
-func RenderPredefinedTask(cfg PredefinedTaskConfig) ([]byte, error) {
-	templateContent, ok := predefinedTaskTemplates[cfg.TemplateName]
-	if !ok {
-		return nil, fmt.Errorf("predefinedTask template content named '%s' not found", cfg.TemplateName)
-	}
-
-	return renderTemplate(templateContent, generateTaskTemplateName(cfg.TemplateName), cfg)
-}
-
-func generateTaskTemplateName(taskType string) string {
-	return "pipeline-" + taskType + "-task template"
-}
-
-var predefinedTaskTemplates = map[string]string{
-	string(pipelineapi.GitClone):       GitCloneTaskContent,
-	string(pipelineapi.GoTest):         GoTestTaskContent,
-	string(pipelineapi.GoLint):         GoLintTaskContent,
-	string(pipelineapi.BuildPushImage): BuildPushImageContent,
-}
diff --git a/pkg/fleet-manager/pipeline/render/predefined_task_content.go b/pkg/fleet-manager/pipeline/render/predefined_task_content.go
deleted file mode 100644
index d91ecf6..0000000
--- a/pkg/fleet-manager/pipeline/render/predefined_task_content.go
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
-Copyright Kurator 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 render
-
-const GitCloneTaskContent = `apiVersion: tekton.dev/v1beta1
-kind: Task
-metadata:
-  name: {{ .PredefinedTaskName }}
-  namespace: {{ .Namespace }}
-  labels:
-    app.kubernetes.io/version: "0.9"
-  annotations:
-    tekton.dev/pipelines.minVersion: "0.38.0"
-    tekton.dev/categories: Git
-    tekton.dev/tags: git
-    tekton.dev/displayName: "git clone"
-    tekton.dev/platforms: "linux/amd64,linux/s390x,linux/ppc64le,linux/arm64"
-{{- if .OwnerReference }}
-  ownerReferences:
-  - apiVersion: "{{ .OwnerReference.APIVersion }}"
-    kind: "{{ .OwnerReference.Kind }}"
-    name: "{{ .OwnerReference.Name }}"
-    uid: "{{ .OwnerReference.UID }}"
-{{- end }}
-spec:
-  description: >-
-    These Tasks are Git tasks to work with repositories used by other tasks
-    in your Pipeline.
-    The git-clone Task will clone a repo from the provided url into the
-    source Workspace. By default the repo will be cloned into the root of
-    your Workspace. You can clone into a subdirectory by setting this Task's
-    subdirectory param. This Task also supports sparse checkouts. To perform
-    a sparse checkout, pass a list of comma separated directory patterns to
-    this Task's sparseCheckoutDirectories param.
-  workspaces:
-  - name: source
-    description: The git repo will be cloned onto the volume backing this Workspace.
-  - name: ssh-directory
-    optional: true
-    description: |
-      A .ssh directory with private key, known_hosts, config, etc. Copied to
-      the user's home before git commands are executed. Used to authenticate
-      with the git remote when performing the clone. Binding a Secret to this
-      Workspace is strongly recommended over other volume types.
-  - name: basic-auth
-    optional: true
-    description: |
-      A Workspace containing a .gitconfig and .git-credentials file. These
-      will be copied to the user's home before any git commands are run. Any
-      other files in this Workspace are ignored. It is strongly recommended
-      to use ssh-directory over basic-auth whenever possible and to bind a
-      Secret to this Workspace over other volume types.
-  - name: ssl-ca-directory
-    optional: true
-    description: |
-      A workspace containing CA certificates, this will be used by Git to
-      verify the peer with when fetching or pushing over HTTPS.
-  params:
-  - name: url
-    description: Repository URL to clone from.
-    type: string
-  - name: revision
-    description: Revision to checkout. (branch, tag, sha, ref, etc...)
-    type: string
-    default: ""
-  - name: refspec
-    description: Refspec to fetch before checking out revision.
-    default: ""
-  - name: submodules
-    description: Initialize and fetch git submodules.
-    type: string
-    default: "true"
-  - name: depth
-    description: Perform a shallow clone, fetching only the most recent N commits.
-    type: string
-    default: "1"
-  - name: sslVerify
-    description: Set the "http.sslVerify" global git config. Setting this to "false" is not advised unless you are sure that you trust your git remote.
-    type: string
-    default: "true"
-  - name: crtFileName
-    description: file name of mounted crt using ssl-ca-directory workspace. default value is ca-bundle.crt.
-    type: string
-    default: "ca-bundle.crt"
-  - name: subdirectory
-    description: Subdirectory inside the "source" Workspace to clone the repo into.
-    type: string
-    default: ""
-  - name: sparseCheckoutDirectories
-    description: Define the directory patterns to match or exclude when performing a sparse checkout.
-    type: string
-    default: ""
-  - name: deleteExisting
-    description: Clean out the contents of the destination directory if it already exists before cloning.
-    type: string
-    default: "true"
-  - name: httpProxy
-    description: HTTP proxy server for non-SSL requests.
-    type: string
-    default: ""
-  - name: httpsProxy
-    description: HTTPS proxy server for SSL requests.
-    type: string
-    default: ""
-  - name: noProxy
-    description: Opt out of proxying HTTP/HTTPS requests.
-    type: string
-    default: ""
-  - name: verbose
-    description: Log the commands that are executed during "git-clone"'s operation.
-    type: string
-    default: "true"
-  - name: gitInitImage
-    description: The image providing the git-init binary that this Task runs.
-    type: string
-    default: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.40.2"
-  - name: userHome
-    description: |
-      Absolute path to the user's home directory.
-    type: string
-    default: "/home/git"
-  results:
-  - name: commit
-    description: The precise commit SHA that was fetched by this Task.
-  - name: url
-    description: The precise URL that was fetched by this Task.
-  - name: committer-date
-    description: The epoch timestamp of the commit that was fetched by this Task.
-  steps:
-  - name: clone
-    image: "$(params.gitInitImage)"
-    env:
-    - name: HOME
-      value: "$(params.userHome)"
-    - name: PARAM_URL
-      value: $(params.url)
-    - name: PARAM_REVISION
-      value: $(params.revision)
-    - name: PARAM_REFSPEC
-      value: $(params.refspec)
-    - name: PARAM_SUBMODULES
-      value: $(params.submodules)
-    - name: PARAM_DEPTH
-      value: $(params.depth)
-    - name: PARAM_SSL_VERIFY
-      value: $(params.sslVerify)
-    - name: PARAM_CRT_FILENAME
-      value: $(params.crtFileName)
-    - name: PARAM_SUBDIRECTORY
-      value: $(params.subdirectory)
-    - name: PARAM_DELETE_EXISTING
-      value: $(params.deleteExisting)
-    - name: PARAM_HTTP_PROXY
-      value: $(params.httpProxy)
-    - name: PARAM_HTTPS_PROXY
-      value: $(params.httpsProxy)
-    - name: PARAM_NO_PROXY
-      value: $(params.noProxy)
-    - name: PARAM_VERBOSE
-      value: $(params.verbose)
-    - name: PARAM_SPARSE_CHECKOUT_DIRECTORIES
-      value: $(params.sparseCheckoutDirectories)
-    - name: PARAM_USER_HOME
-      value: $(params.userHome)
-    - name: WORKSPACE_SOURCE_PATH
-      value: $(workspaces.source.path)
-    - name: WORKSPACE_SSH_DIRECTORY_BOUND
-      value: $(workspaces.ssh-directory.bound)
-    - name: WORKSPACE_SSH_DIRECTORY_PATH
-      value: $(workspaces.ssh-directory.path)
-    - name: WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND
-      value: $(workspaces.basic-auth.bound)
-    - name: WORKSPACE_BASIC_AUTH_DIRECTORY_PATH
-      value: $(workspaces.basic-auth.path)
-    - name: WORKSPACE_SSL_CA_DIRECTORY_BOUND
-      value: $(workspaces.ssl-ca-directory.bound)
-    - name: WORKSPACE_SSL_CA_DIRECTORY_PATH
-      value: $(workspaces.ssl-ca-directory.path)
-    securityContext:
-      runAsNonRoot: true
-      runAsUser: 65532
-    script: |
-      #!/usr/bin/env sh
-      set -eu
-      if [ "${PARAM_VERBOSE}" = "true" ] ; then
-        set -x
-      fi
-      if [ "${WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND}" = "true" ] ; then
-        cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.git-credentials" "${PARAM_USER_HOME}/.git-credentials"
-        cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.gitconfig" "${PARAM_USER_HOME}/.gitconfig"
-        chmod 400 "${PARAM_USER_HOME}/.git-credentials"
-        chmod 400 "${PARAM_USER_HOME}/.gitconfig"
-      fi
-      if [ "${WORKSPACE_SSH_DIRECTORY_BOUND}" = "true" ] ; then
-        cp -R "${WORKSPACE_SSH_DIRECTORY_PATH}" "${PARAM_USER_HOME}"/.ssh
-        chmod 700 "${PARAM_USER_HOME}"/.ssh
-        chmod -R 400 "${PARAM_USER_HOME}"/.ssh/*
-      fi
-      if [ "${WORKSPACE_SSL_CA_DIRECTORY_BOUND}" = "true" ] ; then
-         export GIT_SSL_CAPATH="${WORKSPACE_SSL_CA_DIRECTORY_PATH}"
-         if [ "${PARAM_CRT_FILENAME}" != "" ] ; then
-            export GIT_SSL_CAINFO="${WORKSPACE_SSL_CA_DIRECTORY_PATH}/${PARAM_CRT_FILENAME}"
-         fi
-      fi
-      CHECKOUT_DIR="${WORKSPACE_SOURCE_PATH}/${PARAM_SUBDIRECTORY}"
-      cleandir() {
-        # Delete any existing contents of the repo directory if it exists.
-        #
-        # We don't just "rm -rf ${CHECKOUT_DIR}" because ${CHECKOUT_DIR} might be "/"
-        # or the root of a mounted volume.
-        if [ -d "${CHECKOUT_DIR}" ] ; then
-          # Delete non-hidden files and directories
-          rm -rf "${CHECKOUT_DIR:?}"/*
-          # Delete files and directories starting with . but excluding ..
-          rm -rf "${CHECKOUT_DIR}"/.[!.]*
-          # Delete files and directories starting with .. plus any other character
-          rm -rf "${CHECKOUT_DIR}"/..?*
-        fi
-      }
-      if [ "${PARAM_DELETE_EXISTING}" = "true" ] ; then
-        cleandir || true
-      fi
-      test -z "${PARAM_HTTP_PROXY}" || export HTTP_PROXY="${PARAM_HTTP_PROXY}"
-      test -z "${PARAM_HTTPS_PROXY}" || export HTTPS_PROXY="${PARAM_HTTPS_PROXY}"
-      test -z "${PARAM_NO_PROXY}" || export NO_PROXY="${PARAM_NO_PROXY}"
-      git config --global --add safe.directory "${WORKSPACE_SOURCE_PATH}"
-      /ko-app/git-init \
-        -url="${PARAM_URL}" \
-        -revision="${PARAM_REVISION}" \
-        -refspec="${PARAM_REFSPEC}" \
-        -path="${CHECKOUT_DIR}" \
-        -sslVerify="${PARAM_SSL_VERIFY}" \
-        -submodules="${PARAM_SUBMODULES}" \
-        -depth="${PARAM_DEPTH}" \
-        -sparseCheckoutDirectories="${PARAM_SPARSE_CHECKOUT_DIRECTORIES}"
-      cd "${CHECKOUT_DIR}"
-      RESULT_SHA="$(git rev-parse HEAD)"
-      EXIT_CODE="$?"
-      if [ "${EXIT_CODE}" != 0 ] ; then
-        exit "${EXIT_CODE}"
-      fi
-      RESULT_COMMITTER_DATE="$(git log -1 --pretty=%ct)"
-      printf "%s" "${RESULT_COMMITTER_DATE}" > "$(results.committer-date.path)"
-      printf "%s" "${RESULT_SHA}" > "$(results.commit.path)"
-      printf "%s" "${PARAM_URL}" > "$(results.url.path)"
-`
-
-const GoTestTaskContent = `apiVersion: tekton.dev/v1beta1
-kind: Task
-metadata:
-  name: {{ .PredefinedTaskName }}
-  namespace: {{ .Namespace }}
-  labels:
-    app.kubernetes.io/version: "0.2"
-  annotations:
-    tekton.dev/pipelines.minVersion: "0.12.1"
-    tekton.dev/categories: Testing
-    tekton.dev/tags: test
-    tekton.dev/displayName: "golang test"
-    tekton.dev/platforms: "linux/amd64,linux/s390x,linux/ppc64le"
-{{- if .OwnerReference }}
-  ownerReferences:
-  - apiVersion: "{{ .OwnerReference.APIVersion }}"
-    kind: "{{ .OwnerReference.Kind }}"
-    name: "{{ .OwnerReference.Name }}"
-    uid: "{{ .OwnerReference.UID }}"
-{{- end }}
-spec:
-  description: >-
-    This Task is Golang task to test Go projects.
-
-  params:
-  - name: package
-    description: package (and its children) under test
-    default: "{{ default "." .Params.package }}"
-  - name: packages
-    description: "packages to test (default: ./...)"
-    default: "{{ default "./..." .Params.packages }}"
-  - name: context
-    description: path to the directory to use as context.
-    default: "{{ default "." .Params.context }}"
-  - name: version
-    description: golang version to use for tests
-    default: "{{ default "latest" .Params.version }}"
-  - name: flags
-    description: flags to use for the test command
-    default: "{{ default "-race -cover -v" .Params.flags }}"
-  - name: GOOS
-    description: "running program's operating system target"
-    default: "{{ default "linux" .Params.GOOS }}"
-  - name: GOARCH
-    description: "running program's architecture target"
-    default: "{{ default "amd64" .Params.GOARCH }}"
-  - name: GO111MODULE
-    description: "value of module support"
-    default: "{{ default "auto" .Params.GO111MODULE }}"
-  - name: GOCACHE
-    description: "Go caching directory path"
-    default: "{{ default "" .Params.GOCACHE }}"
-  - name: GOMODCACHE
-    description: "Go mod caching directory path"
-    default: "{{ default "" .Params.GOMODCACHE }}"
-  workspaces:
-  - name: source
-  steps:
-  - name: unit-test
-    image: docker.io/library/golang:$(params.version)
-    workingDir: $(workspaces.source.path)
-    script: |
-      if [ ! -e $GOPATH/src/$(params.package)/go.mod ];then
-         SRC_PATH="$GOPATH/src/$(params.package)"
-         mkdir -p $SRC_PATH
-         cp -R "$(workspaces.source.path)/$(params.context)"/* $SRC_PATH
-         cd $SRC_PATH
-      fi
-      go test $(params.flags) $(params.packages)
-    env:
-    - name: GOOS
-      value: "$(params.GOOS)"
-    - name: GOARCH
-      value: "$(params.GOARCH)"
-    - name: GO111MODULE
-      value: "$(params.GO111MODULE)"
-    - name: GOCACHE
-      value: "$(params.GOCACHE)"
-    - name: GOMODCACHE
-      value: "$(params.GOMODCACHE)"
-`
-
-const GoLintTaskContent = `apiVersion: tekton.dev/v1beta1
-kind: Task
-metadata:
-  name: {{ .PredefinedTaskName }}
-  namespace: {{ .Namespace }}
-  labels:
-    app.kubernetes.io/version: "0.2"
-  annotations:
-    tekton.dev/pipelines.minVersion: "0.12.1"
-    tekton.dev/categories: Code Quality
-    tekton.dev/tags: lint
-    tekton.dev/displayName: "golangci lint"
-    tekton.dev/platforms: "linux/amd64"
-{{- if .OwnerReference }}
-  ownerReferences:
-  - apiVersion: "{{ .OwnerReference.APIVersion }}"
-    kind: "{{ .OwnerReference.Kind }}"
-    name: "{{ .OwnerReference.Name }}"
-    uid: "{{ .OwnerReference.UID }}"
-{{- end }}
-spec:
-  description: >-
-    This Task is Golang task to validate Go projects.
-
-  params:
-  - name: package
-    description: base package (and its children) under validation
-    default: "{{ default "." .Params.package }}"
-  - name: context
-    description: path to the directory to use as context.
-    default: "{{ default "." .Params.context }}"
-  - name: flags
-    description: flags to use for the lint command
-    default: "{{ default "--verbose" .Params.flags }}"
-  - name: version
-    description: golangci-lint version to use
-    default: "{{ default "latest" .Params.version }}"
-  - name: GOOS
-    description: "running program's operating system target"
-    default: "{{ default "linux" .Params.GOOS }}"
-  - name: GOARCH
-    description: "running program's architecture target"
-    default: "{{ default "amd64" .Params.GOARCH }}"
-  - name: GO111MODULE
-    description: "value of module support"
-    default: "{{ default "auto" .Params.GO111MODULE }}"
-  - name: GOCACHE
-    description: "Go caching directory path"
-    default: "{{ default "" .Params.GOCACHE }}"
-  - name: GOMODCACHE
-    description: "Go mod caching directory path"
-    default: "{{ default "" .Params.GOMODCACHE }}"
-  - name: GOLANGCI_LINT_CACHE
-    description: "golangci-lint cache path"
-    default: "{{ default "" .Params.GOLANGCI_LINT_CACHE }}"
-  workspaces:
-  - name: source
-    mountPath: /workspace/src/$(params.package)
-  steps:
-  - name: lint
-    image: docker.io/golangci/golangci-lint:$(params.version)
-    workingDir: $(workspaces.source.path)/$(params.context)
-    script: |
-      golangci-lint run $(params.flags)
-    env:
-    - name: GOPATH
-      value: /workspace
-    - name: GOOS
-      value: "$(params.GOOS)"
-    - name: GOARCH
-      value: "$(params.GOARCH)"
-    - name: GO111MODULE
-      value: "$(params.GO111MODULE)"
-    - name: GOCACHE
-      value: "$(params.GOCACHE)"
-    - name: GOMODCACHE
-      value: "$(params.GOMODCACHE)"
-    - name: GOLANGCI_LINT_CACHE
-      value: "$(params.GOLANGCI_LINT_CACHE)"
-`
-const BuildPushImageContent = `apiVersion: tekton.dev/v1beta1
-kind: Task
-metadata:
-  name: {{ .PredefinedTaskName }}
-  namespace: {{ .Namespace }}
-  labels:
-    app.kubernetes.io/version: "0.6"
-  annotations:
-    tekton.dev/pipelines.minVersion: "0.17.0"
-    tekton.dev/categories: Image Build
-    tekton.dev/tags: image-build
-    tekton.dev/displayName: "Build and upload container image using Kaniko"
-    tekton.dev/platforms: "linux/amd64,linux/arm64,linux/ppc64le"
-{{- if .OwnerReference }}
-  ownerReferences:
-  - apiVersion: "{{ .OwnerReference.APIVersion }}"
-    kind: "{{ .OwnerReference.Kind }}"
-    name: "{{ .OwnerReference.Name }}"
-    uid: "{{ .OwnerReference.UID }}"
-{{- end }}
-spec:
-  description: >-
-    This Task builds a simple Dockerfile with kaniko and pushes to a registry.
-    This Task stores the image name and digest as results, allowing Tekton Chains to pick up
-    that an image was built & sign it.
-  params:
-  - name: IMAGE # This is a parameter that must be set.
-    description: Name (reference) of the image to build.
-    default: {{ default "Unknown" .Params.image }}
-  - name: DOCKERFILE
-    description: Path to the Dockerfile to build.
-    default: {{ default "./Dockerfile" .Params.dockerfile }}
-  - name: CONTEXT
-    description: The build context used by Kaniko.
-    default: {{ default "./" .Params.context }}
-  - name: EXTRA_ARGS # more details see https://github.com/GoogleContainerTools/kaniko?tab=readme-ov-file#additional-flags
-    type: array
-    default: {{ default "[]" .Params.extra_args }}
-  - name: BUILDER_IMAGE
-    description: The image on which builds will run (default is v1.19.2 debug)
-    default: {{ default "gcr.io/kaniko-project/executor@sha256:899886a2db1c127ff1565d5c7b1e574af1810bbdad048e9850e4f40b5848d79c" .Params.builder_image }}
-  workspaces:
-  - name: source
-    description: Holds the context and Dockerfile
-  - name: dockerconfig
-    description: Includes a docker "config.json"
-    optional: true
-    mountPath: /kaniko/.docker
-  results:
-  - name: IMAGE_DIGEST
-    description: Digest of the image just built.
-  - name: IMAGE_URL
-    description: URL of the image just built.
-  steps:
-  - name: build-and-push
-    workingDir: $(workspaces.source.path)
-    image: $(params.BUILDER_IMAGE)
-    args:
-    - $(params.EXTRA_ARGS)
-    - --dockerfile=$(params.DOCKERFILE)
-    - --context=$(workspaces.source.path)/$(params.CONTEXT) # The user does not need to care the workspace and the source.
-    - --destination=$(params.IMAGE)
-    - --digest-file=$(results.IMAGE_DIGEST.path)
-    - --ignore-path=/product_uuid # in case kind cluster run failed, see https://github.com/GoogleContainerTools/kaniko/issues/2164
-    # kaniko assumes it is running as root, which means this example fails on platforms
-    # that default to run containers as random uid (like OpenShift). Adding this securityContext
-    # makes it explicit that it needs to run as root.
-    securityContext:
-      runAsUser: 0
-  - name: write-url
-    image: docker.io/library/bash:5.1.4@sha256:c523c636b722339f41b6a431b44588ab2f762c5de5ec3bd7964420ff982fb1d9
-    script: |
-      set -e
-      image="$(params.IMAGE)"
-      echo -n "${image}" | tee "$(results.IMAGE_URL.path)"
-`
diff --git a/pkg/fleet-manager/pipeline/render/trigger.go b/pkg/fleet-manager/pipeline/render/trigger.go
deleted file mode 100644
index 3aa0ccc..0000000
--- a/pkg/fleet-manager/pipeline/render/trigger.go
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
-Copyright Kurator 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 render
-
-import (
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
-	pipelineapi "kurator.dev/kurator/pkg/apis/pipeline/v1alpha1"
-)
-
-const (
-	TriggerTemplateName = "pipeline trigger template"
-)
-
-type TriggerConfig struct {
-	PipelineName      string
-	PipelineNamespace string
-	OwnerReference    *metav1.OwnerReference
-	AccessMode        string
-	StorageRequest    string
-	StorageClassName  string
-	VolumeMode        string
-}
-
-// ServiceAccountName is the service account used by trigger
-func (cfg TriggerConfig) ServiceAccountName() string {
-	return cfg.PipelineName
-}
-
-// RenderTriggerWithPipeline takes a pipeline object and generates YAML byte array configuration representing the trigger configuration.
-func RenderTriggerWithPipeline(pipeline *pipelineapi.Pipeline) ([]byte, error) {
-	config := TriggerConfig{
-		PipelineName:      pipeline.Name,
-		PipelineNamespace: pipeline.Namespace,
-		OwnerReference:    GeneratePipelineOwnerRef(pipeline),
-	}
-	if pipeline.Spec.SharedWorkspace != nil {
-		config.AccessMode = string(pipeline.Spec.SharedWorkspace.AccessMode)
-		config.StorageRequest = pipeline.Spec.SharedWorkspace.StorageRequest
-		config.StorageClassName = pipeline.Spec.SharedWorkspace.StorageClassName
-		config.VolumeMode = string(pipeline.Spec.SharedWorkspace.VolumeMode)
-	}
-
-	return RenderTrigger(config)
-}
-
-// RenderTrigger takes a TriggerConfig object and generates YAML byte array configuration representing the trigger configuration.
-func RenderTrigger(cfg TriggerConfig) ([]byte, error) {
-	return renderTemplate(TriggerTemplateContent, TriggerTemplateName, cfg)
-}
-
-const TriggerTemplateContent = `apiVersion: triggers.tekton.dev/v1alpha1
-kind: TriggerTemplate
-metadata:
-  name: {{ .PipelineName }}-triggertemplate
-  namespace: {{ .PipelineNamespace }}
-{{- if .OwnerReference }}
-  ownerReferences:
-  - apiVersion: "{{ .OwnerReference.APIVersion }}"
-    kind: "{{ .OwnerReference.Kind }}"
-    name: "{{ .OwnerReference.Name }}"
-    uid: "{{ .OwnerReference.UID }}"
-{{- end }}
-spec:
-  params:
-  - name: gitrevision
-    description: The git revision
-  - name: gitrepositoryurl
-    description: The git repository url
-  - name: namespace
-    description: The namespace to create the resources
-  resourceTemplates:
-  - apiVersion: tekton.dev/v1beta1
-    kind: PipelineRun
-    metadata:
-      generateName: {{ .PipelineName }}-run-
-      namespace: $(tt.params.namespace)
-    spec:
-      serviceAccountName: {{ .ServiceAccountName }}
-      pipelineRef:
-        name: {{ .PipelineName }}
-      params:
-      - name: revision
-        value: $(tt.params.gitrevision)
-      - name: repo-url
-        value: $(tt.params.gitrepositoryurl)
-      workspaces:
-      - name: kurator-pipeline-shared-data # there only one pvc workspace in each pipeline, and the name is kurator-pipeline-shared-data
-        volumeClaimTemplate:
-          spec:
-            accessModes:
-              - {{ default "ReadWriteOnce" .AccessMode }}
-            resources:
-              requests:
-                storage: {{ default "1Gi" .StorageRequest }}
-{{- if .VolumeMode }}
-            volumeMode: {{ .VolumeMode }}
-{{- end }}
-{{- if .StorageClassName }}
-            storageClassName: {{ .StorageClassName }}
-{{- end }}
-      - name: git-credentials
-        secret:
-          secretName: git-credentials
-      - name: docker-credentials
-        secret:
-          secretName: docker-credentials  # auth for task
----
-apiVersion: triggers.tekton.dev/v1alpha1
-kind: TriggerBinding
-metadata:
-  name: {{ .PipelineName }}-triggerbinding
-  namespace: {{ .PipelineNamespace}}
-{{- if .OwnerReference }}
-  ownerReferences:
-  - apiVersion: "{{ .OwnerReference.APIVersion }}"
-    kind: "{{ .OwnerReference.Kind }}"
-    name: "{{ .OwnerReference.Name }}"
-    uid: "{{ .OwnerReference.UID }}"
-{{- end }}
-spec:
-  params:
-  - name: gitrevision
-    value: $(body.head_commit.id)
-  - name: namespace
-    value: {{ .PipelineNamespace}}
-  - name: gitrepositoryurl
-    value: "https://github.com/$(body.repository.full_name)"
----
-apiVersion: triggers.tekton.dev/v1alpha1
-kind: EventListener
-metadata:
-  name: {{ .PipelineName }}-listener
-  namespace: {{ .PipelineNamespace}}
-{{- if .OwnerReference }}
-  ownerReferences:
-  - apiVersion: "{{ .OwnerReference.APIVersion }}"
-    kind: "{{ .OwnerReference.Kind }}"
-    name: "{{ .OwnerReference.Name }}"
-    uid: "{{ .OwnerReference.UID }}"
-{{- end }}
-spec:
-  serviceAccountName: {{ .ServiceAccountName }}
-  triggers:
-  - bindings:
-    - ref: {{ .PipelineName }}-triggerbinding
-    template:
-      ref: {{ .PipelineName }}-triggertemplate
-`


Test patch:
diff --git a/pkg/fleet-manager/application/manifests/rollout_testloader.go b/pkg/fleet-manager/application/manifests/rollout_testloader.go
deleted file mode 100644
index 8ca0196..0000000
--- a/pkg/fleet-manager/application/manifests/rollout_testloader.go
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
-Copyright Kurator 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 render
-
-import (
-	"bytes"
-	"text/template"
-
-	"k8s.io/apimachinery/pkg/types"
-)
-
-type TestloaderConfig struct {
-	Name            string
-	Namespace       string
-	LabelKey        string
-	LabelValue      string
-	AnnotationKey   string
-	AnnotationValue string
-}
-
-const testloaderTemplateName = "testloader"
-
-// RenderTestloaderConfig takes generates YAML byte array configuration representing the testloader configuration.
-func RenderTestloaderConfig(constTemplateName string, namespacedName types.NamespacedName, annotationKey, annotationsValue string) ([]byte, error) {
-	cfg := TestloaderConfig{
-		Name:            namespacedName.Name,
-		Namespace:       namespacedName.Namespace,
-		LabelKey:        "app",
-		LabelValue:      namespacedName.Name,
-		AnnotationKey:   annotationKey,
-		AnnotationValue: annotationsValue,
-	}
-
-	return renderTestloaderTemplateConfig(constTemplateName, cfg)
-}
-
-// renderTestloaderTemplateConfig reads, parses, and renders a template file using the provided configuration data.
-func renderTestloaderTemplateConfig(constTemplateName string, cfg TestloaderConfig) ([]byte, error) {
-	tql, err := template.New(testloaderTemplateName).Funcs(funMap()).Parse(constTemplateName)
-	if err != nil {
-		return nil, err
-	}
-
-	var b bytes.Buffer
-	if err := tql.Execute(&b, cfg); err != nil {
-		return nil, err
-	}
-
-	return b.Bytes(), nil
-}
-
-func funMap() template.FuncMap {
-	return nil
-}
-
-const TestlaoderDeployment = `apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: {{.Name}}
-  namespace: {{.Namespace}}
-  labels:
-    {{.LabelKey}}: {{.LabelValue}}
-  annotations:
-    {{.AnnotationKey}}: {{.AnnotationValue}}
-spec:
-  selector:
-    matchLabels:
-      {{.LabelKey}}: {{.LabelValue}}
-  template:
-    metadata:
-      labels:
-        {{.LabelKey}}: {{.LabelValue}}
-      annotations:
-        prometheus.io/scrape: "true"
-        prometheus.io/port: "8080"
-        openservicemesh.io/inbound-port-exclusion-list: "80, 8080"
-    spec:
-      containers:
-        - name: loadtester
-          image: ghcr.io/fluxcd/flagger-loadtester:0.29.0
-          imagePullPolicy: IfNotPresent
-          ports:
-            - name: http
-              containerPort: 8080
-          command:
-            - ./loadtester
-            - -port=8080
-            - -log-level=info
-            - -timeout=1h
-          livenessProbe:
-            exec:
-              command:
-                - wget
-                - --quiet
-                - --tries=1
-                - --timeout=4
-                - --spider
-                - http://localhost:8080/healthz
-            timeoutSeconds: 5
-          readinessProbe:
-            exec:
-              command:
-                - wget
-                - --quiet
-                - --tries=1
-                - --timeout=4
-                - --spider
-                - http://localhost:8080/healthz
-            timeoutSeconds: 5
-          resources:
-            limits:
-              memory: "512Mi"
-              cpu: "1000m"
-            requests:
-              memory: "32Mi"
-              cpu: "10m"
-          securityContext:
-            readOnlyRootFilesystem: true
-            runAsUser: 10001
-`
-
-const TestlaoderService = `apiVersion: v1
-kind: Service
-metadata:
-  name: {{.Name}}
-  namespace: {{.Namespace}}
-  labels:
-    {{.LabelKey}}: {{.LabelValue}}
-  annotations:
-    {{.AnnotationKey}}: {{.AnnotationValue}}
-spec:
-  type: ClusterIP
-  selector:
-    {{.LabelKey}}: {{.LabelValue}}
-  ports:
-    - name: http
-      port: 80
-      protocol: TCP
-      targetPort: http
-`
diff --git a/pkg/fleet-manager/application/manifests/rollout_testloader_test.go b/pkg/fleet-manager/application/manifests/rollout_testloader_test.go
deleted file mode 100644
index 2e47ac2..0000000
--- a/pkg/fleet-manager/application/manifests/rollout_testloader_test.go
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-Copyright Kurator 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 render
-
-import (
-	"os"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-	"k8s.io/apimachinery/pkg/types"
-)
-
-func TestRenderTestloaderConfig(t *testing.T) {
-	expectedTestDataFile := "testdata/"
-	namespacedName := types.NamespacedName{
-		Namespace: "test",
-		Name:      "testloader",
-	}
-	annotationKey := "kurator.dev/rollout"
-	annotationValue := "policy"
-	cases := []struct {
-		name              string
-		constTemplateName string
-		expectFileName    string
-	}{
-		{
-			name:              "testloader deploy template",
-			constTemplateName: TestlaoderDeployment,
-			expectFileName:    "testloader-deploy.yaml",
-		},
-		{
-			name:              "testloader svc template",
-			constTemplateName: TestlaoderService,
-			expectFileName:    "testloader-svc.yaml",
-		},
-	}
-
-	for _, tc := range cases {
-		t.Run(tc.name, func(t *testing.T) {
-			result, err := RenderTestloaderConfig(tc.constTemplateName, namespacedName, annotationKey, annotationValue)
-			if err != nil {
-				assert.Error(t, err)
-			} else {
-				expected, err := os.ReadFile(expectedTestDataFile + tc.expectFileName)
-				assert.NoError(t, err)
-				assert.Equal(t, result, expected)
-			}
-		})
-	}
-}
diff --git a/pkg/fleet-manager/application/manifests/testdata/testloader-deploy.yaml b/pkg/fleet-manager/application/manifests/testdata/testloader-deploy.yaml
deleted file mode 100644
index 19fe590..0000000
--- a/pkg/fleet-manager/application/manifests/testdata/testloader-deploy.yaml
+++ /dev/null
@@ -1,64 +0,0 @@
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: testloader
-  namespace: test
-  labels:
-    app: testloader
-  annotations:
-    kurator.dev/rollout: policy
-spec:
-  selector:
-    matchLabels:
-      app: testloader
-  template:
-    metadata:
-      labels:
-        app: testloader
-      annotations:
-        prometheus.io/scrape: "true"
-        prometheus.io/port: "8080"
-        openservicemesh.io/inbound-port-exclusion-list: "80, 8080"
-    spec:
-      containers:
-        - name: loadtester
-          image: ghcr.io/fluxcd/flagger-loadtester:0.29.0
-          imagePullPolicy: IfNotPresent
-          ports:
-            - name: http
-              containerPort: 8080
-          command:
-            - ./loadtester
-            - -port=8080
-            - -log-level=info
-            - -timeout=1h
-          livenessProbe:
-            exec:
-              command:
-                - wget
-                - --quiet
-                - --tries=1
-                - --timeout=4
-                - --spider
-                - http://localhost:8080/healthz
-            timeoutSeconds: 5
-          readinessProbe:
-            exec:
-              command:
-                - wget
-                - --quiet
-                - --tries=1
-                - --timeout=4
-                - --spider
-                - http://localhost:8080/healthz
-            timeoutSeconds: 5
-          resources:
-            limits:
-              memory: "512Mi"
-              cpu: "1000m"
-            requests:
-              memory: "32Mi"
-              cpu: "10m"
-          securityContext:
-            readOnlyRootFilesystem: true
-            runAsUser: 10001
diff --git a/pkg/fleet-manager/application/manifests/testdata/testloader-svc.yaml b/pkg/fleet-manager/application/manifests/testdata/testloader-svc.yaml
deleted file mode 100644
index ebfb35d..0000000
--- a/pkg/fleet-manager/application/manifests/testdata/testloader-svc.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
-  name: testloader
-  namespace: test
-  labels:
-    app: testloader
-  annotations:
-    kurator.dev/rollout: policy
-spec:
-  type: ClusterIP
-  selector:
-    app: testloader
-  ports:
-    - name: http
-      port: 80
-      protocol: TCP
-      targetPort: http
diff --git a/pkg/fleet-manager/application/rollout_helper_test.go b/pkg/fleet-manager/application/rollout_helper_test.go
deleted file mode 100644
index 4bf90e1..0000000
--- a/pkg/fleet-manager/application/rollout_helper_test.go
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
-Copyright Kurator 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 application
-
-import (
-	"reflect"
-	"testing"
-
-	flaggerv1b1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
-	"github.com/fluxcd/flagger/pkg/apis/istio/common/v1alpha1"
-	istiov1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
-	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/util/intstr"
-	"sigs.k8s.io/controller-runtime/pkg/client"
-
-	applicationapi "kurator.dev/kurator/pkg/apis/apps/v1alpha1"
-)
-
-func generateRolloutPloicy(installPrivateTestloader *bool) applicationapi.RolloutConfig {
-	timeout := 50
-	RolloutTimeoutSeconds := int32(50)
-	min := 99.0
-	max := 500.0
-
-	rolloutPolicy := applicationapi.RolloutConfig{
-		TestLoader:             installPrivateTestloader,
-		TrafficRoutingProvider: "istio",
-		Workload: &applicationapi.CrossNamespaceObjectReference{
-			APIVersion: "appv1/deployment",
-			Kind:       "Deployment",
-			Name:       "podinfo",
-			Namespace:  "test",
-		},
-		ServiceName: "podinfo-service",
-		Port:        80,
-		RolloutPolicy: &applicationapi.RolloutPolicy{
-			TrafficRouting: &applicationapi.TrafficRoutingConfig{
-				TimeoutSeconds: 50,
-				Gateways: []string{
-					"istio-system/public-gateway",
-				},
-				Hosts: []string{
-					"app.example.com",
-				},
-				Retries: &istiov1alpha3.HTTPRetry{
-					Attempts:      10,
-					PerTryTimeout: "40s",
-					RetryOn:       "gateway-error, connect-failure, refused-stream",
-				},
-				Headers: &istiov1alpha3.Headers{
-					Request: &istiov1alpha3.HeaderOperations{
-						Add: map[string]string{
-							"x-some-header": "value",
-						},
-					},
-				},
-				CorsPolicy: &istiov1alpha3.CorsPolicy{
-					AllowOrigin:      []string{"example"},
-					AllowMethods:     []string{"GET"},
-					AllowCredentials: false,
-					AllowHeaders:     []string{"x-some-header"},
-					MaxAge:           "24h",
-				},
-				CanaryStrategy: &applicationapi.CanaryConfig{
-					MaxWeight:  50,
-					StepWeight: 10,
-					StepWeights: []int{
-						1, 20, 40, 80,
-					},
-					StepWeightPromotion: 30,
-				},
-				AnalysisTimes: 5,
-				Match: []istiov1alpha3.HTTPMatchRequest{
-					{
-						Headers: map[string]v1alpha1.StringMatch{
-							"user-agent": {
-								Regex: ".*Firefox.*",
-							},
-							"cookie": {
-								Regex: "^(.*?;)?(type=insider)(;.*)?$",
-							},
-						},
-					},
-				},
-			},
-			TrafficAnalysis: &applicationapi.TrafficAnalysis{
-				CheckIntervalSeconds: &timeout,
-				CheckFailedTimes:     &timeout,
-				Metrics: []applicationapi.Metric{
-					{
-						Name:            "request-success-rate",
-						IntervalSeconds: &timeout,
-						ThresholdRange: &applicationapi.CanaryThresholdRange{
-							Min: &min,
-						},
-					},
-					{
-						Name:            "request-duration",
-						IntervalSeconds: &timeout,
-						ThresholdRange: &applicationapi.CanaryThresholdRange{
-							Max: &max,
-						},
-					},
-				},
-				Webhooks: applicationapi.Webhook{
-					TimeoutSeconds: &timeout,
-					Commands: []string{
-						"hey -z 1m -q 10 -c 2 http://podinfo-canary.test:9898/",
-						"curl -sd 'test' http://podinfo-canary:9898/token | grep token",
-					},
-				},
-				SessionAffinity: &applicationapi.SessionAffinity{
-					CookieName: "User",
-					MaxAge:     24,
-				},
-			},
-			RolloutTimeoutSeconds: &RolloutTimeoutSeconds,
-			SkipTrafficAnalysis:   false,
-			RevertOnDeletion:      false,
-			Suspend:               false,
-		},
-	}
-	return rolloutPolicy
-}
-
-func Test_renderCanary(t *testing.T) {
-	int32Time := int32(50)
-	sign := true
-	type args struct {
-		rolloutPolicy applicationapi.RolloutConfig
-	}
-	tests := []struct {
-		name string
-		args args
-		want *flaggerv1b1.Canary
-	}{
-		{
-			name: "functional test",
-			args: args{
-				rolloutPolicy: generateRolloutPloicy(&sign),
-			},
-			want: &flaggerv1b1.Canary{
-				ObjectMeta: metav1.ObjectMeta{
-					Namespace: "test",
-					Name:      "podinfo",
-				},
-				TypeMeta: metav1.TypeMeta{
-					Kind:       "Canary",
-					APIVersion: "flagger.app/v1beta1",
-				},
-				Spec: flaggerv1b1.CanarySpec{
-					Provider: "istio",
-					TargetRef: flaggerv1b1.LocalObjectReference{
-						APIVersion: "appv1/deployment",
-						Kind:       "Deployment",
-						Name:       "podinfo",
-					},
-					ProgressDeadlineSeconds: &int32Time,
-					SkipAnalysis:            false,
-					RevertOnDeletion:        false,
-					Suspend:                 false,
-				},
-			},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if got := renderCanary(tt.args.rolloutPolicy, &flaggerv1b1.Canary{}); !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("renderCanary() = %v\n, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_renderCanaryService(t *testing.T) {
-	sign := true
-	rolloutPolicy := generateRolloutPloicy(&sign)
-	type args struct {
-		rolloutPolicy applicationapi.RolloutConfig
-		service       *corev1.Service
-	}
-	tests := []struct {
-		name string
-		args args
-		want *flaggerv1b1.CanaryService
-	}{
-		{
-			name: "functional test",
-			args: args{
-				rolloutPolicy: rolloutPolicy,
-				service: &corev1.Service{
-					ObjectMeta: metav1.ObjectMeta{
-						Namespace: "test",
-						Name:      "podinfo-service",
-					},
-					Spec: corev1.ServiceSpec{
-						Selector: map[string]string{
-							"app": "podinfo",
-						},
-						Ports: []corev1.ServicePort{
-							{
-								Protocol:   corev1.ProtocolTCP,
-								Port:       80,
-								TargetPort: intstr.FromInt(8080),
-							},
-						},
-					},
-				},
-			},
-			want: &flaggerv1b1.CanaryService{
-				Name:       "podinfo-service",
-				Port:       80,
-				Timeout:    "50s",
-				TargetPort: intstr.FromInt(8080),
-				Gateways: []string{
-					"istio-system/public-gateway",
-				},
-				Hosts: []string{
-					"app.example.com",
-				},
-				Retries:    rolloutPolicy.RolloutPolicy.TrafficRouting.Retries,
-				Headers:    rolloutPolicy.RolloutPolicy.TrafficRouting.Headers,
-				CorsPolicy: rolloutPolicy.RolloutPolicy.TrafficRouting.CorsPolicy,
-			},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if got, _ := renderCanaryService(tt.args.rolloutPolicy, tt.args.service); !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("renderCanaryService() = %v\n, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_renderCanaryAnalysis(t *testing.T) {
-	sign := true
-	wantFalse := false
-	timeout := 50
-	rolloutPolicy := generateRolloutPloicy(&sign)
-	wantPublicTestloaderRolloutPolicy := generateRolloutPloicy(&wantFalse)
-	type args struct {
-		rolloutPolicy applicationapi.RolloutConfig
-	}
-	tests := []struct {
-		name string
-		args args
-		want *flaggerv1b1.CanaryAnalysis
-	}{
-		{
-			name: "functional test",
-			args: args{
-				rolloutPolicy: rolloutPolicy,
-			},
-			want: &flaggerv1b1.CanaryAnalysis{
-				Interval:   "50s",
-				Iterations: 5,
-				MaxWeight:  50,
-				StepWeight: 10,
-				StepWeights: []int{
-					1, 20, 40, 80,
-				},
-				StepWeightPromotion: 30,
-				Threshold:           timeout,
-				Match: []istiov1alpha3.HTTPMatchRequest{
-					{
-						Headers: map[string]v1alpha1.StringMatch{
-							"user-agent": {
-								Regex: ".*Firefox.*",
-							},
-							"cookie": {
-								Regex: "^(.*?;)?(type=insider)(;.*)?$",
-							},
-						},
-					},
-				},
-				SessionAffinity: (*flaggerv1b1.SessionAffinity)(rolloutPolicy.RolloutPolicy.TrafficAnalysis.SessionAffinity),
-				Metrics: []flaggerv1b1.CanaryMetric{
-					{
-						Name:           "request-success-rate",
-						Interval:       "50s",
-						ThresholdRange: (*flaggerv1b1.CanaryThresholdRange)(rolloutPolicy.RolloutPolicy.TrafficAnalysis.Metrics[0].ThresholdRange),
-					},
-					{
-						Name:           "request-duration",
-						Interval:       "50s",
-						ThresholdRange: (*flaggerv1b1.CanaryThresholdRange)(rolloutPolicy.RolloutPolicy.TrafficAnalysis.Metrics[1].ThresholdRange),
-					},
-				},
-				Webhooks: []flaggerv1b1.CanaryWebhook{
-					{
-						Name:    "generated-testload-0",
-						Timeout: "50s",
-						URL:     "http://podinfo-service-testloader.test/",
-						Metadata: &map[string]string{
-							"type": "cmd",
-							"cmd":  "hey -z 1m -q 10 -c 2 http://podinfo-canary.test:9898/",
-						},
-					},
-					{
-						Name:    "generated-testload-1",
-						Timeout: "50s",
-						URL:     "http://podinfo-service-testloader.test/",
-						Metadata: &map[string]string{
-							"type": "cmd",
-							"cmd":  "curl -sd 'test' http://podinfo-canary:9898/token | grep token",
-						},
-					},
-				},
-			},
-		},
-		{
-			name: "public Testloader",
-			args: args{
-				rolloutPolicy: wantPublicTestloaderRolloutPolicy,
-			},
-			want: &flaggerv1b1.CanaryAnalysis{
-				Interval:   "50s",
-				Iterations: 5,
-				MaxWeight:  50,
-				StepWeight: 10,
-				StepWeights: []int{
-					1, 20, 40, 80,
-				},
-				StepWeightPromotion: 30,
-				Threshold:           timeout,
-				Match: []istiov1alpha3.HTTPMatchRequest{
-					{
-						Headers: map[string]v1alpha1.StringMatch{
-							"user-agent": {
-								Regex: ".*Firefox.*",
-							},
-							"cookie": {
-								Regex: "^(.*?;)?(type=insider)(;.*)?$",
-							},
-						},
-					},
-				},
-				SessionAffinity: (*flaggerv1b1.SessionAffinity)(rolloutPolicy.RolloutPolicy.TrafficAnalysis.SessionAffinity),
-				Metrics: []flaggerv1b1.CanaryMetric{
-					{
-						Name:           "request-success-rate",
-						Interval:       "50s",
-						ThresholdRange: (*flaggerv1b1.CanaryThresholdRange)(rolloutPolicy.RolloutPolicy.TrafficAnalysis.Metrics[0].ThresholdRange),
-					},
-					{
-						Name:           "request-duration",
-						Interval:       "50s",
-						ThresholdRange: (*flaggerv1b1.CanaryThresholdRange)(rolloutPolicy.RolloutPolicy.TrafficAnalysis.Metrics[1].ThresholdRange),
-					},
-				},
-				Webhooks: []flaggerv1b1.CanaryWebhook{
-					{
-						Name:    "generated-testload-0",
-						Timeout: "50s",
-						URL:     "http://istio-system-testloader-kurator-member-loadtester.istio-system/",
-						Metadata: &map[string]string{
-							"type": "cmd",
-							"cmd":  "hey -z 1m -q 10 -c 2 http://podinfo-canary.test:9898/",
-						},
-					},
-					{
-						Name:    "generated-testload-1",
-						Timeout: "50s",
-						URL:     "http://istio-system-testloader-kurator-member-loadtester.istio-system/",
-						Metadata: &map[string]string{
-							"type": "cmd",
-							"cmd":  "curl -sd 'test' http://podinfo-canary:9898/token | grep token",
-						},
-					},
-				},
-			},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if got := renderCanaryAnalysis(tt.args.rolloutPolicy, "kurator-member"); !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("renderCanaryAnalysis() = %v\n, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-/*
-func Test_generateDeployConfig(t *testing.T) {
-	filepath := manifests.BuiltinOrDir("")
-	//fmt.Printf("%s", filepath)
-	deployname := "plugins/testloader-deploy.yaml"
-	namespacedName := types.NamespacedName{
-		Namespace: "test",
-		Name:      "podinfo",
-	}
-	if _, err := generateDeployConfig(filepath, deployname, namespacedName.Name, namespacedName.Namespace); err != nil {
-		fmt.Printf("failed get testloader deployment configuration: %v", err)
-	}
-}
-
-func Test_generateSvcConfig(t *testing.T) {
-	filepath := manifests.BuiltinOrDir("")
-	//fmt.Printf("%s", filepath)
-	svcname := "plugins/testloader-svc.yaml"
-	namespacedName := types.NamespacedName{
-		Namespace: "test",
-		Name:      "podinfo",
-	}
-	if _, err := generateSvcConfig(filepath, svcname, namespacedName.Name, namespacedName.Namespace); err != nil {
-		fmt.Printf("failed get testloader deployment configuration: %v", err)
-	}
-}
-*/
-
-func Test_addLables(t *testing.T) {
-	type args struct {
-		obj   client.Object
-		key   string
-		value string
-	}
-	tests := []struct {
-		name string
-		args args
-		want client.Object
-	}{
-		{
-			name: "function test",
-			args: args{
-				obj: &corev1.Namespace{
-					TypeMeta: metav1.TypeMeta{
-						Kind:       "Namespace",
-						APIVersion: "v1",
-					},
-					ObjectMeta: metav1.ObjectMeta{
-						Name: "webapp",
-						Labels: map[string]string{
-							"xxx": "abc",
-						},
-					},
-				},
-				key:   "istio-injection",
-				value: "ebabled",
-			},
-			want: &corev1.Namespace{
-				TypeMeta: metav1.TypeMeta{
-					Kind:       "Namespace",
-					APIVersion: "v1",
-				},
-				ObjectMeta: metav1.ObjectMeta{
-					Name: "webapp",
-					Labels: map[string]string{
-						"xxx":             "abc",
-						"istio-injection": "ebabled",
-					},
-				},
-			},
-		},
-		{
-			name: "empty labels test",
-			args: args{
-				obj: &corev1.Namespace{
-					TypeMeta: metav1.TypeMeta{
-						Kind:       "Namespace",
-						APIVersion: "v1",
-					},
-					ObjectMeta: metav1.ObjectMeta{
-						Name: "webapp",
-					},
-				},
-				key:   "XXX",
-				value: "abc",
-			},
-			want: &corev1.Namespace{
-				TypeMeta: metav1.TypeMeta{
-					Kind:       "Namespace",
-					APIVersion: "v1",
-				},
-				ObjectMeta: metav1.ObjectMeta{
-					Name: "webapp",
-					Labels: map[string]string{
-						"XXX": "abc",
-					},
-				},
-			},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if got := addLabels(tt.args.obj, tt.args.key, tt.args.value); !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("addLablesOrAnnotaions() = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
diff --git a/pkg/fleet-manager/pipeline/render/predefined_task_test.go b/pkg/fleet-manager/pipeline/render/predefined_task_test.go
deleted file mode 100644
index 0af9be2..0000000
--- a/pkg/fleet-manager/pipeline/render/predefined_task_test.go
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
-Copyright Kurator 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 render
-
-import (
-	"os"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
-	pipelineapi "kurator.dev/kurator/pkg/apis/pipeline/v1alpha1"
-)
-
-func TestRenderPredefinedTask(t *testing.T) {
-	expectedTaskFilePath := "testdata/predefined-task/"
-	// Define test cases for various task templates and configurations.
-	cases := []struct {
-		name         string
-		cfg          PredefinedTaskConfig
-		expectError  bool
-		expectedFile string
-	}{
-		// ---- Case: Default Configuration for Git Clone ----
-		// This case tests the basic configuration of the 'git-clone' template.
-		// It will not include auth, because auth will add in pipeline.
-		{
-			name: "git-clone with basic parameters",
-			cfg: PredefinedTaskConfig{
-				PipelineName: "test-pipeline",
-				Namespace:    "kurator-pipeline",
-				TemplateName: string(pipelineapi.GitClone),
-				Params:       map[string]string{},
-			},
-			expectError:  false,
-			expectedFile: "git-clone.yaml",
-		},
-
-		// ---- Case: Default Configuration for Go Test ----
-		// This case tests the default configuration of the 'go-test' template.
-		// It uses the default namespace and relies on all default parameter values.
-		{
-			name: "go-test with default parameters",
-			cfg: PredefinedTaskConfig{
-				PipelineName: "test-pipeline",
-				Namespace:    "default",
-				TemplateName: string(pipelineapi.GoTest),
-				Params:       map[string]string{},
-			},
-			expectError:  false,
-			expectedFile: "go-test-default.yaml",
-		},
-
-		// ---- Case: Custom Configuration for Go Test ----
-		// This case customizes the 'go-test' template: setting Go version to 1.20,
-		// targeting the './pkg/...' package path, and specifying the Linux ARM architecture.
-		{
-			name: "go-test with custom parameters - Go 1.20, ./pkg/..., Linux ARM",
-			cfg: PredefinedTaskConfig{
-				PipelineName: "test-pipeline",
-				Namespace:    "kurator-pipeline",
-				TemplateName: string(pipelineapi.GoTest),
-				Params: map[string]string{
-					"packages": "./pkg/...",
-					"version":  "1.20",
-					"GOOS":     "linux",
-					"GOARCH":   "arm",
-					"flags":    "-race -cover -v",
-				},
-			},
-			expectError:  false,
-			expectedFile: "go-test-custom-value.yaml",
-		},
-
-		// ---- Case: Custom Configuration for Go Lint ----
-		// This case customizes the 'go-lint' template: setting golangci-lint version to latest,
-		// just specifying additional linting flags.
-		{
-			name: "go-lint with custom parameters - latest version, ./src/..., extra flags",
-			cfg: PredefinedTaskConfig{
-				PipelineName: "test-pipeline",
-				Namespace:    "kurator-pipeline",
-				TemplateName: string(pipelineapi.GoLint),
-				Params:       map[string]string{},
-			},
-			expectError:  false,
-			expectedFile: "go-lint-custom-value.yaml",
-		},
-
-		// ---- Case: Advanced Custom Configuration for Go Lint ----
-		// This case customizes the 'go-lint' template for a more complex scenario: setting
-		// golangci-lint version to a specific older version (1.25.0), targeting a specific
-		// package path './cmd/...', and specifying custom linting flags for that context.
-		{
-			name: "advanced go-lint custom configuration - version 1.25.0, ./cmd/..., specific flags",
-			cfg: PredefinedTaskConfig{
-				PipelineName: "test-pipeline",
-				Namespace:    "kurator-pipeline",
-				TemplateName: string(pipelineapi.GoLint),
-				Params: map[string]string{
-					"package": "./cmd/...",
-					"version": "1.25.0",
-					"flags":   "--enable=govet --enable=errcheck",
-					"GOOS":    "linux",
-					"GOARCH":  "arm",
-				},
-			},
-			expectError:  false,
-			expectedFile: "go-lint-advanced-config.yaml",
-		},
-
-		// ---- Case: default Configuration for build and upload image ----
-		{
-			name: "Custom Configuration for Kaniko Build Task",
-			cfg: PredefinedTaskConfig{
-				PipelineName: "test-pipeline",
-				Namespace:    "kurator-pipeline",
-				TemplateName: string(pipelineapi.BuildPushImage),
-				Params: map[string]string{
-					"image": "ghcr.io/test-orz/test-image:0.3.1",
-				},
-				OwnerReference: &metav1.OwnerReference{
-					APIVersion: "v1",
-					Kind:       "Deployment",
-					Name:       "example-deployment",
-					UID:        "22345678-1234-1234-1234-123456789abc",
-				},
-			},
-			expectError:  false,
-			expectedFile: "build-and-push-image-default.yaml",
-		},
-
-		{
-			name: "Custom Dockerfile and Context for Kaniko Build Task",
-			cfg: PredefinedTaskConfig{
-				PipelineName: "test-pipeline",
-				Namespace:    "kurator-pipeline",
-				TemplateName: string(pipelineapi.BuildPushImage),
-				Params: map[string]string{
-					"image":      "ghcr.io/test-orz/test-image:0.3.2",
-					"dockerfile": "./app/Dockerfile",
-					"context":    "./app/",
-				},
-				OwnerReference: &metav1.OwnerReference{
-					APIVersion: "v1",
-					Kind:       "Deployment",
-					Name:       "example-deployment",
-					UID:        "22345678-1234-1234-1234-123456789abc",
-				},
-			},
-			expectError:  false,
-			expectedFile: "build-and-push-image-custom.yaml",
-		},
-
-		// TODO: Add more test cases here for different task templates or configurations
-	}
-
-	for _, tc := range cases {
-		t.Run(tc.name, func(t *testing.T) {
-			result, err := RenderPredefinedTask(tc.cfg)
-
-			// Test assertions
-			if tc.expectError {
-				assert.Error(t, err)
-			} else {
-				assert.NoError(t, err)
-
-				expected, err := os.ReadFile(expectedTaskFilePath + tc.expectedFile)
-				assert.NoError(t, err)
-				assert.Equal(t, string(expected), string(result))
-			}
-		})
-	}
-}
diff --git a/pkg/fleet-manager/pipeline/render/testdata/predefined-task/build-and-push-image-custom.yaml b/pkg/fleet-manager/pipeline/render/testdata/predefined-task/build-and-push-image-custom.yaml
deleted file mode 100644
index e4014d0..0000000
--- a/pkg/fleet-manager/pipeline/render/testdata/predefined-task/build-and-push-image-custom.yaml
+++ /dev/null
@@ -1,73 +0,0 @@
-apiVersion: tekton.dev/v1beta1
-kind: Task
-metadata:
-  name: build-and-push-image-test-pipeline
-  namespace: kurator-pipeline
-  labels:
-    app.kubernetes.io/version: "0.6"
-  annotations:
-    tekton.dev/pipelines.minVersion: "0.17.0"
-    tekton.dev/categories: Image Build
-    tekton.dev/tags: image-build
-    tekton.dev/displayName: "Build and upload container image using Kaniko"
-    tekton.dev/platforms: "linux/amd64,linux/arm64,linux/ppc64le"
-  ownerReferences:
-  - apiVersion: "v1"
-    kind: "Deployment"
-    name: "example-deployment"
-    uid: "22345678-1234-1234-1234-123456789abc"
-spec:
-  description: >-
-    This Task builds a simple Dockerfile with kaniko and pushes to a registry.
-    This Task stores the image name and digest as results, allowing Tekton Chains to pick up
-    that an image was built & sign it.
-  params:
-  - name: IMAGE # This is a parameter that must be set.
-    description: Name (reference) of the image to build.
-    default: ghcr.io/test-orz/test-image:0.3.2
-  - name: DOCKERFILE
-    description: Path to the Dockerfile to build.
-    default: ./app/Dockerfile
-  - name: CONTEXT
-    description: The build context used by Kaniko.
-    default: ./app/
-  - name: EXTRA_ARGS # more details see https://github.com/GoogleContainerTools/kaniko?tab=readme-ov-file#additional-flags
-    type: array
-    default: []
-  - name: BUILDER_IMAGE
-    description: The image on which builds will run (default is v1.19.2 debug)
-    default: gcr.io/kaniko-project/executor@sha256:899886a2db1c127ff1565d5c7b1e574af1810bbdad048e9850e4f40b5848d79c
-  workspaces:
-  - name: source
-    description: Holds the context and Dockerfile
-  - name: dockerconfig
-    description: Includes a docker "config.json"
-    optional: true
-    mountPath: /kaniko/.docker
-  results:
-  - name: IMAGE_DIGEST
-    description: Digest of the image just built.
-  - name: IMAGE_URL
-    description: URL of the image just built.
-  steps:
-  - name: build-and-push
-    workingDir: $(workspaces.source.path)
-    image: $(params.BUILDER_IMAGE)
-    args:
-    - $(params.EXTRA_ARGS)
-    - --dockerfile=$(params.DOCKERFILE)
-    - --context=$(workspaces.source.path)/$(params.CONTEXT) # The user does not need to care the workspace and the source.
-    - --destination=$(params.IMAGE)
-    - --digest-file=$(results.IMAGE_DIGEST.path)
-    - --ignore-path=/product_uuid # in case kind cluster run failed, see https://github.com/GoogleContainerTools/kaniko/issues/2164
-    # kaniko assumes it is running as root, which means this example fails on platforms
-    # that default to run containers as random uid (like OpenShift). Adding this securityContext
-    # makes it explicit that it needs to run as root.
-    securityContext:
-      runAsUser: 0
-  - name: write-url
-    image: docker.io/library/bash:5.1.4@sha256:c523c636b722339f41b6a431b44588ab2f762c5de5ec3bd7964420ff982fb1d9
-    script: |
-      set -e
-      image="$(params.IMAGE)"
-      echo -n "${image}" | tee "$(results.IMAGE_URL.path)"
diff --git a/pkg/fleet-manager/pipeline/render/testdata/predefined-task/build-and-push-image-default.yaml b/pkg/fleet-manager/pipeline/render/testdata/predefined-task/build-and-push-image-default.yaml
deleted file mode 100644
index dabcb4b..0000000
--- a/pkg/fleet-manager/pipeline/render/testdata/predefined-task/build-and-push-image-default.yaml
+++ /dev/null
@@ -1,73 +0,0 @@
-apiVersion: tekton.dev/v1beta1
-kind: Task
-metadata:
-  name: build-and-push-image-test-pipeline
-  namespace: kurator-pipeline
-  labels:
-    app.kubernetes.io/version: "0.6"
-  annotations:
-    tekton.dev/pipelines.minVersion: "0.17.0"
-    tekton.dev/categories: Image Build
-    tekton.dev/tags: image-build
-    tekton.dev/displayName: "Build and upload container image using Kaniko"
-    tekton.dev/platforms: "linux/amd64,linux/arm64,linux/ppc64le"
-  ownerReferences:
-  - apiVersion: "v1"
-    kind: "Deployment"
-    name: "example-deployment"
-    uid: "22345678-1234-1234-1234-123456789abc"
-spec:
-  description: >-
-    This Task builds a simple Dockerfile with kaniko and pushes to a registry.
-    This Task stores the image name and digest as results, allowing Tekton Chains to pick up
-    that an image was built & sign it.
-  params:
-  - name: IMAGE # This is a parameter that must be set.
-    description: Name (reference) of the image to build.
-    default: ghcr.io/test-orz/test-image:0.3.1
-  - name: DOCKERFILE
-    description: Path to the Dockerfile to build.
-    default: ./Dockerfile
-  - name: CONTEXT
-    description: The build context used by Kaniko.
-    default: ./
-  - name: EXTRA_ARGS # more details see https://github.com/GoogleContainerTools/kaniko?tab=readme-ov-file#additional-flags
-    type: array
-    default: []
-  - name: BUILDER_IMAGE
-    description: The image on which builds will run (default is v1.19.2 debug)
-    default: gcr.io/kaniko-project/executor@sha256:899886a2db1c127ff1565d5c7b1e574af1810bbdad048e9850e4f40b5848d79c
-  workspaces:
-  - name: source
-    description: Holds the context and Dockerfile
-  - name: dockerconfig
-    description: Includes a docker "config.json"
-    optional: true
-    mountPath: /kaniko/.docker
-  results:
-  - name: IMAGE_DIGEST
-    description: Digest of the image just built.
-  - name: IMAGE_URL
-    description: URL of the image just built.
-  steps:
-  - name: build-and-push
-    workingDir: $(workspaces.source.path)
-    image: $(params.BUILDER_IMAGE)
-    args:
-    - $(params.EXTRA_ARGS)
-    - --dockerfile=$(params.DOCKERFILE)
-    - --context=$(workspaces.source.path)/$(params.CONTEXT) # The user does not need to care the workspace and the source.
-    - --destination=$(params.IMAGE)
-    - --digest-file=$(results.IMAGE_DIGEST.path)
-    - --ignore-path=/product_uuid # in case kind cluster run failed, see https://github.com/GoogleContainerTools/kaniko/issues/2164
-    # kaniko assumes it is running as root, which means this example fails on platforms
-    # that default to run containers as random uid (like OpenShift). Adding this securityContext
-    # makes it explicit that it needs to run as root.
-    securityContext:
-      runAsUser: 0
-  - name: write-url
-    image: docker.io/library/bash:5.1.4@sha256:c523c636b722339f41b6a431b44588ab2f762c5de5ec3bd7964420ff982fb1d9
-    script: |
-      set -e
-      image="$(params.IMAGE)"
-      echo -n "${image}" | tee "$(results.IMAGE_URL.path)"
diff --git a/pkg/fleet-manager/pipeline/render/testdata/predefined-task/git-clone.yaml b/pkg/fleet-manager/pipeline/render/testdata/predefined-task/git-clone.yaml
deleted file mode 100644
index 31974a3..0000000
--- a/pkg/fleet-manager/pipeline/render/testdata/predefined-task/git-clone.yaml
+++ /dev/null
@@ -1,234 +0,0 @@
-apiVersion: tekton.dev/v1beta1
-kind: Task
-metadata:
-  name: git-clone-test-pipeline
-  namespace: kurator-pipeline
-  labels:
-    app.kubernetes.io/version: "0.9"
-  annotations:
-    tekton.dev/pipelines.minVersion: "0.38.0"
-    tekton.dev/categories: Git
-    tekton.dev/tags: git
-    tekton.dev/displayName: "git clone"
-    tekton.dev/platforms: "linux/amd64,linux/s390x,linux/ppc64le,linux/arm64"
-spec:
-  description: >-
-    These Tasks are Git tasks to work with repositories used by other tasks
-    in your Pipeline.
-    The git-clone Task will clone a repo from the provided url into the
-    source Workspace. By default the repo will be cloned into the root of
-    your Workspace. You can clone into a subdirectory by setting this Task's
-    subdirectory param. This Task also supports sparse checkouts. To perform
-    a sparse checkout, pass a list of comma separated directory patterns to
-    this Task's sparseCheckoutDirectories param.
-  workspaces:
-  - name: source
-    description: The git repo will be cloned onto the volume backing this Workspace.
-  - name: ssh-directory
-    optional: true
-    description: |
-      A .ssh directory with private key, known_hosts, config, etc. Copied to
-      the user's home before git commands are executed. Used to authenticate
-      with the git remote when performing the clone. Binding a Secret to this
-      Workspace is strongly recommended over other volume types.
-  - name: basic-auth
-    optional: true
-    description: |
-      A Workspace containing a .gitconfig and .git-credentials file. These
-      will be copied to the user's home before any git commands are run. Any
-      other files in this Workspace are ignored. It is strongly recommended
-      to use ssh-directory over basic-auth whenever possible and to bind a
-      Secret to this Workspace over other volume types.
-  - name: ssl-ca-directory
-    optional: true
-    description: |
-      A workspace containing CA certificates, this will be used by Git to
-      verify the peer with when fetching or pushing over HTTPS.
-  params:
-  - name: url
-    description: Repository URL to clone from.
-    type: string
-  - name: revision
-    description: Revision to checkout. (branch, tag, sha, ref, etc...)
-    type: string
-    default: ""
-  - name: refspec
-    description: Refspec to fetch before checking out revision.
-    default: ""
-  - name: submodules
-    description: Initialize and fetch git submodules.
-    type: string
-    default: "true"
-  - name: depth
-    description: Perform a shallow clone, fetching only the most recent N commits.
-    type: string
-    default: "1"
-  - name: sslVerify
-    description: Set the "http.sslVerify" global git config. Setting this to "false" is not advised unless you are sure that you trust your git remote.
-    type: string
-    default: "true"
-  - name: crtFileName
-    description: file name of mounted crt using ssl-ca-directory workspace. default value is ca-bundle.crt.
-    type: string
-    default: "ca-bundle.crt"
-  - name: subdirectory
-    description: Subdirectory inside the "source" Workspace to clone the repo into.
-    type: string
-    default: ""
-  - name: sparseCheckoutDirectories
-    description: Define the directory patterns to match or exclude when performing a sparse checkout.
-    type: string
-    default: ""
-  - name: deleteExisting
-    description: Clean out the contents of the destination directory if it already exists before cloning.
-    type: string
-    default: "true"
-  - name: httpProxy
-    description: HTTP proxy server for non-SSL requests.
-    type: string
-    default: ""
-  - name: httpsProxy
-    description: HTTPS proxy server for SSL requests.
-    type: string
-    default: ""
-  - name: noProxy
-    description: Opt out of proxying HTTP/HTTPS requests.
-    type: string
-    default: ""
-  - name: verbose
-    description: Log the commands that are executed during "git-clone"'s operation.
-    type: string
-    default: "true"
-  - name: gitInitImage
-    description: The image providing the git-init binary that this Task runs.
-    type: string
-    default: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.40.2"
-  - name: userHome
-    description: |
-      Absolute path to the user's home directory.
-    type: string
-    default: "/home/git"
-  results:
-  - name: commit
-    description: The precise commit SHA that was fetched by this Task.
-  - name: url
-    description: The precise URL that was fetched by this Task.
-  - name: committer-date
-    description: The epoch timestamp of the commit that was fetched by this Task.
-  steps:
-  - name: clone
-    image: "$(params.gitInitImage)"
-    env:
-    - name: HOME
-      value: "$(params.userHome)"
-    - name: PARAM_URL
-      value: $(params.url)
-    - name: PARAM_REVISION
-      value: $(params.revision)
-    - name: PARAM_REFSPEC
-      value: $(params.refspec)
-    - name: PARAM_SUBMODULES
-      value: $(params.submodules)
-    - name: PARAM_DEPTH
-      value: $(params.depth)
-    - name: PARAM_SSL_VERIFY
-      value: $(params.sslVerify)
-    - name: PARAM_CRT_FILENAME
-      value: $(params.crtFileName)
-    - name: PARAM_SUBDIRECTORY
-      value: $(params.subdirectory)
-    - name: PARAM_DELETE_EXISTING
-      value: $(params.deleteExisting)
-    - name: PARAM_HTTP_PROXY
-      value: $(params.httpProxy)
-    - name: PARAM_HTTPS_PROXY
-      value: $(params.httpsProxy)
-    - name: PARAM_NO_PROXY
-      value: $(params.noProxy)
-    - name: PARAM_VERBOSE
-      value: $(params.verbose)
-    - name: PARAM_SPARSE_CHECKOUT_DIRECTORIES
-      value: $(params.sparseCheckoutDirectories)
-    - name: PARAM_USER_HOME
-      value: $(params.userHome)
-    - name: WORKSPACE_SOURCE_PATH
-      value: $(workspaces.source.path)
-    - name: WORKSPACE_SSH_DIRECTORY_BOUND
-      value: $(workspaces.ssh-directory.bound)
-    - name: WORKSPACE_SSH_DIRECTORY_PATH
-      value: $(workspaces.ssh-directory.path)
-    - name: WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND
-      value: $(workspaces.basic-auth.bound)
-    - name: WORKSPACE_BASIC_AUTH_DIRECTORY_PATH
-      value: $(workspaces.basic-auth.path)
-    - name: WORKSPACE_SSL_CA_DIRECTORY_BOUND
-      value: $(workspaces.ssl-ca-directory.bound)
-    - name: WORKSPACE_SSL_CA_DIRECTORY_PATH
-      value: $(workspaces.ssl-ca-directory.path)
-    securityContext:
-      runAsNonRoot: true
-      runAsUser: 65532
-    script: |
-      #!/usr/bin/env sh
-      set -eu
-      if [ "${PARAM_VERBOSE}" = "true" ] ; then
-        set -x
-      fi
-      if [ "${WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND}" = "true" ] ; then
-        cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.git-credentials" "${PARAM_USER_HOME}/.git-credentials"
-        cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.gitconfig" "${PARAM_USER_HOME}/.gitconfig"
-        chmod 400 "${PARAM_USER_HOME}/.git-credentials"
-        chmod 400 "${PARAM_USER_HOME}/.gitconfig"
-      fi
-      if [ "${WORKSPACE_SSH_DIRECTORY_BOUND}" = "true" ] ; then
-        cp -R "${WORKSPACE_SSH_DIRECTORY_PATH}" "${PARAM_USER_HOME}"/.ssh
-        chmod 700 "${PARAM_USER_HOME}"/.ssh
-        chmod -R 400 "${PARAM_USER_HOME}"/.ssh/*
-      fi
-      if [ "${WORKSPACE_SSL_CA_DIRECTORY_BOUND}" = "true" ] ; then
-         export GIT_SSL_CAPATH="${WORKSPACE_SSL_CA_DIRECTORY_PATH}"
-         if [ "${PARAM_CRT_FILENAME}" != "" ] ; then
-            export GIT_SSL_CAINFO="${WORKSPACE_SSL_CA_DIRECTORY_PATH}/${PARAM_CRT_FILENAME}"
-         fi
-      fi
-      CHECKOUT_DIR="${WORKSPACE_SOURCE_PATH}/${PARAM_SUBDIRECTORY}"
-      cleandir() {
-        # Delete any existing contents of the repo directory if it exists.
-        #
-        # We don't just "rm -rf ${CHECKOUT_DIR}" because ${CHECKOUT_DIR} might be "/"
-        # or the root of a mounted volume.
-        if [ -d "${CHECKOUT_DIR}" ] ; then
-          # Delete non-hidden files and directories
-          rm -rf "${CHECKOUT_DIR:?}"/*
-          # Delete files and directories starting with . but excluding ..
-          rm -rf "${CHECKOUT_DIR}"/.[!.]*
-          # Delete files and directories starting with .. plus any other character
-          rm -rf "${CHECKOUT_DIR}"/..?*
-        fi
-      }
-      if [ "${PARAM_DELETE_EXISTING}" = "true" ] ; then
-        cleandir || true
-      fi
-      test -z "${PARAM_HTTP_PROXY}" || export HTTP_PROXY="${PARAM_HTTP_PROXY}"
-      test -z "${PARAM_HTTPS_PROXY}" || export HTTPS_PROXY="${PARAM_HTTPS_PROXY}"
-      test -z "${PARAM_NO_PROXY}" || export NO_PROXY="${PARAM_NO_PROXY}"
-      git config --global --add safe.directory "${WORKSPACE_SOURCE_PATH}"
-      /ko-app/git-init \
-        -url="${PARAM_URL}" \
-        -revision="${PARAM_REVISION}" \
-        -refspec="${PARAM_REFSPEC}" \
-        -path="${CHECKOUT_DIR}" \
-        -sslVerify="${PARAM_SSL_VERIFY}" \
-        -submodules="${PARAM_SUBMODULES}" \
-        -depth="${PARAM_DEPTH}" \
-        -sparseCheckoutDirectories="${PARAM_SPARSE_CHECKOUT_DIRECTORIES}"
-      cd "${CHECKOUT_DIR}"
-      RESULT_SHA="$(git rev-parse HEAD)"
-      EXIT_CODE="$?"
-      if [ "${EXIT_CODE}" != 0 ] ; then
-        exit "${EXIT_CODE}"
-      fi
-      RESULT_COMMITTER_DATE="$(git log -1 --pretty=%ct)"
-      printf "%s" "${RESULT_COMMITTER_DATE}" > "$(results.committer-date.path)"
-      printf "%s" "${RESULT_SHA}" > "$(results.commit.path)"
-      printf "%s" "${PARAM_URL}" > "$(results.url.path)"
diff --git a/pkg/fleet-manager/pipeline/render/testdata/predefined-task/go-lint-advanced-config.yaml b/pkg/fleet-manager/pipeline/render/testdata/predefined-task/go-lint-advanced-config.yaml
deleted file mode 100644
index 1239a9a..0000000
--- a/pkg/fleet-manager/pipeline/render/testdata/predefined-task/go-lint-advanced-config.yaml
+++ /dev/null
@@ -1,72 +0,0 @@
-apiVersion: tekton.dev/v1beta1
-kind: Task
-metadata:
-  name: go-lint-test-pipeline
-  namespace: kurator-pipeline
-  labels:
-    app.kubernetes.io/version: "0.2"
-  annotations:
-    tekton.dev/pipelines.minVersion: "0.12.1"
-    tekton.dev/categories: Code Quality
-    tekton.dev/tags: lint
-    tekton.dev/displayName: "golangci lint"
-    tekton.dev/platforms: "linux/amd64"
-spec:
-  description: >-
-    This Task is Golang task to validate Go projects.
-
-  params:
-  - name: package
-    description: base package (and its children) under validation
-    default: "./cmd/..."
-  - name: context
-    description: path to the directory to use as context.
-    default: "."
-  - name: flags
-    description: flags to use for the lint command
-    default: "--enable=govet --enable=errcheck"
-  - name: version
-    description: golangci-lint version to use
-    default: "1.25.0"
-  - name: GOOS
-    description: "running program's operating system target"
-    default: "linux"
-  - name: GOARCH
-    description: "running program's architecture target"
-    default: "arm"
-  - name: GO111MODULE
-    description: "value of module support"
-    default: "auto"
-  - name: GOCACHE
-    description: "Go caching directory path"
-    default: ""
-  - name: GOMODCACHE
-    description: "Go mod caching directory path"
-    default: ""
-  - name: GOLANGCI_LINT_CACHE
-    description: "golangci-lint cache path"
-    default: ""
-  workspaces:
-  - name: source
-    mountPath: /workspace/src/$(params.package)
-  steps:
-  - name: lint
-    image: docker.io/golangci/golangci-lint:$(params.version)
-    workingDir: $(workspaces.source.path)/$(params.context)
-    script: |
-      golangci-lint run $(params.flags)
-    env:
-    - name: GOPATH
-      value: /workspace
-    - name: GOOS
-      value: "$(params.GOOS)"
-    - name: GOARCH
-      value: "$(params.GOARCH)"
-    - name: GO111MODULE
-      value: "$(params.GO111MODULE)"
-    - name: GOCACHE
-      value: "$(params.GOCACHE)"
-    - name: GOMODCACHE
-      value: "$(params.GOMODCACHE)"
-    - name: GOLANGCI_LINT_CACHE
-      value: "$(params.GOLANGCI_LINT_CACHE)"
diff --git a/pkg/fleet-manager/pipeline/render/testdata/predefined-task/go-lint-custom-value.yaml b/pkg/fleet-manager/pipeline/render/testdata/predefined-task/go-lint-custom-value.yaml
deleted file mode 100644
index d3f6208..0000000
--- a/pkg/fleet-manager/pipeline/render/testdata/predefined-task/go-lint-custom-value.yaml
+++ /dev/null
@@ -1,72 +0,0 @@
-apiVersion: tekton.dev/v1beta1
-kind: Task
-metadata:
-  name: go-lint-test-pipeline
-  namespace: kurator-pipeline
-  labels:
-    app.kubernetes.io/version: "0.2"
-  annotations:
-    tekton.dev/pipelines.minVersion: "0.12.1"
-    tekton.dev/categories: Code Quality
-    tekton.dev/tags: lint
-    tekton.dev/displayName: "golangci lint"
-    tekton.dev/platforms: "linux/amd64"
-spec:
-  description: >-
-    This Task is Golang task to validate Go projects.
-
-  params:
-  - name: package
-    description: base package (and its children) under validation
-    default: "."
-  - name: context
-    description: path to the directory to use as context.
-    default: "."
-  - name: flags
-    description: flags to use for the lint command
-    default: "--verbose"
-  - name: version
-    description: golangci-lint version to use
-    default: "latest"
-  - name: GOOS
-    description: "running program's operating system target"
-    default: "linux"
-  - name: GOARCH
-    description: "running program's architecture target"
-    default: "amd64"
-  - name: GO111MODULE
-    description: "value of module support"
-    default: "auto"
-  - name: GOCACHE
-    description: "Go caching directory path"
-    default: ""
-  - name: GOMODCACHE
-    description: "Go mod caching directory path"
-    default: ""
-  - name: GOLANGCI_LINT_CACHE
-    description: "golangci-lint cache path"
-    default: ""
-  workspaces:
-  - name: source
-    mountPath: /workspace/src/$(params.package)
-  steps:
-  - name: lint
-    image: docker.io/golangci/golangci-lint:$(params.version)
-    workingDir: $(workspaces.source.path)/$(params.context)
-    script: |
-      golangci-lint run $(params.flags)
-    env:
-    - name: GOPATH
-      value: /workspace
-    - name: GOOS
-      value: "$(params.GOOS)"
-    - name: GOARCH
-      value: "$(params.GOARCH)"
-    - name: GO111MODULE
-      value: "$(params.GO111MODULE)"
-    - name: GOCACHE
-      value: "$(params.GOCACHE)"
-    - name: GOMODCACHE
-      value: "$(params.GOMODCACHE)"
-    - name: GOLANGCI_LINT_CACHE
-      value: "$(params.GOLANGCI_LINT_CACHE)"
diff --git a/pkg/fleet-manager/pipeline/render/testdata/predefined-task/go-test-custom-value.yaml b/pkg/fleet-manager/pipeline/render/testdata/predefined-task/go-test-custom-value.yaml
deleted file mode 100644
index def4707..0000000
--- a/pkg/fleet-manager/pipeline/render/testdata/predefined-task/go-test-custom-value.yaml
+++ /dev/null
@@ -1,73 +0,0 @@
-apiVersion: tekton.dev/v1beta1
-kind: Task
-metadata:
-  name: go-test-test-pipeline
-  namespace: kurator-pipeline
-  labels:
-    app.kubernetes.io/version: "0.2"
-  annotations:
-    tekton.dev/pipelines.minVersion: "0.12.1"
-    tekton.dev/categories: Testing
-    tekton.dev/tags: test
-    tekton.dev/displayName: "golang test"
-    tekton.dev/platforms: "linux/amd64,linux/s390x,linux/ppc64le"
-spec:
-  description: >-
-    This Task is Golang task to test Go projects.
-
-  params:
-  - name: package
-    description: package (and its children) under test
-    default: "."
-  - name: packages
-    description: "packages to test (default: ./...)"
-    default: "./pkg/..."
-  - name: context
-    description: path to the directory to use as context.
-    default: "."
-  - name: version
-    description: golang version to use for tests
-    default: "1.20"
-  - name: flags
-    description: flags to use for the test command
-    default: "-race -cover -v"
-  - name: GOOS
-    description: "running program's operating system target"
-    default: "linux"
-  - name: GOARCH
-    description: "running program's architecture target"
-    default: "arm"
-  - name: GO111MODULE
-    description: "value of module support"
-    default: "auto"
-  - name: GOCACHE
-    description: "Go caching directory path"
-    default: ""
-  - name: GOMODCACHE
-    description: "Go mod caching directory path"
-    default: ""
-  workspaces:
-  - name: source
-  steps:
-  - name: unit-test
-    image: docker.io/library/golang:$(params.version)
-    workingDir: $(workspaces.source.path)
-    script: |
-      if [ ! -e $GOPATH/src/$(params.package)/go.mod ];then
-         SRC_PATH="$GOPATH/src/$(params.package)"
-         mkdir -p $SRC_PATH
-         cp -R "$(workspaces.source.path)/$(params.context)"/* $SRC_PATH
-         cd $SRC_PATH
-      fi
-      go test $(params.flags) $(params.packages)
-    env:
-    - name: GOOS
-      value: "$(params.GOOS)"
-    - name: GOARCH
-      value: "$(params.GOARCH)"
-    - name: GO111MODULE
-      value: "$(params.GO111MODULE)"
-    - name: GOCACHE
-      value: "$(params.GOCACHE)"
-    - name: GOMODCACHE
-      value: "$(params.GOMODCACHE)"
diff --git a/pkg/fleet-manager/pipeline/render/testdata/predefined-task/go-test-default.yaml b/pkg/fleet-manager/pipeline/render/testdata/predefined-task/go-test-default.yaml
deleted file mode 100644
index 1e66eb3..0000000
--- a/pkg/fleet-manager/pipeline/render/testdata/predefined-task/go-test-default.yaml
+++ /dev/null
@@ -1,73 +0,0 @@
-apiVersion: tekton.dev/v1beta1
-kind: Task
-metadata:
-  name: go-test-test-pipeline
-  namespace: default
-  labels:
-    app.kubernetes.io/version: "0.2"
-  annotations:
-    tekton.dev/pipelines.minVersion: "0.12.1"
-    tekton.dev/categories: Testing
-    tekton.dev/tags: test
-    tekton.dev/displayName: "golang test"
-    tekton.dev/platforms: "linux/amd64,linux/s390x,linux/ppc64le"
-spec:
-  description: >-
-    This Task is Golang task to test Go projects.
-
-  params:
-  - name: package
-    description: package (and its children) under test
-    default: "."
-  - name: packages
-    description: "packages to test (default: ./...)"
-    default: "./..."
-  - name: context
-    description: path to the directory to use as context.
-    default: "."
-  - name: version
-    description: golang version to use for tests
-    default: "latest"
-  - name: flags
-    description: flags to use for the test command
-    default: "-race -cover -v"
-  - name: GOOS
-    description: "running program's operating system target"
-    default: "linux"
-  - name: GOARCH
-    description: "running program's architecture target"
-    default: "amd64"
-  - name: GO111MODULE
-    description: "value of module support"
-    default: "auto"
-  - name: GOCACHE
-    description: "Go caching directory path"
-    default: ""
-  - name: GOMODCACHE
-    description: "Go mod caching directory path"
-    default: ""
-  workspaces:
-  - name: source
-  steps:
-  - name: unit-test
-    image: docker.io/library/golang:$(params.version)
-    workingDir: $(workspaces.source.path)
-    script: |
-      if [ ! -e $GOPATH/src/$(params.package)/go.mod ];then
-         SRC_PATH="$GOPATH/src/$(params.package)"
-         mkdir -p $SRC_PATH
-         cp -R "$(workspaces.source.path)/$(params.context)"/* $SRC_PATH
-         cd $SRC_PATH
-      fi
-      go test $(params.flags) $(params.packages)
-    env:
-    - name: GOOS
-      value: "$(params.GOOS)"
-    - name: GOARCH
-      value: "$(params.GOARCH)"
-    - name: GO111MODULE
-      value: "$(params.GO111MODULE)"
-    - name: GOCACHE
-      value: "$(params.GOCACHE)"
-    - name: GOMODCACHE
-      value: "$(params.GOMODCACHE)"
diff --git a/pkg/fleet-manager/pipeline/render/testdata/trigger/default.yaml b/pkg/fleet-manager/pipeline/render/testdata/trigger/default.yaml
deleted file mode 100644
index 6fd299c..0000000
--- a/pkg/fleet-manager/pipeline/render/testdata/trigger/default.yaml
+++ /dev/null
@@ -1,70 +0,0 @@
-apiVersion: triggers.tekton.dev/v1alpha1
-kind: TriggerTemplate
-metadata:
-  name: test-pipeline-triggertemplate
-  namespace: kurator-pipeline
-spec:
-  params:
-  - name: gitrevision
-    description: The git revision
-  - name: gitrepositoryurl
-    description: The git repository url
-  - name: namespace
-    description: The namespace to create the resources
-  resourceTemplates:
-  - apiVersion: tekton.dev/v1beta1
-    kind: PipelineRun
-    metadata:
-      generateName: test-pipeline-run-
-      namespace: $(tt.params.namespace)
-    spec:
-      serviceAccountName: test-pipeline
-      pipelineRef:
-        name: test-pipeline
-      params:
-      - name: revision
-        value: $(tt.params.gitrevision)
-      - name: repo-url
-        value: $(tt.params.gitrepositoryurl)
-      workspaces:
-      - name: kurator-pipeline-shared-data # there only one pvc workspace in each pipeline, and the name is kurator-pipeline-shared-data
-        volumeClaimTemplate:
-          spec:
-            accessModes:
-              - ReadWriteOnce
-            resources:
-              requests:
-                storage: 1Gi
-      - name: git-credentials
-        secret:
-          secretName: git-credentials
-      - name: docker-credentials
-        secret:
-          secretName: docker-credentials  # auth for task
----
-apiVersion: triggers.tekton.dev/v1alpha1
-kind: TriggerBinding
-metadata:
-  name: test-pipeline-triggerbinding
-  namespace: kurator-pipeline
-spec:
-  params:
-  - name: gitrevision
-    value: $(body.head_commit.id)
-  - name: namespace
-    value: kurator-pipeline
-  - name: gitrepositoryurl
-    value: "https://github.com/$(body.repository.full_name)"
----
-apiVersion: triggers.tekton.dev/v1alpha1
-kind: EventListener
-metadata:
-  name: test-pipeline-listener
-  namespace: kurator-pipeline
-spec:
-  serviceAccountName: test-pipeline
-  triggers:
-  - bindings:
-    - ref: test-pipeline-triggerbinding
-    template:
-      ref: test-pipeline-triggertemplate
diff --git a/pkg/fleet-manager/pipeline/render/testdata/trigger/with-volume-claim.yaml b/pkg/fleet-manager/pipeline/render/testdata/trigger/with-volume-claim.yaml
deleted file mode 100644
index e18ab7d..0000000
--- a/pkg/fleet-manager/pipeline/render/testdata/trigger/with-volume-claim.yaml
+++ /dev/null
@@ -1,72 +0,0 @@
-apiVersion: triggers.tekton.dev/v1alpha1
-kind: TriggerTemplate
-metadata:
-  name: test-pipeline-triggertemplate
-  namespace: kurator-pipeline
-spec:
-  params:
-  - name: gitrevision
-    description: The git revision
-  - name: gitrepositoryurl
-    description: The git repository url
-  - name: namespace
-    description: The namespace to create the resources
-  resourceTemplates:
-  - apiVersion: tekton.dev/v1beta1
-    kind: PipelineRun
-    metadata:
-      generateName: test-pipeline-run-
-      namespace: $(tt.params.namespace)
-    spec:
-      serviceAccountName: test-pipeline
-      pipelineRef:
-        name: test-pipeline
-      params:
-      - name: revision
-        value: $(tt.params.gitrevision)
-      - name: repo-url
-        value: $(tt.params.gitrepositoryurl)
-      workspaces:
-      - name: kurator-pipeline-shared-data # there only one pvc workspace in each pipeline, and the name is kurator-pipeline-shared-data
-        volumeClaimTemplate:
-          spec:
-            accessModes:
-              - ReadWriteOnce
-            resources:
-              requests:
-                storage: 500Mi
-            volumeMode: Filesystem
-            storageClassName: manual
-      - name: git-credentials
-        secret:
-          secretName: git-credentials
-      - name: docker-credentials
-        secret:
-          secretName: docker-credentials  # auth for task
----
-apiVersion: triggers.tekton.dev/v1alpha1
-kind: TriggerBinding
-metadata:
-  name: test-pipeline-triggerbinding
-  namespace: kurator-pipeline
-spec:
-  params:
-  - name: gitrevision
-    value: $(body.head_commit.id)
-  - name: namespace
-    value: kurator-pipeline
-  - name: gitrepositoryurl
-    value: "https://github.com/$(body.repository.full_name)"
----
-apiVersion: triggers.tekton.dev/v1alpha1
-kind: EventListener
-metadata:
-  name: test-pipeline-listener
-  namespace: kurator-pipeline
-spec:
-  serviceAccountName: test-pipeline
-  triggers:
-  - bindings:
-    - ref: test-pipeline-triggerbinding
-    template:
-      ref: test-pipeline-triggertemplate
diff --git a/pkg/fleet-manager/pipeline/render/trigger_test.go b/pkg/fleet-manager/pipeline/render/trigger_test.go
deleted file mode 100644
index ac51844..0000000
--- a/pkg/fleet-manager/pipeline/render/trigger_test.go
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-Copyright Kurator 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 render
-
-import (
-	"os"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func TestRenderTrigger(t *testing.T) {
-	expectedRBACFilePath := "testdata/trigger/"
-	cases := []struct {
-		name         string
-		cfg          TriggerConfig
-		expectError  bool
-		expectedFile string
-	}{
-		{
-			name: "default trigger configuration",
-			cfg: TriggerConfig{
-				PipelineName:      "test-pipeline",
-				PipelineNamespace: "kurator-pipeline",
-			},
-			expectError:  false,
-			expectedFile: "default.yaml",
-		},
-		{
-			name: "trigger configuration with custom volume claim",
-			cfg: TriggerConfig{
-				PipelineName:      "test-pipeline",
-				PipelineNamespace: "kurator-pipeline",
-				AccessMode:        "ReadWriteOnce",
-				StorageRequest:    "500Mi",
-				StorageClassName:  "manual",
-				VolumeMode:        "Filesystem",
-			},
-			expectError:  false,
-			expectedFile: "with-volume-claim.yaml",
-		},
-	}
-
-	for _, tc := range cases {
-		t.Run(tc.name, func(t *testing.T) {
-			result, err := RenderTrigger(tc.cfg)
-
-			if tc.expectError {
-				assert.Error(t, err)
-			} else {
-				assert.NoError(t, err)
-
-				expected, err := os.ReadFile(expectedRBACFilePath + tc.expectedFile)
-				assert.NoError(t, err)
-				assert.Equal(t, string(expected), string(result))
-			}
-		})
-	}
-}