You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by as...@apache.org on 2021/08/25 11:48:11 UTC

[incubator-shenyu] branch master updated: [type: refactor] refactor integration test for waf plugin (#1975)

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

asxing pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new 51487bf  [type: refactor] refactor integration test for waf plugin (#1975)
51487bf is described below

commit 51487bfd956866dae5e264c2c78a4a93af3d0389
Author: xiaoyu <xi...@apache.org>
AuthorDate: Wed Aug 25 19:48:02 2021 +0800

    [type: refactor] refactor integration test for waf plugin (#1975)
    
    * [type: refactor] refactor integration test for waf plugin
    
    * [type: refactor] refactor integration test for waf plugin
    
    * [type: refactor] refactor integration test for waf plugin
    
    * [type: refactor] refactor integration test for waf plugin
---
 .../integratedtest/common/helper/HttpHelper.java   |   5 +-
 .../src/main/resources/admin-config/schema.sql     |  14 +-
 .../http/combination/AbstractPluginDataInit.java   | 104 ++++++++++
 .../test/http/combination/WafPluginTest.java       |  61 +++++-
 .../shenyu/plugin/base/cache/BaseDataCache.java    |  59 ++++--
 .../shenyu/web/controller/PluginController.java    | 221 +++++++++++++++++++++
 6 files changed, 435 insertions(+), 29 deletions(-)

diff --git a/shenyu-integrated-test/shenyu-integrated-test-common/src/main/java/org/apache/shenyu/integratedtest/common/helper/HttpHelper.java b/shenyu-integrated-test/shenyu-integrated-test-common/src/main/java/org/apache/shenyu/integratedtest/common/helper/HttpHelper.java
index ca59a02..efde273 100644
--- a/shenyu-integrated-test/shenyu-integrated-test-common/src/main/java/org/apache/shenyu/integratedtest/common/helper/HttpHelper.java
+++ b/shenyu-integrated-test/shenyu-integrated-test-common/src/main/java/org/apache/shenyu/integratedtest/common/helper/HttpHelper.java
@@ -30,6 +30,7 @@ import org.springframework.util.CollectionUtils;
 import java.io.IOException;
 import java.lang.reflect.Type;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * The type Http helper.
@@ -74,7 +75,7 @@ public class HttpHelper {
                 .post(RequestBody.create(GSON.toJson(req), JSON))
                 .build();
         Response response = client.newCall(request).execute();
-        String respBody = response.body().string();
+        String respBody = Objects.requireNonNull(response.body()).string();
         LOG.info("postGateway({}) resp({})", path, respBody);
         return GSON.fromJson(respBody, respType);
     }
@@ -109,7 +110,7 @@ public class HttpHelper {
         }
         Request request = requestBuilder.build();
         Response response = client.newCall(request).execute();
-        String respBody = response.body().string();
+        String respBody = Objects.requireNonNull(response.body()).string();
         LOG.info("getFromGateway({}) resp({})", path, respBody);
         return GSON.fromJson(respBody, type);
     }
diff --git a/shenyu-integrated-test/shenyu-integrated-test-http/src/main/resources/admin-config/schema.sql b/shenyu-integrated-test/shenyu-integrated-test-http/src/main/resources/admin-config/schema.sql
index 93e27f0..054f60d 100644
--- a/shenyu-integrated-test/shenyu-integrated-test-http/src/main/resources/admin-config/schema.sql
+++ b/shenyu-integrated-test/shenyu-integrated-test-http/src/main/resources/admin-config/schema.sql
@@ -37,13 +37,13 @@ INSERT IGNORE INTO auth_param(id,auth_id,app_name,date_created, date_updated) VA
 INSERT IGNORE INTO auth_path(id,auth_id,app_name,path,enabled,date_created, date_updated) VALUES ('1412255231079411712','1412239238157819904','http-sign','/http/test/path/456',1,'2021-07-06 13:09:3','2021-07-06 13:09:33');
 
 /** prepare waf **/
-UPDATE plugin SET enabled = 1 WHERE id = '2';
-INSERT IGNORE INTO selector (id, plugin_id, name, match_mode, type, sort, handle, enabled, loged, continued, date_created, date_updated) VALUES ('1422826261990641664', '2', '/http/test/waf', 0, 1, 1, null, 1, 1, 1,'2021-08-04 13:09:32','2021-08-04 13:09:32');
-INSERT IGNORE INTO selector_condition (id, selector_id, param_type, operator, param_name, param_value, date_created, date_updated) VALUES ('1422826261999030272', '1422826261990641664', 'uri', 'match', '/', '/http/test/waf/**','2021-08-04 13:09:32','2021-08-04 13:09:32');
-INSERT IGNORE INTO rule (id, selector_id, match_mode, name, enabled, loged, sort, handle, date_created, date_updated) VALUES ('1422826330114527232', '1422826261990641664', 0, '/http/test/waf/pass', 1, 1, 1, '{"permission":"allow","statusCode":"200"}', '2021-08-04 13:09:32','2021-08-04 13:09:32');
-INSERT IGNORE INTO rule (id, selector_id, match_mode, name, enabled, loged, sort, handle, date_created, date_updated) VALUES ('1422826385177350144', '1422826261990641664', 0, '/http/test/waf/deny', 1, 1, 1, '{"permission":"reject","statusCode":"403"}', '2021-08-04 13:09:32','2021-08-04 13:09:32');
-INSERT IGNORE INTO rule_condition (id, rule_id, param_type, operator, param_name, param_value, date_created, date_updated) VALUES ('1422826330122915840', '1422826330114527232', 'uri', '=', '/', '/http/test/waf/pass','2021-08-04 13:09:32','2021-08-04 13:09:32');
-INSERT IGNORE INTO rule_condition (id, rule_id, param_type, operator, param_name, param_value, date_created, date_updated) VALUES ('1422826385185738752', '1422826385177350144', 'uri', '=', '/', '/http/test/waf/deny','2021-08-04 13:09:32','2021-08-04 13:09:32');
+-- UPDATE plugin SET enabled = 1 WHERE id = '2';
+-- INSERT IGNORE INTO selector (id, plugin_id, name, match_mode, type, sort, handle, enabled, loged, continued, date_created, date_updated) VALUES ('1422826261990641664', '2', '/http/test/waf', 0, 1, 1, null, 1, 1, 1,'2021-08-04 13:09:32','2021-08-04 13:09:32');
+-- INSERT IGNORE INTO selector_condition (id, selector_id, param_type, operator, param_name, param_value, date_created, date_updated) VALUES ('1422826261999030272', '1422826261990641664', 'uri', 'match', '/', '/http/test/waf/**','2021-08-04 13:09:32','2021-08-04 13:09:32');
+-- INSERT IGNORE INTO rule (id, selector_id, match_mode, name, enabled, loged, sort, handle, date_created, date_updated) VALUES ('1422826330114527232', '1422826261990641664', 0, '/http/test/waf/pass', 1, 1, 1, '{"permission":"allow","statusCode":"200"}', '2021-08-04 13:09:32','2021-08-04 13:09:32');
+-- INSERT IGNORE INTO rule (id, selector_id, match_mode, name, enabled, loged, sort, handle, date_created, date_updated) VALUES ('1422826385177350144', '1422826261990641664', 0, '/http/test/waf/deny', 1, 1, 1, '{"permission":"reject","statusCode":"403"}', '2021-08-04 13:09:32','2021-08-04 13:09:32');
+-- INSERT IGNORE INTO rule_condition (id, rule_id, param_type, operator, param_name, param_value, date_created, date_updated) VALUES ('1422826330122915840', '1422826330114527232', 'uri', '=', '/', '/http/test/waf/pass','2021-08-04 13:09:32','2021-08-04 13:09:32');
+-- INSERT IGNORE INTO rule_condition (id, rule_id, param_type, operator, param_name, param_value, date_created, date_updated) VALUES ('1422826385185738752', '1422826385177350144', 'uri', '=', '/', '/http/test/waf/deny','2021-08-04 13:09:32','2021-08-04 13:09:32');
 
 /** prepare redirect **/
 UPDATE plugin SET enabled = 1 WHERE id = '16';
diff --git a/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/AbstractPluginDataInit.java b/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/AbstractPluginDataInit.java
new file mode 100644
index 0000000..dd6042d
--- /dev/null
+++ b/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/AbstractPluginDataInit.java
@@ -0,0 +1,104 @@
+/*
+ * 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 org.apache.shenyu.integrated.test.http.combination;
+
+import org.apache.shenyu.common.dto.ConditionData;
+import org.apache.shenyu.common.dto.PluginData;
+import org.apache.shenyu.integratedtest.common.AbstractTest;
+import org.apache.shenyu.integratedtest.common.helper.HttpHelper;
+import org.apache.shenyu.web.controller.PluginController.RuleLocalData;
+import org.apache.shenyu.web.controller.PluginController.SelectorRuleData;
+import org.apache.shenyu.web.controller.PluginController.SelectorRulesData;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * The type Abstract plugin data init.
+ */
+public class AbstractPluginDataInit extends AbstractTest {
+    
+    /**
+     * Init plugin string.
+     *
+     * @param pluginName the plugin name
+     * @param config the config
+     * @return the string
+     * @throws IOException the io exception
+     */
+    public static String initPlugin(final String pluginName, final String config) throws IOException {
+        PluginData pluginData = new PluginData();
+        pluginData.setEnabled(true);
+        pluginData.setName(pluginName);
+        pluginData.setConfig(config);
+        return HttpHelper.INSTANCE.postGateway("/shenyu/plugin/saveOrUpdate", pluginData, String.class);
+    }
+    
+    /**
+     * Init selector and rules string.
+     *
+     * @param pluginName the plugin name
+     * @param selectorHandler the selector handler
+     * @param selectorConditionData the selector condition data
+     * @param ruleDataList the rule data list
+     * @return the string
+     * @throws IOException the io exception
+     */
+    public static String initSelectorAndRules(final String pluginName, final String selectorHandler, 
+                                       final List<ConditionData> selectorConditionData,
+                                       final List<RuleLocalData> ruleDataList) throws IOException {
+        SelectorRulesData selectorRulesData = new SelectorRulesData();
+        selectorRulesData.setPluginName(pluginName);
+        selectorRulesData.setSelectorHandler(selectorHandler);
+        selectorRulesData.setConditionDataList(selectorConditionData);
+        selectorRulesData.setRuleDataList(ruleDataList);
+        return HttpHelper.INSTANCE.postGateway("/shenyu/plugin/selectorAndRules", selectorRulesData, String.class);
+    }
+    
+    /**
+     * Init selector and rule string.
+     *
+     * @param pluginName the plugin name
+     * @param selectorHandler the selector handler
+     * @param ruleHandler the rule handler
+     * @param conditionDataList the condition data list
+     * @return the string
+     * @throws IOException the io exception
+     */
+    public static String initSelectorAndRule(final String pluginName, final String selectorHandler,
+                                       final String ruleHandler,
+                                       final List<ConditionData> conditionDataList) throws IOException {
+        SelectorRuleData selectorRuleData = new SelectorRuleData();
+        selectorRuleData.setPluginName(pluginName);
+        selectorRuleData.setSelectorHandler(selectorHandler);
+        selectorRuleData.setRuleHandler(ruleHandler);
+        selectorRuleData.setConditionDataList(conditionDataList);
+        return HttpHelper.INSTANCE.postGateway("/shenyu/plugin/selectorAndRule", selectorRuleData, String.class);
+    }
+    
+    /**
+     * Clean plugin data string.
+     *
+     * @param pluginName the plugin name
+     * @return the string
+     * @throws IOException the io exception
+     */
+    public static String cleanPluginData(final String pluginName) throws IOException {
+        return HttpHelper.INSTANCE.getFromGateway("/shenyu/cleanPlugin?name=" + pluginName, String.class);
+    }
+}
diff --git a/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/WafPluginTest.java b/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/WafPluginTest.java
index f2b49d0..ccd10a9 100644
--- a/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/WafPluginTest.java
+++ b/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/WafPluginTest.java
@@ -17,29 +17,82 @@
 
 package org.apache.shenyu.integrated.test.http.combination;
 
-import org.apache.shenyu.integratedtest.common.AbstractTest;
+import org.apache.shenyu.common.dto.ConditionData;
+import org.apache.shenyu.common.dto.convert.WafHandle;
+import org.apache.shenyu.common.enums.OperatorEnum;
+import org.apache.shenyu.common.enums.ParamTypeEnum;
+import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.common.enums.WafEnum;
+import org.apache.shenyu.common.utils.JsonUtils;
 import org.apache.shenyu.integratedtest.common.helper.HttpHelper;
+import org.apache.shenyu.web.controller.PluginController.RuleLocalData;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 
 import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThat;
 
-public final class WafPluginTest extends AbstractTest {
+public final class WafPluginTest extends AbstractPluginDataInit {
+    
+    @BeforeClass
+    public static void setup() throws IOException {
+        String pluginResult = initPlugin(PluginEnum.WAF.getName(), "{\"model\":\"black\"}");
+        assertThat(pluginResult, is("success"));
+        String selectorAndRulesResult = initSelectorAndRules(PluginEnum.WAF.getName(), "", buildSelectorConditionList(), buildRuleLocalDataList());
+        assertThat(selectorAndRulesResult, is("success"));
+    }
 
     @Test
     public void test() throws IOException {
         Map<String, Object> result = HttpHelper.INSTANCE.postGateway("/http/test/waf/pass", "", Map.class);
         assertNotNull(result);
         assertEquals("pass", result.get("msg"));
-
         result = HttpHelper.INSTANCE.postGateway("/http/test/waf/deny", "", Map.class);
         assertNotNull(result);
         assertThat(String.valueOf(result.get("message")), containsString("You are forbidden to visit"));
     }
-
+    
+    private static List<ConditionData> buildSelectorConditionList() {
+        ConditionData conditionData = new ConditionData();
+        conditionData.setParamType(ParamTypeEnum.URI.getName());
+        conditionData.setOperator(OperatorEnum.MATCH.getAlias());
+        conditionData.setParamValue("/http/test/waf/**");
+        return Collections.singletonList(conditionData);
+    }
+    
+    private static List<RuleLocalData> buildRuleLocalDataList() {
+        List<RuleLocalData> ruleLocalDataList = new ArrayList<>();
+        ruleLocalDataList.add(buildRuleLocalData(WafEnum.ALLOW.getName(), "200", "/http/test/waf/pass"));
+        ruleLocalDataList.add(buildRuleLocalData(WafEnum.REJECT.getName(), "403", "/http/test/waf/deny"));
+        return ruleLocalDataList;
+    }
+    
+    private static RuleLocalData buildRuleLocalData(final String permission, final String statusCode, final String paramValue) {
+        RuleLocalData ruleLocalData = new RuleLocalData();
+        WafHandle wafHandle = new WafHandle();
+        wafHandle.setPermission(permission);
+        wafHandle.setStatusCode(statusCode);
+        ruleLocalData.setRuleHandler(JsonUtils.toJson(wafHandle));
+        ConditionData conditionData = new ConditionData();
+        conditionData.setParamType(ParamTypeEnum.URI.getName());
+        conditionData.setOperator(OperatorEnum.EQ.getAlias());
+        conditionData.setParamValue(paramValue);
+        ruleLocalData.setConditionDataList(Collections.singletonList(conditionData));
+        return ruleLocalData;
+    }
+    
+    @AfterClass
+    public static void clean() throws IOException {
+        cleanPluginData(PluginEnum.WAF.getName());
+    }
 }
diff --git a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/BaseDataCache.java b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/BaseDataCache.java
index 7544cfa..f661e39 100644
--- a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/BaseDataCache.java
+++ b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/BaseDataCache.java
@@ -53,7 +53,7 @@ public final class BaseDataCache {
 
     private BaseDataCache() {
     }
-
+    
     /**
      * Gets instance.
      *
@@ -62,7 +62,7 @@ public final class BaseDataCache {
     public static BaseDataCache getInstance() {
         return INSTANCE;
     }
-
+    
     /**
      * Cache plugin data.
      *
@@ -71,7 +71,7 @@ public final class BaseDataCache {
     public void cachePluginData(final PluginData pluginData) {
         Optional.ofNullable(pluginData).ifPresent(data -> PLUGIN_MAP.put(data.getName(), data));
     }
-
+    
     /**
      * Remove plugin data.
      *
@@ -80,14 +80,23 @@ public final class BaseDataCache {
     public void removePluginData(final PluginData pluginData) {
         Optional.ofNullable(pluginData).ifPresent(data -> PLUGIN_MAP.remove(data.getName()));
     }
-
+    
+    /**
+     * Remove plugin data by plugin name.
+     *
+     * @param pluginName the plugin name
+     */
+    public void removePluginDataByPluginName(final String pluginName) {
+        PLUGIN_MAP.remove(pluginName);
+    }
+    
     /**
      * Clean plugin data.
      */
     public void cleanPluginData() {
         PLUGIN_MAP.clear();
     }
-
+    
     /**
      * Clean plugin data self.
      *
@@ -96,7 +105,7 @@ public final class BaseDataCache {
     public void cleanPluginDataSelf(final List<PluginData> pluginDataList) {
         pluginDataList.forEach(this::removePluginData);
     }
-
+    
     /**
      * Obtain plugin data plugin data.
      *
@@ -106,7 +115,7 @@ public final class BaseDataCache {
     public PluginData obtainPluginData(final String pluginName) {
         return PLUGIN_MAP.get(pluginName);
     }
-
+    
     /**
      * Cache select data.
      *
@@ -115,7 +124,7 @@ public final class BaseDataCache {
     public void cacheSelectData(final SelectorData selectorData) {
         Optional.ofNullable(selectorData).ifPresent(this::selectorAccept);
     }
-
+    
     /**
      * Remove select data.
      *
@@ -127,14 +136,23 @@ public final class BaseDataCache {
             Optional.ofNullable(selectorDataList).ifPresent(list -> list.removeIf(e -> e.getId().equals(data.getId())));
         });
     }
-
+    
+    /**
+     * Remove select data by plugin name.
+     *
+     * @param pluginName the plugin name
+     */
+    public void removeSelectDataByPluginName(final String pluginName) {
+        SELECTOR_MAP.remove(pluginName);
+    }
+    
     /**
      * Clean selector data.
      */
     public void cleanSelectorData() {
         SELECTOR_MAP.clear();
     }
-
+    
     /**
      * Clean selector data self.
      *
@@ -143,7 +161,7 @@ public final class BaseDataCache {
     public void cleanSelectorDataSelf(final List<SelectorData> selectorDataList) {
         selectorDataList.forEach(this::removeSelectData);
     }
-
+    
     /**
      * Obtain selector data list list.
      *
@@ -153,7 +171,7 @@ public final class BaseDataCache {
     public List<SelectorData> obtainSelectorData(final String pluginName) {
         return SELECTOR_MAP.get(pluginName);
     }
-
+    
     /**
      * Cache rule data.
      *
@@ -162,7 +180,7 @@ public final class BaseDataCache {
     public void cacheRuleData(final RuleData ruleData) {
         Optional.ofNullable(ruleData).ifPresent(this::ruleAccept);
     }
-
+    
     /**
      * Remove rule data.
      *
@@ -174,14 +192,23 @@ public final class BaseDataCache {
             Optional.ofNullable(ruleDataList).ifPresent(list -> list.removeIf(rule -> rule.getId().equals(data.getId())));
         });
     }
-
+    
+    /**
+     * Remove rule data by selector id.
+     *
+     * @param selectorId the selector id
+     */
+    public void removeRuleDataBySelectorId(final String selectorId) {
+        RULE_MAP.remove(selectorId);
+    }
+    
     /**
      * Clean rule data.
      */
     public void cleanRuleData() {
         RULE_MAP.clear();
     }
-
+    
     /**
      * Clean rule data self.
      *
@@ -190,7 +217,7 @@ public final class BaseDataCache {
     public void cleanRuleDataSelf(final List<RuleData> ruleDataList) {
         ruleDataList.forEach(this::removeRuleData);
     }
-
+    
     /**
      * Obtain rule data list list.
      *
diff --git a/shenyu-web/src/main/java/org/apache/shenyu/web/controller/PluginController.java b/shenyu-web/src/main/java/org/apache/shenyu/web/controller/PluginController.java
index 0effa17..c699513 100644
--- a/shenyu-web/src/main/java/org/apache/shenyu/web/controller/PluginController.java
+++ b/shenyu-web/src/main/java/org/apache/shenyu/web/controller/PluginController.java
@@ -83,6 +83,24 @@ public class PluginController {
     }
     
     /**
+     * Clean plugin mono.
+     *
+     * @param name the name
+     * @return the mono
+     */
+    @GetMapping("/cleanPlugin")
+    public Mono<String> cleanPlugin(@RequestParam("name") final String name) {
+        BaseDataCache.getInstance().removePluginDataByPluginName(name);
+        List<SelectorData> selectorData = BaseDataCache.getInstance().obtainSelectorData(name);
+        List<String> selectorIds = selectorData.stream().map(SelectorData::getId).collect(Collectors.toList());
+        BaseDataCache.getInstance().removeSelectDataByPluginName(name);
+        for (String selectorId : selectorIds) {
+            BaseDataCache.getInstance().removeRuleDataBySelectorId(selectorId);
+        }
+        return Mono.just(SUCCESS);
+    }
+    
+    /**
      * Add plugin string.
      *
      * @param pluginData the plugin data
@@ -177,6 +195,36 @@ public class PluginController {
     }
     
     /**
+     * Selector and rules mono.
+     *
+     * @param selectorRulesData the selector rules data
+     * @return the mono
+     */
+    @PostMapping("/plugin/selectorAndRules")
+    public Mono<String> selectorAndRules(@RequestBody final SelectorRulesData selectorRulesData) {
+        SelectorData selectorData = SelectorData.builder()
+                .pluginName(selectorRulesData.getPluginName())
+                .handle(selectorRulesData.getSelectorHandler())
+                .conditionList(selectorRulesData.getConditionDataList())
+                .type(SelectorTypeEnum.CUSTOM_FLOW.getCode())
+                .build();
+        SelectorData result = buildDefaultSelectorData(selectorData);
+        subscriber.onSelectorSubscribe(result);
+        List<RuleLocalData> ruleDataList = selectorRulesData.getRuleDataList();
+        for (RuleLocalData data : ruleDataList) {
+            RuleData ruleData = RuleData.builder()
+                    .selectorId(result.getId())
+                    .pluginName(result.getPluginName())
+                    .name(data.getRuleName())
+                    .handle(data.getRuleHandler())
+                    .conditionDataList(data.getConditionDataList())
+                    .build();
+            subscriber.onRuleSubscribe(buildDefaultRuleData(ruleData));
+        }
+        return Mono.just(SUCCESS);
+    }
+    
+    /**
      * Delete selector mono.
      *
      * @param pluginName the plugin name
@@ -415,4 +463,177 @@ public class PluginController {
             this.conditionDataList = conditionDataList;
         }
     }
+    
+    /**
+     * The type Selector rules data.
+     */
+    public static class SelectorRulesData {
+        
+        private String pluginName;
+    
+        private String selectorName;
+    
+        private String selectorHandler;
+    
+        private List<ConditionData> conditionDataList;
+    
+        private List<RuleLocalData> ruleDataList;
+    
+        /**
+         * Gets plugin name.
+         *
+         * @return the plugin name
+         */
+        public String getPluginName() {
+            return pluginName;
+        }
+    
+        /**
+         * Sets plugin name.
+         *
+         * @param pluginName the plugin name
+         */
+        public void setPluginName(final String pluginName) {
+            this.pluginName = pluginName;
+        }
+    
+        /**
+         * Gets selector name.
+         *
+         * @return the selector name
+         */
+        public String getSelectorName() {
+            return selectorName;
+        }
+    
+        /**
+         * Sets selector name.
+         *
+         * @param selectorName the selector name
+         */
+        public void setSelectorName(final String selectorName) {
+            this.selectorName = selectorName;
+        }
+    
+        /**
+         * Gets selector handler.
+         *
+         * @return the selector handler
+         */
+        public String getSelectorHandler() {
+            return selectorHandler;
+        }
+    
+        /**
+         * Sets selector handler.
+         *
+         * @param selectorHandler the selector handler
+         */
+        public void setSelectorHandler(final String selectorHandler) {
+            this.selectorHandler = selectorHandler;
+        }
+    
+        /**
+         * Gets condition data list.
+         *
+         * @return the condition data list
+         */
+        public List<ConditionData> getConditionDataList() {
+            return conditionDataList;
+        }
+    
+        /**
+         * Sets condition data list.
+         *
+         * @param conditionDataList the condition data list
+         */
+        public void setConditionDataList(final List<ConditionData> conditionDataList) {
+            this.conditionDataList = conditionDataList;
+        }
+    
+        /**
+         * Gets rule data list.
+         *
+         * @return the rule data list
+         */
+        public List<RuleLocalData> getRuleDataList() {
+            return ruleDataList;
+        }
+    
+        /**
+         * Sets rule data list.
+         *
+         * @param ruleDataList the rule data list
+         */
+        public void setRuleDataList(final List<RuleLocalData> ruleDataList) {
+            this.ruleDataList = ruleDataList;
+        }
+        
+    }
+    
+    /**
+     * The type Rule data dto.
+     */
+    public static class RuleLocalData {
+        
+        private String ruleName;
+        
+        private String ruleHandler;
+        
+        private List<ConditionData> conditionDataList;
+    
+        /**
+         * Gets rule name.
+         *
+         * @return the rule name
+         */
+        public String getRuleName() {
+            return ruleName;
+        }
+    
+        /**
+         * Sets rule name.
+         *
+         * @param ruleName the rule name
+         */
+        public void setRuleName(final String ruleName) {
+            this.ruleName = ruleName;
+        }
+    
+        /**
+         * Gets rule handler.
+         *
+         * @return the rule handler
+         */
+        public String getRuleHandler() {
+            return ruleHandler;
+        }
+    
+        /**
+         * Sets rule handler.
+         *
+         * @param ruleHandler the rule handler
+         */
+        public void setRuleHandler(final String ruleHandler) {
+            this.ruleHandler = ruleHandler;
+        }
+    
+        /**
+         * Gets condition data list.
+         *
+         * @return the condition data list
+         */
+        public List<ConditionData> getConditionDataList() {
+            return conditionDataList;
+        }
+    
+        /**
+         * Sets condition data list.
+         *
+         * @param conditionDataList the condition data list
+         */
+        public void setConditionDataList(final List<ConditionData> conditionDataList) {
+            this.conditionDataList = conditionDataList;
+        }
+    }
 }