You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by zh...@apache.org on 2025/01/14 08:23:45 UTC

(dubbo-kubernetes) branch master updated: [Admin]Fix: Rules pagination & search (#538)

This is an automated email from the ASF dual-hosted git repository.

zhongxjian pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-kubernetes.git


The following commit(s) were added to refs/heads/master by this push:
     new 631856eb [Admin]Fix: Rules pagination & search (#538)
631856eb is described below

commit 631856ebefde4901bf7cf981b8bcbf02717f2030
Author: robb <ro...@gmail.com>
AuthorDate: Tue Jan 14 16:23:40 2025 +0800

    [Admin]Fix: Rules pagination & search (#538)
    
    * Complement config,handler of grafana dashboards and prometheus
    
    * refractor version.go, bump controller-runtime to v0.19.4
    
    * refractor rules
---
 pkg/admin/handler/application.go                   |  24 ++---
 ...traffic_condition_rule.go => condition_rule.go} |  96 +++---------------
 ...raffic_configurator.go => configurator_rule.go} |  92 ++++++-----------
 pkg/admin/handler/instance.go                      |  16 +--
 pkg/admin/handler/service.go                       |  24 ++---
 .../handler/{traffic_tag_rule.go => tag_rule.go}   |  96 ++++++------------
 ...traffic_condition_rule.go => condition_rule.go} |  80 +++++++--------
 ...raffic_configurator.go => configurator_rule.go} |  36 +++----
 .../model/{traffic_tag_rule.go => tag_rule.go}     |  43 +++-----
 pkg/admin/service/condition_rule.go                | 109 +++++++++++++++++++++
 pkg/admin/service/configurator_rule.go             |  69 +++++++++++++
 pkg/admin/service/tag_rule.go                      |  73 ++++++++++++++
 12 files changed, 428 insertions(+), 330 deletions(-)

diff --git a/pkg/admin/handler/application.go b/pkg/admin/handler/application.go
index 0caa74d4..073ed169 100644
--- a/pkg/admin/handler/application.go
+++ b/pkg/admin/handler/application.go
@@ -148,7 +148,7 @@ func ApplicationConfigOperatorLogPut(rt core_runtime.Runtime) gin.HandlerFunc {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		}
-		res, err := getConfigurator(rt, ApplicationName)
+		res, err := service.GetConfigurator(rt, ApplicationName)
 		if err != nil {
 			if core_store.IsResourceNotFound(err) {
 				// for check app exist
@@ -196,13 +196,13 @@ func ApplicationConfigOperatorLogPut(rt core_runtime.Runtime) gin.HandlerFunc {
 		}
 		// restore
 		if isNotExist {
-			err = createConfigurator(rt, ApplicationName, res)
+			err = service.CreateConfigurator(rt, ApplicationName, res)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
 			}
 		} else {
-			err = updateConfigurator(rt, ApplicationName, res)
+			err = service.UpdateConfigurator(rt, ApplicationName, res)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
@@ -219,7 +219,7 @@ func ApplicationConfigOperatorLogGet(rt core_runtime.Runtime) gin.HandlerFunc {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp("appName is required"))
 			return
 		}
-		res, err := getConfigurator(rt, ApplicationName)
+		res, err := service.GetConfigurator(rt, ApplicationName)
 		if err != nil {
 			if core_store.IsResourceNotFound(err) {
 				c.JSON(http.StatusOK, model.NewSuccessResp(map[string]interface{}{"operatorLog": false}))
@@ -255,7 +255,7 @@ func ApplicationConfigFlowWeightGET(rt core_runtime.Runtime) gin.HandlerFunc {
 
 		resp.FlowWeightSets = make([]model.FlowWeightSet, 0)
 
-		res, err := getConfigurator(rt, ApplicationName)
+		res, err := service.GetConfigurator(rt, ApplicationName)
 		if err != nil {
 			if core_store.IsResourceNotFound(err) {
 				c.JSON(http.StatusOK, model.NewSuccessResp(resp))
@@ -323,7 +323,7 @@ func ApplicationConfigFlowWeightPUT(rt core_runtime.Runtime) gin.HandlerFunc {
 		}
 		// get from store, or generate default resource
 		isNotExist := false
-		res, err := getConfigurator(rt, ApplicationName)
+		res, err := service.GetConfigurator(rt, ApplicationName)
 		if err != nil {
 			if core_store.IsResourceNotFound(err) {
 				// for check app exist
@@ -363,13 +363,13 @@ func ApplicationConfigFlowWeightPUT(rt core_runtime.Runtime) gin.HandlerFunc {
 		}
 		// restore
 		if isNotExist {
-			err = createConfigurator(rt, ApplicationName, res)
+			err = service.CreateConfigurator(rt, ApplicationName, res)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
 			}
 		} else {
-			err = updateConfigurator(rt, ApplicationName, res)
+			err = service.UpdateConfigurator(rt, ApplicationName, res)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
@@ -393,7 +393,7 @@ func ApplicationConfigGrayGET(rt core_runtime.Runtime) gin.HandlerFunc {
 			return
 		}
 
-		res, err := getTagRule(rt, ApplicationName)
+		res, err := service.GetTagRule(rt, ApplicationName)
 		if err != nil {
 			if core_store.IsResourceNotFound(err) {
 				resp.GraySets = make([]model.GraySet, 0)
@@ -440,7 +440,7 @@ func ApplicationConfigGrayPUT(rt core_runtime.Runtime) gin.HandlerFunc {
 		}
 
 		isNotExist := false
-		res, err := getTagRule(rt, ApplicationName)
+		res, err := service.GetTagRule(rt, ApplicationName)
 		if core_store.IsResourceNotFound(err) {
 			data, err := service.GetApplicationDetail(rt, &model.ApplicationDetailReq{AppName: ApplicationName})
 			if err != nil {
@@ -473,13 +473,13 @@ func ApplicationConfigGrayPUT(rt core_runtime.Runtime) gin.HandlerFunc {
 
 		// restore
 		if isNotExist {
-			err = createTagRule(rt, ApplicationName, res)
+			err = service.CreateTagRule(rt, ApplicationName, res)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
 			}
 		} else {
-			err = updateTagRule(rt, ApplicationName, res)
+			err = service.UpdateTagRule(rt, ApplicationName, res)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
diff --git a/pkg/admin/handler/traffic_condition_rule.go b/pkg/admin/handler/condition_rule.go
similarity index 62%
rename from pkg/admin/handler/traffic_condition_rule.go
rename to pkg/admin/handler/condition_rule.go
index d9f6ad5c..c830a6e7 100644
--- a/pkg/admin/handler/traffic_condition_rule.go
+++ b/pkg/admin/handler/condition_rule.go
@@ -20,6 +20,7 @@ package handler
 import (
 	"encoding/json"
 	"fmt"
+	"github.com/apache/dubbo-kubernetes/pkg/admin/service"
 	"io"
 	"net/http"
 	"strings"
@@ -35,47 +36,23 @@ import (
 	mesh_proto "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1"
 	"github.com/apache/dubbo-kubernetes/pkg/admin/model"
 	"github.com/apache/dubbo-kubernetes/pkg/core/consts"
-	"github.com/apache/dubbo-kubernetes/pkg/core/logger"
 	"github.com/apache/dubbo-kubernetes/pkg/core/resources/apis/mesh"
-	res_model "github.com/apache/dubbo-kubernetes/pkg/core/resources/model"
-	"github.com/apache/dubbo-kubernetes/pkg/core/resources/store"
 	core_runtime "github.com/apache/dubbo-kubernetes/pkg/core/runtime"
 )
 
 func ConditionRuleSearch(rt core_runtime.Runtime) gin.HandlerFunc {
 	return func(c *gin.Context) {
-		resList := &mesh.ConditionRouteResourceList{
-			Items: make([]*mesh.ConditionRouteResource, 0),
-		}
-		if err := rt.ResourceManager().List(rt.AppContext(), resList); err != nil {
+		req := model.NewSearchConditionRuleReq()
+		if err := c.ShouldBindQuery(req); err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		}
-		resp := model.ConditionRuleSearchResp{
-			Code:    http.StatusOK,
-			Message: "success",
-			Data:    make([]model.ConditionRuleSearchResp_Data, 0, len(resList.Items)),
-		}
-		for _, item := range resList.Items {
-			if v3 := item.Spec.ToConditionRouteV3(); v3 != nil {
-				resp.Data = append(resp.Data, model.ConditionRuleSearchResp_Data{
-					RuleName:   item.Meta.GetName(),
-					Scope:      v3.GetScope(),
-					CreateTime: item.Meta.GetCreationTime().String(),
-					Enabled:    v3.GetEnabled(),
-				})
-			} else if v3x1 := item.Spec.ToConditionRouteV3x1(); v3x1 != nil {
-				resp.Data = append(resp.Data, model.ConditionRuleSearchResp_Data{
-					RuleName:   item.Meta.GetName(),
-					Scope:      v3x1.GetScope(),
-					CreateTime: item.Meta.GetCreationTime().String(),
-					Enabled:    v3x1.GetEnabled(),
-				})
-			} else {
-				panic("invalid condition route item")
-			}
+		resp, err := service.SearchConditionRules(rt, req)
+		if err != nil {
+			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
+			return
 		}
-		c.JSON(http.StatusOK, resp)
+		c.JSON(http.StatusOK, model.NewSuccessResp(resp))
 	}
 }
 
@@ -89,29 +66,18 @@ func GetConditionRuleWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(fmt.Sprintf("ruleName must end with %s", consts.ConditionRuleSuffix)))
 			return
 		}
-		if res, err := getConditionRule(rt, name); err != nil {
+		if res, err := service.GetConditionRule(rt, name); err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		} else {
 			if v3x1 := res.Spec.ToConditionRouteV3x1(); v3x1 != nil {
 				res.Spec = v3x1.ToConditionRoute()
 			}
-			c.JSON(http.StatusOK, model.GenConditionRuleToResp(http.StatusOK, "success", res.Spec))
+			c.JSON(http.StatusOK, model.GenConditionRuleToResp(res.Spec))
 		}
 	}
 }
 
-func getConditionRule(rt core_runtime.Runtime, name string) (*mesh.ConditionRouteResource, error) {
-	res := &mesh.ConditionRouteResource{Spec: &mesh_proto.ConditionRoute{}}
-	if err := rt.ResourceManager().Get(rt.AppContext(), res,
-		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
-		store.GetByApplication(name), store.GetByKey(name+consts.ConditionRuleSuffix, res_model.DefaultMesh)); err != nil {
-		logger.Warnf("get %s condition failed with error: %s", name, err.Error())
-		return nil, err
-	}
-	return res, nil
-}
-
 func bodyToMap(reader io.ReadCloser) (map[string]interface{}, error) {
 	defer reader.Close()
 	res := map[string]interface{}{}
@@ -178,25 +144,15 @@ func PutConditionRuleWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 			return
 		}
 
-		if err := updateConditionRule(rt, name, res); err != nil {
+		if err := service.UpdateConditionRule(rt, name, res); err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		} else {
-			c.JSON(http.StatusOK, model.GenConditionRuleToResp(http.StatusOK, "success", nil))
+			c.JSON(http.StatusOK, model.GenConditionRuleToResp(res.Spec))
 		}
 	}
 }
 
-func updateConditionRule(rt core_runtime.Runtime, name string, res *mesh.ConditionRouteResource) error {
-	if err := rt.ResourceManager().Update(rt.AppContext(), res,
-		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
-		store.UpdateByApplication(name), store.UpdateByKey(name+consts.ConditionRuleSuffix, res_model.DefaultMesh)); err != nil {
-		logger.Warnf("update %s condition failed with error: %s", name, err.Error())
-		return err
-	}
-	return nil
-}
-
 func PostConditionRuleWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 	return func(c *gin.Context) {
 		var name string
@@ -243,25 +199,15 @@ func PostConditionRuleWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 			return
 		}
 
-		if err := createConditionRule(rt, name, res); err != nil {
+		if err := service.CreateConditionRule(rt, name, res); err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		} else {
-			c.JSON(http.StatusCreated, model.GenConditionRuleToResp(http.StatusCreated, "success", nil))
+			c.JSON(http.StatusOK, model.GenConditionRuleToResp(res.Spec))
 		}
 	}
 }
 
-func createConditionRule(rt core_runtime.Runtime, name string, res *mesh.ConditionRouteResource) error {
-	if err := rt.ResourceManager().Create(rt.AppContext(), res,
-		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
-		store.CreateByApplication(name), store.CreateByKey(name+consts.ConditionRuleSuffix, res_model.DefaultMesh)); err != nil {
-		logger.Warnf("create %s condition failed with error: %s", name, err.Error())
-		return err
-	}
-	return nil
-}
-
 func DeleteConditionRuleWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 	return func(c *gin.Context) {
 		var name string
@@ -273,20 +219,10 @@ func DeleteConditionRuleWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(fmt.Sprintf("ruleName must end with %s", consts.ConditionRuleSuffix)))
 			return
 		}
-		if err := deleteConditionRule(rt, name, res); err != nil {
+		if err := service.DeleteConditionRule(rt, name, res); err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		}
-		c.JSON(http.StatusNoContent, model.GenConditionRuleToResp(http.StatusNoContent, "success", nil))
-	}
-}
-
-func deleteConditionRule(rt core_runtime.Runtime, name string, res *mesh.ConditionRouteResource) error {
-	if err := rt.ResourceManager().Delete(rt.AppContext(), res,
-		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
-		store.DeleteByApplication(name), store.DeleteByKey(name+consts.ConditionRuleSuffix, res_model.DefaultMesh)); err != nil {
-		logger.Warnf("delete %s condition failed with error: %s", name, err.Error())
-		return err
+		c.JSON(http.StatusOK, model.NewSuccessResp(""))
 	}
-	return nil
 }
diff --git a/pkg/admin/handler/traffic_configurator.go b/pkg/admin/handler/configurator_rule.go
similarity index 57%
rename from pkg/admin/handler/traffic_configurator.go
rename to pkg/admin/handler/configurator_rule.go
index 6d49fcf9..4b8a7a38 100644
--- a/pkg/admin/handler/traffic_configurator.go
+++ b/pkg/admin/handler/configurator_rule.go
@@ -19,7 +19,9 @@ package handler
 
 import (
 	"fmt"
+	"github.com/apache/dubbo-kubernetes/pkg/admin/service"
 	"net/http"
+	"strconv"
 	"strings"
 )
 
@@ -31,36 +33,43 @@ import (
 	mesh_proto "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1"
 	"github.com/apache/dubbo-kubernetes/pkg/admin/model"
 	"github.com/apache/dubbo-kubernetes/pkg/core/consts"
-	"github.com/apache/dubbo-kubernetes/pkg/core/logger"
 	"github.com/apache/dubbo-kubernetes/pkg/core/resources/apis/mesh"
-	res_model "github.com/apache/dubbo-kubernetes/pkg/core/resources/model"
 	"github.com/apache/dubbo-kubernetes/pkg/core/resources/store"
 	core_runtime "github.com/apache/dubbo-kubernetes/pkg/core/runtime"
 )
 
 func ConfiguratorSearch(rt core_runtime.Runtime) gin.HandlerFunc {
 	return func(c *gin.Context) {
-		resList := &mesh.DynamicConfigResourceList{
-			Items: make([]*mesh.DynamicConfigResource, 0),
-		}
-		if err := rt.ResourceManager().List(rt.AppContext(), resList); err != nil {
+		req := model.NewSearchConfiguratorReq()
+		if err := c.ShouldBindQuery(req); err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		}
-		resp := model.ConfiguratorSearchResp{
-			Code:    200,
-			Message: "success",
-			Data:    make([]model.ConfiguratorSearchResp_Data, 0, len(resList.Items)),
+		ruleList := &mesh.DynamicConfigResourceList{}
+		var respList []model.ConfiguratorSearchResp
+		if req.Keywords == "" {
+			if err := rt.ResourceManager().List(rt.AppContext(), ruleList, store.ListByPage(req.PageSize, strconv.Itoa(req.PageOffset))); err != nil {
+				c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
+				return
+			}
+		} else {
+			if err := rt.ResourceManager().List(rt.AppContext(), ruleList, store.ListByNameContains(req.Keywords), store.ListByPage(req.PageSize, strconv.Itoa(req.PageOffset))); err != nil {
+				c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
+				return
+			}
 		}
-		for _, item := range resList.Items {
-			resp.Data = append(resp.Data, model.ConfiguratorSearchResp_Data{
+		for _, item := range ruleList.Items {
+			respList = append(respList, model.ConfiguratorSearchResp{
 				RuleName:   item.Meta.GetName(),
 				Scope:      item.Spec.GetScope(),
 				CreateTime: item.Meta.GetCreationTime().String(),
 				Enabled:    item.Spec.GetEnabled(),
 			})
 		}
-		c.JSON(http.StatusOK, resp)
+		result := model.NewSearchPaginationResult()
+		result.List = respList
+		result.PageInfo = &ruleList.Pagination
+		c.JSON(http.StatusOK, model.NewSuccessResp(result))
 	}
 }
 
@@ -74,26 +83,15 @@ func GetConfiguratorWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(fmt.Sprintf("ruleName must end with %s", consts.ConfiguratorRuleSuffix)))
 			return
 		}
-		res, err := getConfigurator(rt, name)
+		res, err := service.GetConfigurator(rt, name)
 		if err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		}
-		c.JSON(http.StatusOK, model.GenDynamicConfigToResp(http.StatusOK, "success", res.Spec))
+		c.JSON(http.StatusOK, model.GenDynamicConfigToResp(res.Spec))
 	}
 }
 
-func getConfigurator(rt core_runtime.Runtime, name string) (*mesh.DynamicConfigResource, error) {
-	res := &mesh.DynamicConfigResource{Spec: &mesh_proto.DynamicConfig{}}
-	if err := rt.ResourceManager().Get(rt.AppContext(), res,
-		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
-		store.GetByApplication(name), store.GetByKey(name+consts.ConfiguratorRuleSuffix, res_model.DefaultMesh)); err != nil {
-		logger.Warnf("get %s configurator failed with error: %s", name, err.Error())
-		return nil, err
-	}
-	return res, nil
-}
-
 func PutConfiguratorWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 	return func(c *gin.Context) {
 		var name string
@@ -113,25 +111,15 @@ func PutConfiguratorWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		}
-		if err = updateConfigurator(rt, name, res); err != nil {
+		if err = service.UpdateConfigurator(rt, name, res); err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		} else {
-			c.JSON(http.StatusOK, model.GenDynamicConfigToResp(http.StatusOK, "success", nil))
+			c.JSON(http.StatusOK, model.GenDynamicConfigToResp(res.Spec))
 		}
 	}
 }
 
-func updateConfigurator(rt core_runtime.Runtime, name string, res *mesh.DynamicConfigResource) error {
-	if err := rt.ResourceManager().Update(rt.AppContext(), res,
-		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
-		store.UpdateByApplication(name), store.UpdateByKey(name+consts.ConfiguratorRuleSuffix, res_model.DefaultMesh)); err != nil {
-		logger.Warnf("update %s configurator failed with error: %s", name, err.Error())
-		return err
-	}
-	return nil
-}
-
 func PostConfiguratorWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 	return func(c *gin.Context) {
 		var name string
@@ -151,25 +139,15 @@ func PostConfiguratorWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		}
-		if err = createConfigurator(rt, name, res); err != nil {
+		if err = service.CreateConfigurator(rt, name, res); err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		} else {
-			c.JSON(http.StatusCreated, model.GenDynamicConfigToResp(http.StatusCreated, "success", nil))
+			c.JSON(http.StatusOK, model.GenDynamicConfigToResp(res.Spec))
 		}
 	}
 }
 
-func createConfigurator(rt core_runtime.Runtime, name string, res *mesh.DynamicConfigResource) error {
-	if err := rt.ResourceManager().Create(rt.AppContext(), res,
-		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
-		store.CreateByApplication(name), store.CreateByKey(name+consts.ConfiguratorRuleSuffix, res_model.DefaultMesh)); err != nil {
-		logger.Warnf("create %s configurator failed with error: %s", name, err.Error())
-		return err
-	}
-	return nil
-}
-
 func DeleteConfiguratorWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 	return func(c *gin.Context) {
 		var name string
@@ -181,20 +159,10 @@ func DeleteConfiguratorWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(fmt.Sprintf("ruleName must end with %s", consts.ConfiguratorRuleSuffix)))
 			return
 		}
-		if err := deleteConfigurator(rt, name, res); err != nil {
+		if err := service.DeleteConfigurator(rt, name, res); err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		}
-		c.JSON(http.StatusOK, model.GenDynamicConfigToResp(http.StatusOK, "success", nil))
-	}
-}
-
-func deleteConfigurator(rt core_runtime.Runtime, name string, res *mesh.DynamicConfigResource) error {
-	if err := rt.ResourceManager().Delete(rt.AppContext(), res,
-		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
-		store.DeleteByApplication(name), store.DeleteByKey(name+consts.ConfiguratorRuleSuffix, res_model.DefaultMesh)); err != nil {
-		logger.Warnf("delete %s configurator failed with error: %s", name, err.Error())
-		return err
+		c.JSON(http.StatusOK, model.NewSuccessResp(""))
 	}
-	return nil
 }
diff --git a/pkg/admin/handler/instance.go b/pkg/admin/handler/instance.go
index f9746722..23086f72 100644
--- a/pkg/admin/handler/instance.go
+++ b/pkg/admin/handler/instance.go
@@ -97,7 +97,7 @@ func InstanceConfigTrafficDisableGET(rt core_runtime.Runtime) gin.HandlerFunc {
 			return
 		}
 
-		res, err := getConditionRule(rt, applicationName)
+		res, err := service.GetConditionRule(rt, applicationName)
 		if err != nil {
 			if core_store.IsResourceNotFound(err) {
 				c.JSON(http.StatusOK, model.NewSuccessResp(resp))
@@ -163,7 +163,7 @@ func InstanceConfigTrafficDisablePUT(rt core_runtime.Runtime) gin.HandlerFunc {
 
 		// get
 		NotExist := false
-		rawRes, err := getConditionRule(rt, applicationName)
+		rawRes, err := service.GetConditionRule(rt, applicationName)
 		var res *mesh_proto.ConditionRouteV3X1
 		if err != nil {
 			if !core_store.IsResourceNotFound(err) {
@@ -192,13 +192,13 @@ func InstanceConfigTrafficDisablePUT(rt core_runtime.Runtime) gin.HandlerFunc {
 		rawRes.Spec = res.ToConditionRoute()
 
 		if NotExist {
-			err = createConditionRule(rt, applicationName, rawRes)
+			err = service.CreateConditionRule(rt, applicationName, rawRes)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
 			}
 		} else {
-			err = updateConditionRule(rt, applicationName, rawRes)
+			err = service.UpdateConditionRule(rt, applicationName, rawRes)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
@@ -244,7 +244,7 @@ func InstanceConfigOperatorLogGET(rt core_runtime.Runtime) gin.HandlerFunc {
 			return
 		}
 
-		res, err := getConfigurator(rt, applicationName)
+		res, err := service.GetConfigurator(rt, applicationName)
 		if err != nil {
 			if core_store.IsResourceNotFound(err) {
 				c.JSON(http.StatusOK, model.NewSuccessResp(resp))
@@ -296,7 +296,7 @@ func InstanceConfigOperatorLogPUT(rt core_runtime.Runtime) gin.HandlerFunc {
 			return
 		}
 
-		res, err := getConfigurator(rt, applicationName)
+		res, err := service.GetConfigurator(rt, applicationName)
 		notExist := false
 		if err != nil {
 			if !core_store.IsResourceNotFound(err) {
@@ -328,13 +328,13 @@ func InstanceConfigOperatorLogPUT(rt core_runtime.Runtime) gin.HandlerFunc {
 		}
 
 		if notExist {
-			err = createConfigurator(rt, applicationName, res)
+			err = service.CreateConfigurator(rt, applicationName, res)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
 			}
 		} else {
-			err = updateConfigurator(rt, applicationName, res)
+			err = service.UpdateConfigurator(rt, applicationName, res)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
diff --git a/pkg/admin/handler/service.go b/pkg/admin/handler/service.go
index 75dbd411..50a3402d 100644
--- a/pkg/admin/handler/service.go
+++ b/pkg/admin/handler/service.go
@@ -135,7 +135,7 @@ func ServiceConfigTimeoutGET(rt core_runtime.Runtime) gin.HandlerFunc {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		}
-		res, err := getConfigurator(rt, param.toInterface())
+		res, err := service.GetConfigurator(rt, param.toInterface())
 		if err != nil {
 			if !core_store.IsResourceNotFound(err) {
 				c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
@@ -178,7 +178,7 @@ func ServiceConfigTimeoutPUT(rt core_runtime.Runtime) gin.HandlerFunc {
 		}
 
 		isExist := true
-		res, err := getConfigurator(rt, param.toInterface())
+		res, err := service.GetConfigurator(rt, param.toInterface())
 		if err != nil {
 			if !core_store.IsResourceNotFound(err) {
 				c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
@@ -204,13 +204,13 @@ func ServiceConfigTimeoutPUT(rt core_runtime.Runtime) gin.HandlerFunc {
 				Parameters:    map[string]string{`timeout`: strconv.Itoa(int(param.Timeout))},
 				XGenerateByCp: true,
 			})
-			err = createConfigurator(rt, param.toInterface(), res)
+			err = service.CreateConfigurator(rt, param.toInterface(), res)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
 			}
 		} else {
-			err = updateConfigurator(rt, param.toInterface(), res)
+			err = service.UpdateConfigurator(rt, param.toInterface(), res)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
@@ -230,7 +230,7 @@ func ServiceConfigRetryGET(rt core_runtime.Runtime) gin.HandlerFunc {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		}
-		res, err := getConfigurator(rt, param.toInterface())
+		res, err := service.GetConfigurator(rt, param.toInterface())
 		if err != nil {
 			if !core_store.IsResourceNotFound(err) {
 				c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
@@ -273,7 +273,7 @@ func ServiceConfigRetryPUT(rt core_runtime.Runtime) gin.HandlerFunc {
 		}
 
 		isExist := true
-		res, err := getConfigurator(rt, param.toInterface())
+		res, err := service.GetConfigurator(rt, param.toInterface())
 		if err != nil {
 			if !core_store.IsResourceNotFound(err) {
 				c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
@@ -297,13 +297,13 @@ func ServiceConfigRetryPUT(rt core_runtime.Runtime) gin.HandlerFunc {
 		})
 
 		if !isExist {
-			err = createConfigurator(rt, param.toInterface(), res)
+			err = service.CreateConfigurator(rt, param.toInterface(), res)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
 			}
 		} else {
-			err = updateConfigurator(rt, param.toInterface(), res)
+			err = service.UpdateConfigurator(rt, param.toInterface(), res)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
@@ -428,7 +428,7 @@ func ServiceConfigArgumentRouteGET(rt core_runtime.Runtime) gin.HandlerFunc {
 			return
 		}
 
-		rawRes, err := getConditionRule(rt, param.toInterface())
+		rawRes, err := service.GetConditionRule(rt, param.toInterface())
 		if err != nil {
 			if !core_store.IsResourceNotFound(err) {
 				c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
@@ -467,7 +467,7 @@ func ServiceConfigArgumentRoutePUT(rt core_runtime.Runtime) gin.HandlerFunc {
 		}
 
 		isExist := true
-		rawRes, err := getConditionRule(rt, param.toInterface())
+		rawRes, err := service.GetConditionRule(rt, param.toInterface())
 		if err != nil {
 			if !core_store.IsResourceNotFound(err) {
 				c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
@@ -497,13 +497,13 @@ func ServiceConfigArgumentRoutePUT(rt core_runtime.Runtime) gin.HandlerFunc {
 		rawRes.Spec = res.ToConditionRoute()
 
 		if isExist {
-			err = updateConditionRule(rt, param.toInterface(), rawRes)
+			err = service.UpdateConditionRule(rt, param.toInterface(), rawRes)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
 			}
 		} else {
-			err = createConditionRule(rt, param.toInterface(), rawRes)
+			err = service.CreateConditionRule(rt, param.toInterface(), rawRes)
 			if err != nil {
 				c.JSON(http.StatusInternalServerError, model.NewErrorResp(err.Error()))
 				return
diff --git a/pkg/admin/handler/traffic_tag_rule.go b/pkg/admin/handler/tag_rule.go
similarity index 58%
rename from pkg/admin/handler/traffic_tag_rule.go
rename to pkg/admin/handler/tag_rule.go
index d01ad6e7..8a1e5432 100644
--- a/pkg/admin/handler/traffic_tag_rule.go
+++ b/pkg/admin/handler/tag_rule.go
@@ -19,7 +19,10 @@ package handler
 
 import (
 	"fmt"
+	"github.com/apache/dubbo-kubernetes/pkg/admin/service"
+	"github.com/apache/dubbo-kubernetes/pkg/core/resources/store"
 	"net/http"
+	"strconv"
 	"strings"
 )
 
@@ -31,37 +34,43 @@ import (
 	mesh_proto "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1"
 	"github.com/apache/dubbo-kubernetes/pkg/admin/model"
 	"github.com/apache/dubbo-kubernetes/pkg/core/consts"
-	"github.com/apache/dubbo-kubernetes/pkg/core/logger"
 	"github.com/apache/dubbo-kubernetes/pkg/core/resources/apis/mesh"
-	res_model "github.com/apache/dubbo-kubernetes/pkg/core/resources/model"
-	"github.com/apache/dubbo-kubernetes/pkg/core/resources/store"
 	core_runtime "github.com/apache/dubbo-kubernetes/pkg/core/runtime"
 )
 
 func TagRuleSearch(rt core_runtime.Runtime) gin.HandlerFunc {
 	return func(c *gin.Context) {
-		resList := &mesh.TagRouteResourceList{
-			Items: make([]*mesh.TagRouteResource, 0),
-		}
-		if err := rt.ResourceManager().List(rt.AppContext(), resList); err != nil {
+		req := model.NewSearchReq()
+		if err := c.ShouldBindQuery(req); err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		}
-		resp := model.TagRuleSearchResp{
-			Code:    200,
-			Message: "success",
-			Data:    make([]model.TagRuleSearchResp_Datum, 0, len(resList.Items)),
+		resList := &mesh.TagRouteResourceList{}
+		if req.Keywords == "" {
+			if err := rt.ResourceManager().List(rt.AppContext(), resList, store.ListByPage(req.PageSize, strconv.Itoa(req.PageOffset))); err != nil {
+				c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
+				return
+			}
+		} else {
+			if err := rt.ResourceManager().List(rt.AppContext(), resList, store.ListByNameContains(req.Keywords), store.ListByPage(req.PageSize, strconv.Itoa(req.PageOffset))); err != nil {
+				c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
+				return
+			}
 		}
+		var respList []model.TagRuleSearchResp
 		for _, item := range resList.Items {
 			time := item.Meta.GetCreationTime().String()
 			name := item.Meta.GetName()
-			resp.Data = append(resp.Data, model.TagRuleSearchResp_Datum{
+			respList = append(respList, model.TagRuleSearchResp{
 				CreateTime: &time,
 				Enabled:    &item.Spec.Enabled,
 				RuleName:   &name,
 			})
 		}
-		c.JSON(http.StatusOK, resp)
+		result := model.NewSearchPaginationResult()
+		result.List = respList
+		result.PageInfo = &resList.Pagination
+		c.JSON(http.StatusOK, model.NewSuccessResp(result))
 	}
 }
 
@@ -75,27 +84,15 @@ func GetTagRuleWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(fmt.Sprintf("ruleName must end with %s", consts.TagRuleSuffix)))
 			return
 		}
-		if res, err := getTagRule(rt, name); err != nil {
+		if res, err := service.GetTagRule(rt, name); err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		} else {
-			c.JSON(http.StatusOK, model.GenTagRouteResp(http.StatusOK, "success", res.Spec))
+			c.JSON(http.StatusOK, model.GenTagRouteResp(res.Spec))
 		}
 	}
 }
 
-func getTagRule(rt core_runtime.Runtime, name string) (*mesh.TagRouteResource, error) {
-	res := &mesh.TagRouteResource{Spec: &mesh_proto.TagRoute{}}
-	err := rt.ResourceManager().Get(rt.AppContext(), res,
-		// here `name` may be service name or app name, set *ByApplication(`name`) is ok.
-		store.GetByApplication(name), store.GetByKey(name+consts.TagRuleSuffix, res_model.DefaultMesh))
-	if err != nil {
-		logger.Warnf("get tag rule %s error: %v", name, err)
-		return nil, err
-	}
-	return res, nil
-}
-
 func PutTagRuleWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 	return func(c *gin.Context) {
 		var name string
@@ -115,26 +112,15 @@ func PutTagRuleWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		}
-		if err = updateTagRule(rt, name, res); err != nil {
+		if err = service.UpdateTagRule(rt, name, res); err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		} else {
-			c.JSON(http.StatusOK, model.GenTagRouteResp(http.StatusOK, "success", nil))
+			c.JSON(http.StatusOK, model.GenTagRouteResp(res.Spec))
 		}
 	}
 }
 
-func updateTagRule(rt core_runtime.Runtime, name string, res *mesh.TagRouteResource) error {
-	err := rt.ResourceManager().Update(rt.AppContext(), res,
-		// here `name` may be service name or app name, set *ByApplication(`name`) is ok.
-		store.UpdateByApplication(name), store.UpdateByKey(name+consts.TagRuleSuffix, res_model.DefaultMesh))
-	if err != nil {
-		logger.Warnf("update tag rule %s error: %v", name, err)
-		return err
-	}
-	return nil
-}
-
 func PostTagRuleWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 	return func(c *gin.Context) {
 		var name string
@@ -154,26 +140,15 @@ func PostTagRuleWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		}
-		if err = createTagRule(rt, name, res); err != nil {
+		if err = service.CreateTagRule(rt, name, res); err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		} else {
-			c.JSON(http.StatusCreated, model.GenTagRouteResp(http.StatusCreated, "success", nil))
+			c.JSON(http.StatusOK, model.GenTagRouteResp(res.Spec))
 		}
 	}
 }
 
-func createTagRule(rt core_runtime.Runtime, name string, res *mesh.TagRouteResource) error {
-	err := rt.ResourceManager().Create(rt.AppContext(), res,
-		// here `name` may be service name or app name, set *ByApplication(`name`) is ok.
-		store.CreateByApplication(name), store.CreateByKey(name+consts.TagRuleSuffix, res_model.DefaultMesh))
-	if err != nil {
-		logger.Warnf("create tag rule %s error: %v", name, err)
-		return err
-	}
-	return nil
-}
-
 func DeleteTagRuleWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 	return func(c *gin.Context) {
 		var name string
@@ -185,21 +160,10 @@ func DeleteTagRuleWithRuleName(rt core_runtime.Runtime) gin.HandlerFunc {
 			return
 		}
 		res := &mesh.TagRouteResource{Spec: &mesh_proto.TagRoute{}}
-		if err := deleteTagRule(rt, name, res); err != nil {
+		if err := service.DeleteTagRule(rt, name, res); err != nil {
 			c.JSON(http.StatusBadRequest, model.NewErrorResp(err.Error()))
 			return
 		}
-		c.JSON(http.StatusNoContent, model.GenTagRouteResp(http.StatusNoContent, "success", nil))
-	}
-}
-
-func deleteTagRule(rt core_runtime.Runtime, name string, res *mesh.TagRouteResource) error {
-	err := rt.ResourceManager().Delete(rt.AppContext(), res,
-		// here `name` may be service name or app name, set *ByApplication(`name`) is ok.
-		store.DeleteByApplication(name), store.DeleteByKey(name+consts.TagRuleSuffix, res_model.DefaultMesh))
-	if err != nil {
-		logger.Warnf("delete tag rule %s error: %v", name, err)
-		return err
+		c.JSON(http.StatusOK, model.NewSuccessResp(""))
 	}
-	return nil
 }
diff --git a/pkg/admin/model/traffic_condition_rule.go b/pkg/admin/model/condition_rule.go
similarity index 83%
rename from pkg/admin/model/traffic_condition_rule.go
rename to pkg/admin/model/condition_rule.go
index 9b789988..9b84c89c 100644
--- a/pkg/admin/model/traffic_condition_rule.go
+++ b/pkg/admin/model/condition_rule.go
@@ -18,6 +18,7 @@
 package model
 
 import (
+	"net/http"
 	"strings"
 )
 
@@ -26,13 +27,18 @@ import (
 	"github.com/apache/dubbo-kubernetes/pkg/core/consts"
 )
 
-type ConditionRuleSearchResp struct {
-	Code    int64                          `json:"code"`
-	Data    []ConditionRuleSearchResp_Data `json:"data"`
-	Message string                         `json:"message"`
+type SearchConditionRuleReq struct {
+	Keywords string `json:"keywords"`
+	PageReq
+}
+
+func NewSearchConditionRuleReq() *SearchConditionRuleReq {
+	return &SearchConditionRuleReq{
+		PageReq: PageReq{PageSize: 15},
+	}
 }
 
-type ConditionRuleSearchResp_Data struct {
+type ConditionRuleSearchResp struct {
 	CreateTime string `json:"createTime"`
 	Enabled    bool   `json:"enabled"`
 	RuleName   string `json:"ruleName"`
@@ -40,12 +46,6 @@ type ConditionRuleSearchResp_Data struct {
 }
 
 type ConditionRuleResp struct {
-	Code    int         `json:"code"`
-	Message string      `json:"message"`
-	Data    interface{} `json:"data"`
-}
-
-type RespConditionRuleData struct {
 	Conditions    []string `json:"conditions"`
 	ConfigVersion string   `json:"configVersion"`
 	Enabled       bool     `json:"enabled"`
@@ -203,27 +203,23 @@ func matchValueToDestinationCondition(val string) []DestinationCondition {
 	return res
 }
 
-func GenConditionRuleToResp(code int, message string, data *mesh_proto.ConditionRoute) *ConditionRuleResp {
+func GenConditionRuleToResp(data *mesh_proto.ConditionRoute) *CommonResp {
 	if data == nil {
-		return &ConditionRuleResp{
-			Code:    code,
-			Message: message,
-			Data:    map[string]string{},
+		return &CommonResp{
+			Code: http.StatusNotFound,
+			Msg:  "not found",
+			Data: map[string]string{},
 		}
 	}
 	if pb := data.ToConditionRouteV3(); pb != nil {
-		return &ConditionRuleResp{
-			Code:    code,
-			Message: message,
-			Data: RespConditionRuleData{
-				Conditions:    pb.Conditions,
-				ConfigVersion: pb.ConfigVersion,
-				Enabled:       pb.Enabled,
-				Key:           pb.Key,
-				Runtime:       pb.Runtime,
-				Scope:         pb.Scope,
-			},
-		}
+		return NewSuccessResp(ConditionRuleResp{
+			Conditions:    pb.Conditions,
+			ConfigVersion: pb.ConfigVersion,
+			Enabled:       pb.Enabled,
+			Key:           pb.Key,
+			Runtime:       pb.Runtime,
+			Scope:         pb.Scope,
+		})
 	} else if pb := data.ToConditionRouteV3x1(); pb != nil {
 		res := ConditionRuleV3X1{
 			Conditions:    make([]Condition, 0, len(pb.Conditions)),
@@ -236,27 +232,23 @@ func GenConditionRuleToResp(code int, message string, data *mesh_proto.Condition
 		}
 		for _, condition := range pb.Conditions {
 			resCondition := Condition{
-				From: Condition_From{Match: condition.From.Match},
-				To:   make([]Condition_To, 0, len(condition.To)),
+				From: ConditionFrom{Match: condition.From.Match},
+				To:   make([]ConditionTo, 0, len(condition.To)),
 			}
 			for _, to := range condition.To {
-				resCondition.To = append(resCondition.To, Condition_To{
+				resCondition.To = append(resCondition.To, ConditionTo{
 					Match:  to.Match,
 					Weight: to.Weight,
 				})
 			}
 			res.Conditions = append(res.Conditions, resCondition)
 		}
-		return &ConditionRuleResp{
-			Code:    code,
-			Message: message,
-			Data:    res,
-		}
+		return NewSuccessResp(res)
 	} else {
-		return &ConditionRuleResp{
-			Code:    code,
-			Message: message,
-			Data:    data,
+		return &CommonResp{
+			Code: http.StatusInternalServerError,
+			Msg:  "invalid condition rule",
+			Data: data,
 		}
 	}
 }
@@ -277,15 +269,15 @@ type AffinityAware struct {
 }
 
 type Condition struct {
-	From Condition_From `json:"from"`
-	To   []Condition_To `json:"to"`
+	From ConditionFrom `json:"from"`
+	To   []ConditionTo `json:"to"`
 }
 
-type Condition_From struct {
+type ConditionFrom struct {
 	Match string `json:"match"`
 }
 
-type Condition_To struct {
+type ConditionTo struct {
 	Match  string `json:"match"`
 	Weight int32  `json:"weight"`
 }
diff --git a/pkg/admin/model/traffic_configurator.go b/pkg/admin/model/configurator_rule.go
similarity index 92%
rename from pkg/admin/model/traffic_configurator.go
rename to pkg/admin/model/configurator_rule.go
index 94930cf7..cab55ca9 100644
--- a/pkg/admin/model/traffic_configurator.go
+++ b/pkg/admin/model/configurator_rule.go
@@ -19,27 +19,30 @@ package model
 
 import (
 	mesh_proto "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1"
+	"net/http"
 )
 
-type ConfiguratorSearchResp struct {
-	Code    int                           `json:"code"`
-	Message string                        `json:"message"`
-	Data    []ConfiguratorSearchResp_Data `json:"data"`
+type SearchConfiguratorReq struct {
+	Keywords string `json:"keywords"`
+	PageReq
+}
+
+func NewSearchConfiguratorReq() *SearchConfiguratorReq {
+	return &SearchConfiguratorReq{
+		PageReq: PageReq{
+			PageSize:   15,
+			PageOffset: 0,
+		},
+	}
 }
 
-type ConfiguratorSearchResp_Data struct {
+type ConfiguratorSearchResp struct {
 	RuleName   string `json:"ruleName"`
 	Scope      string `json:"scope"`
 	CreateTime string `json:"createTime"`
 	Enabled    bool   `json:"enabled"`
 }
 
-type ConfiguratorResp struct {
-	Code    int              `json:"code"`
-	Message string           `json:"message"`
-	Data    RespConfigurator `json:"data"`
-}
-
 type RespConfigurator struct {
 	Configs       []ConfigItem `json:"configs"`
 	ConfigVersion string       `json:"configVersion"`
@@ -93,7 +96,7 @@ type RespAddressMatch struct {
 	Wildcard *string `json:"wildcard,omitempty"`
 }
 
-func GenDynamicConfigToResp(code int, message string, pb *mesh_proto.DynamicConfig) (res *ConfiguratorResp) {
+func GenDynamicConfigToResp(pb *mesh_proto.DynamicConfig) (res *CommonResp) {
 	cfg := RespConfigurator{}
 	if pb != nil {
 		cfg.ConfigVersion = pb.ConfigVersion
@@ -101,13 +104,12 @@ func GenDynamicConfigToResp(code int, message string, pb *mesh_proto.DynamicConf
 		cfg.Scope = pb.Scope
 		cfg.Enabled = pb.Enabled
 		cfg.Configs = overrideConfigToRespConfigItem(pb.Configs)
+		return NewSuccessResp(cfg)
 	}
-	res = &ConfiguratorResp{
-		Code:    code,
-		Message: message,
-		Data:    cfg,
+	return &CommonResp{
+		Code: http.StatusNotFound,
+		Msg:  "configurator not found",
 	}
-	return
 }
 
 func overrideConfigToRespConfigItem(OverrideConfigs []*mesh_proto.OverrideConfig) []ConfigItem {
diff --git a/pkg/admin/model/traffic_tag_rule.go b/pkg/admin/model/tag_rule.go
similarity index 70%
rename from pkg/admin/model/traffic_tag_rule.go
rename to pkg/admin/model/tag_rule.go
index a5de5cd3..edca14c8 100644
--- a/pkg/admin/model/traffic_tag_rule.go
+++ b/pkg/admin/model/tag_rule.go
@@ -20,27 +20,16 @@ package model
 import (
 	mesh_proto "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1"
 	"github.com/apache/dubbo-kubernetes/pkg/core/consts"
+	"net/http"
 )
 
 type TagRuleSearchResp struct {
-	Code    int64                     `json:"code"`
-	Data    []TagRuleSearchResp_Datum `json:"data"`
-	Message string                    `json:"message"`
-}
-
-type TagRuleSearchResp_Datum struct {
 	CreateTime *string `json:"createTime,omitempty"`
 	Enabled    *bool   `json:"enabled,omitempty"`
 	RuleName   *string `json:"ruleName,omitempty"`
 }
 
 type TagRuleResp struct {
-	Code    int          `json:"code"`
-	Message string       `json:"message"`
-	Data    *RespTagData `json:"data"`
-}
-
-type RespTagData struct {
 	ConfigVersion string           `json:"configVersion"`
 	Enabled       bool             `json:"enabled"`
 	Key           string           `json:"key"`
@@ -55,26 +44,22 @@ type RespTagElement struct {
 	Name      string       `json:"name"`
 }
 
-func GenTagRouteResp(code int, message string, pb *mesh_proto.TagRoute) *TagRuleResp {
+func GenTagRouteResp(pb *mesh_proto.TagRoute) *CommonResp {
 	if pb == nil {
-		return &TagRuleResp{
-			Code:    code,
-			Message: message,
-			Data:    &RespTagData{},
+		return &CommonResp{
+			Code: http.StatusNotFound,
+			Msg:  "tag rule not found",
+			Data: "",
 		}
 	} else {
-		return &TagRuleResp{
-			Code:    code,
-			Message: message,
-			Data: &RespTagData{
-				ConfigVersion: pb.ConfigVersion,
-				Enabled:       pb.Enabled,
-				Key:           pb.Key,
-				Runtime:       pb.Runtime,
-				Scope:         consts.ScopeApplication,
-				Tags:          tagToRespTagElement(pb.Tags),
-			},
-		}
+		return NewSuccessResp(TagRuleResp{
+			ConfigVersion: pb.ConfigVersion,
+			Enabled:       pb.Enabled,
+			Key:           pb.Key,
+			Runtime:       pb.Runtime,
+			Scope:         consts.ScopeApplication,
+			Tags:          tagToRespTagElement(pb.Tags),
+		})
 	}
 }
 
diff --git a/pkg/admin/service/condition_rule.go b/pkg/admin/service/condition_rule.go
new file mode 100644
index 00000000..3693dd12
--- /dev/null
+++ b/pkg/admin/service/condition_rule.go
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 service
+
+import (
+	mesh_proto "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1"
+	"github.com/apache/dubbo-kubernetes/pkg/admin/model"
+	"github.com/apache/dubbo-kubernetes/pkg/core/consts"
+	"github.com/apache/dubbo-kubernetes/pkg/core/logger"
+	"github.com/apache/dubbo-kubernetes/pkg/core/resources/apis/mesh"
+	res_model "github.com/apache/dubbo-kubernetes/pkg/core/resources/model"
+	"github.com/apache/dubbo-kubernetes/pkg/core/resources/store"
+	core_runtime "github.com/apache/dubbo-kubernetes/pkg/core/runtime"
+	"strconv"
+)
+
+func SearchConditionRules(rt core_runtime.Runtime, req *model.SearchConditionRuleReq) (*model.SearchPaginationResult, error) {
+	ruleList := &mesh.ConditionRouteResourceList{}
+	if req.Keywords == "" {
+		if err := rt.ResourceManager().List(rt.AppContext(), ruleList, store.ListByPage(req.PageSize, strconv.Itoa(req.PageOffset))); err != nil {
+			return nil, err
+		}
+	} else {
+		if err := rt.ResourceManager().List(rt.AppContext(), ruleList, store.ListByNameContains(req.Keywords), store.ListByPage(req.PageSize, strconv.Itoa(req.PageOffset))); err != nil {
+			return nil, err
+		}
+	}
+
+	var respList []model.ConditionRuleSearchResp
+	for _, item := range ruleList.Items {
+		if v3 := item.Spec.ToConditionRouteV3(); v3 != nil {
+			respList = append(respList, model.ConditionRuleSearchResp{
+				RuleName:   item.Meta.GetName(),
+				Scope:      v3.GetScope(),
+				CreateTime: item.Meta.GetCreationTime().String(),
+				Enabled:    v3.GetEnabled(),
+			})
+		} else if v3x1 := item.Spec.ToConditionRouteV3x1(); v3x1 != nil {
+			respList = append(respList, model.ConditionRuleSearchResp{
+				RuleName:   item.Meta.GetName(),
+				Scope:      v3x1.GetScope(),
+				CreateTime: item.Meta.GetCreationTime().String(),
+				Enabled:    v3x1.GetEnabled(),
+			})
+		} else {
+			logger.Errorf("Invalid condition route %v", item)
+		}
+	}
+	result := model.NewSearchPaginationResult()
+	result.List = respList
+	result.PageInfo = &ruleList.Pagination
+	return result, nil
+}
+
+func GetConditionRule(rt core_runtime.Runtime, name string) (*mesh.ConditionRouteResource, error) {
+	res := &mesh.ConditionRouteResource{Spec: &mesh_proto.ConditionRoute{}}
+	if err := rt.ResourceManager().Get(rt.AppContext(), res,
+		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
+		store.GetByApplication(name), store.GetByKey(name+consts.ConditionRuleSuffix, res_model.DefaultMesh)); err != nil {
+		logger.Warnf("get %s condition failed with error: %s", name, err.Error())
+		return nil, err
+	}
+	return res, nil
+}
+
+func UpdateConditionRule(rt core_runtime.Runtime, name string, res *mesh.ConditionRouteResource) error {
+	if err := rt.ResourceManager().Update(rt.AppContext(), res,
+		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
+		store.UpdateByApplication(name), store.UpdateByKey(name+consts.ConditionRuleSuffix, res_model.DefaultMesh)); err != nil {
+		logger.Warnf("update %s condition failed with error: %s", name, err.Error())
+		return err
+	}
+	return nil
+}
+
+func CreateConditionRule(rt core_runtime.Runtime, name string, res *mesh.ConditionRouteResource) error {
+	if err := rt.ResourceManager().Create(rt.AppContext(), res,
+		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
+		store.CreateByApplication(name), store.CreateByKey(name+consts.ConditionRuleSuffix, res_model.DefaultMesh)); err != nil {
+		logger.Warnf("create %s condition failed with error: %s", name, err.Error())
+		return err
+	}
+	return nil
+}
+
+func DeleteConditionRule(rt core_runtime.Runtime, name string, res *mesh.ConditionRouteResource) error {
+	if err := rt.ResourceManager().Delete(rt.AppContext(), res,
+		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
+		store.DeleteByApplication(name), store.DeleteByKey(name+consts.ConditionRuleSuffix, res_model.DefaultMesh)); err != nil {
+		logger.Warnf("delete %s condition failed with error: %s", name, err.Error())
+		return err
+	}
+	return nil
+}
diff --git a/pkg/admin/service/configurator_rule.go b/pkg/admin/service/configurator_rule.go
new file mode 100644
index 00000000..2236c317
--- /dev/null
+++ b/pkg/admin/service/configurator_rule.go
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 service
+
+import (
+	mesh_proto "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1"
+	"github.com/apache/dubbo-kubernetes/pkg/core/consts"
+	"github.com/apache/dubbo-kubernetes/pkg/core/logger"
+	"github.com/apache/dubbo-kubernetes/pkg/core/resources/apis/mesh"
+	res_model "github.com/apache/dubbo-kubernetes/pkg/core/resources/model"
+	"github.com/apache/dubbo-kubernetes/pkg/core/resources/store"
+	core_runtime "github.com/apache/dubbo-kubernetes/pkg/core/runtime"
+)
+
+func GetConfigurator(rt core_runtime.Runtime, name string) (*mesh.DynamicConfigResource, error) {
+	res := &mesh.DynamicConfigResource{Spec: &mesh_proto.DynamicConfig{}}
+	if err := rt.ResourceManager().Get(rt.AppContext(), res,
+		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
+		store.GetByApplication(name), store.GetByKey(name+consts.ConfiguratorRuleSuffix, res_model.DefaultMesh)); err != nil {
+		logger.Warnf("get %s configurator failed with error: %s", name, err.Error())
+		return nil, err
+	}
+	return res, nil
+}
+
+func UpdateConfigurator(rt core_runtime.Runtime, name string, res *mesh.DynamicConfigResource) error {
+	if err := rt.ResourceManager().Update(rt.AppContext(), res,
+		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
+		store.UpdateByApplication(name), store.UpdateByKey(name+consts.ConfiguratorRuleSuffix, res_model.DefaultMesh)); err != nil {
+		logger.Warnf("update %s configurator failed with error: %s", name, err.Error())
+		return err
+	}
+	return nil
+}
+
+func CreateConfigurator(rt core_runtime.Runtime, name string, res *mesh.DynamicConfigResource) error {
+	if err := rt.ResourceManager().Create(rt.AppContext(), res,
+		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
+		store.CreateByApplication(name), store.CreateByKey(name+consts.ConfiguratorRuleSuffix, res_model.DefaultMesh)); err != nil {
+		logger.Warnf("create %s configurator failed with error: %s", name, err.Error())
+		return err
+	}
+	return nil
+}
+
+func DeleteConfigurator(rt core_runtime.Runtime, name string, res *mesh.DynamicConfigResource) error {
+	if err := rt.ResourceManager().Delete(rt.AppContext(), res,
+		// here `name` may be service-name or app-name, set *ByApplication(`name`) is ok.
+		store.DeleteByApplication(name), store.DeleteByKey(name+consts.ConfiguratorRuleSuffix, res_model.DefaultMesh)); err != nil {
+		logger.Warnf("delete %s configurator failed with error: %s", name, err.Error())
+		return err
+	}
+	return nil
+}
diff --git a/pkg/admin/service/tag_rule.go b/pkg/admin/service/tag_rule.go
new file mode 100644
index 00000000..6ce7635b
--- /dev/null
+++ b/pkg/admin/service/tag_rule.go
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 service
+
+import (
+	mesh_proto "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1"
+	"github.com/apache/dubbo-kubernetes/pkg/core/consts"
+	"github.com/apache/dubbo-kubernetes/pkg/core/logger"
+	"github.com/apache/dubbo-kubernetes/pkg/core/resources/apis/mesh"
+	res_model "github.com/apache/dubbo-kubernetes/pkg/core/resources/model"
+	"github.com/apache/dubbo-kubernetes/pkg/core/resources/store"
+	core_runtime "github.com/apache/dubbo-kubernetes/pkg/core/runtime"
+)
+
+func GetTagRule(rt core_runtime.Runtime, name string) (*mesh.TagRouteResource, error) {
+	res := &mesh.TagRouteResource{Spec: &mesh_proto.TagRoute{}}
+	err := rt.ResourceManager().Get(rt.AppContext(), res,
+		// here `name` may be service name or app name, set *ByApplication(`name`) is ok.
+		store.GetByApplication(name), store.GetByKey(name+consts.TagRuleSuffix, res_model.DefaultMesh))
+	if err != nil {
+		logger.Warnf("get tag rule %s error: %v", name, err)
+		return nil, err
+	}
+	return res, nil
+}
+
+func UpdateTagRule(rt core_runtime.Runtime, name string, res *mesh.TagRouteResource) error {
+	err := rt.ResourceManager().Update(rt.AppContext(), res,
+		// here `name` may be service name or app name, set *ByApplication(`name`) is ok.
+		store.UpdateByApplication(name), store.UpdateByKey(name+consts.TagRuleSuffix, res_model.DefaultMesh))
+	if err != nil {
+		logger.Warnf("update tag rule %s error: %v", name, err)
+		return err
+	}
+	return nil
+}
+
+func CreateTagRule(rt core_runtime.Runtime, name string, res *mesh.TagRouteResource) error {
+	err := rt.ResourceManager().Create(rt.AppContext(), res,
+		// here `name` may be service name or app name, set *ByApplication(`name`) is ok.
+		store.CreateByApplication(name), store.CreateByKey(name+consts.TagRuleSuffix, res_model.DefaultMesh))
+	if err != nil {
+		logger.Warnf("create tag rule %s error: %v", name, err)
+		return err
+	}
+	return nil
+}
+
+func DeleteTagRule(rt core_runtime.Runtime, name string, res *mesh.TagRouteResource) error {
+	err := rt.ResourceManager().Delete(rt.AppContext(), res,
+		// here `name` may be service name or app name, set *ByApplication(`name`) is ok.
+		store.DeleteByApplication(name), store.DeleteByKey(name+consts.TagRuleSuffix, res_model.DefaultMesh))
+	if err != nil {
+		logger.Warnf("delete tag rule %s error: %v", name, err)
+		return err
+	}
+	return nil
+}