diff --git a/sentinel-dashboard/.gitlab-ci.yml b/sentinel-dashboard/.gitlab-ci.yml
new file mode 100644
index 0000000000..634af063e4
--- /dev/null
+++ b/sentinel-dashboard/.gitlab-ci.yml
@@ -0,0 +1,71 @@
+.default: &default
+ only:
+ - merge_requests
+ - web
+
+.default_tag: &default_tag
+ tags:
+ - backend
+
+stages:
+ - build
+ - quality
+ - deploy
+ - merge
+ - release
+
+merge_ready:
+# tags:
+# - backend
+ stage: quality
+ <<: *default
+ <<: *default_tag
+ script:
+ - mvn test -U -Pquality_check
+
+
+post_merge:
+ stage: merge
+ <<: *default_tag
+ script:
+ - mvn clean test -U -Pquality_check
+ only:
+ refs:
+ - develop
+
+build_snapshot:
+# tags:
+# - backend
+ stage: build
+ <<: *default
+ <<: *default_tag
+ script:
+ - mvn clean install -DskipTests=true -U -Pdocker
+
+deploy_snapshot:
+# tags:
+# - backend
+ stage: deploy
+ <<: *default_tag
+ only:
+ - web
+ script:
+ - mvn deploy -DskipTests=true -Pdocker
+ when: manual
+ allow_failure: false
+
+
+release:
+ <<: *default_tag
+ stage: release
+ script:
+ - git remote set-url origin "git@gitlab.phonepe.com:${CI_PROJECT_PATH}.git"
+ - git checkout master
+ - git checkout develop
+ - mvn -U -Pdocker jgitflow:release-start jgitflow:release-finish
+ - git push --all
+ - git push --tags origin
+ when: manual
+ only:
+ refs:
+ - develop
diff --git a/sentinel-dashboard/Dockerfile b/sentinel-dashboard/Dockerfile
new file mode 100644
index 0000000000..aafbccf8e0
--- /dev/null
+++ b/sentinel-dashboard/Dockerfile
@@ -0,0 +1,13 @@
+FROM openjdk:8-jdk-alpine
+
+ARG SENTINEL_VERSION="1.7.1"
+
+WORKDIR /home/sentinel
+
+ENV JAR_FILE sentinel-dashboard.jar
+ADD target/sentinel-dashboard.jar ${JAR_FILE}
+
+EXPOSE 7070
+EXPOSE 7071
+
+CMD java -Dserver.port=7070 -Dcsp.sentinel.dashboard.server=localhost:7070 -Dproject.name=sentinel -jar ${JAR_FILE}
\ No newline at end of file
diff --git a/sentinel-dashboard/pom.xml b/sentinel-dashboard/pom.xml
index bcf0b2a94d..730988e337 100755
--- a/sentinel-dashboard/pom.xml
+++ b/sentinel-dashboard/pom.xml
@@ -11,37 +11,91 @@
sentinel-dashboard
jar
+ 1.7.1-SNAPSHOT
+
+
+
+ clojars
+ Clojars repository
+ https://clojars.org/repo
+
+
+ phonepe-snapshots
+ http://artifactory.phonepe.com/content/repositories/snapshots
+
+
1.8
1.8
2.0.5.RELEASE
4.0.1
+ 1.7.1
com.alibaba.csp
sentinel-core
+ 1.7.1
com.alibaba.csp
sentinel-web-servlet
- ${project.version}
+ 1.7.1
+
+
+ com.alibaba.csp
+ sentinel-core
+
+
com.alibaba.csp
sentinel-transport-simple-http
+ 1.7.1
+
+
+ com.alibaba.csp
+ sentinel-transport-common
+
+
+
+
+ com.alibaba.csp
+ sentinel-transport-common
+ 1.7.1
+
+
+ com.alibaba.csp
+ sentinel-datasource-extension
+ 1.7.1
com.alibaba.csp
sentinel-parameter-flow-control
- ${project.version}
+ 1.7.1
+
+
+ com.alibaba.csp
+ sentinel-core
+
+
com.alibaba.csp
sentinel-api-gateway-adapter-common
- ${project.version}
+ 1.7.1
+
+
+ com.alibaba.csp
+ sentinel-core
+
+
+ com.alibaba.csp
+ sentinel-parameter-flow-control
+
+
@@ -102,7 +156,14 @@
com.alibaba.csp
sentinel-datasource-nacos
+ 1.7.1
test
+
+
+ com.alibaba.csp
+ sentinel-datasource-extension
+
+
@@ -117,7 +178,6 @@
org.apache.curator
curator-recipes
${curator.version}
- test
@@ -136,6 +196,25 @@
1.16.1
test
+
+
+ org.apache.curator
+ curator-framework
+ 4.2.0
+
+
+
+ com.alibaba.csp
+ sentinel-datasource-zookeeper
+ 1.7.1
+
+
+ com.alibaba.csp
+ sentinel-datasource-extension
+
+
+
+
@@ -171,9 +250,9 @@
org.apache.maven.plugins
maven-deploy-plugin
${maven.deploy.version}
-
+
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/auth/SimpleWebAuthServiceImpl.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/auth/SimpleWebAuthServiceImpl.java
index 5d9599ee96..63225c2b17 100644
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/auth/SimpleWebAuthServiceImpl.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/auth/SimpleWebAuthServiceImpl.java
@@ -15,32 +15,34 @@
*/
package com.alibaba.csp.sentinel.dashboard.auth;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Component;
-
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Component;
/**
* @author cdfive
* @since 1.6.0
*/
-@Component
@Primary
-@ConditionalOnProperty(name = "auth.enabled", matchIfMissing = true)
+@Component
public class SimpleWebAuthServiceImpl implements AuthService {
- public static final String WEB_SESSION_KEY = "session_sentinel_admin";
+ public static final String WEB_SESSION_KEY = "session_sentinel_user";
+ public static final String WEB_SESSION_KEY_ADMIN = "session_sentinel_admin";
@Override
public AuthUser getAuthUser(HttpServletRequest request) {
HttpSession session = request.getSession();
- Object sentinelUserObj = session.getAttribute(SimpleWebAuthServiceImpl.WEB_SESSION_KEY);
- if (sentinelUserObj != null && sentinelUserObj instanceof AuthUser) {
+ Object sentinelUserObj = session.getAttribute(SimpleWebAuthServiceImpl.WEB_SESSION_KEY_ADMIN);
+
+ if (sentinelUserObj != null && sentinelUserObj instanceof AuthService.AuthUser) {
+ return (AuthUser) sentinelUserObj;
+ }
+ sentinelUserObj = session.getAttribute(SimpleWebAuthServiceImpl.WEB_SESSION_KEY);
+ if (sentinelUserObj != null && sentinelUserObj instanceof AuthService.AuthUser) {
return (AuthUser) sentinelUserObj;
}
-
return null;
}
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/SentinelApiClient.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/SentinelApiClient.java
index 008e67c1ec..4c2c920646 100755
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/SentinelApiClient.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/SentinelApiClient.java
@@ -15,37 +15,9 @@
*/
package com.alibaba.csp.sentinel.dashboard.client;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.stream.Collectors;
-
-import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.command.CommandConstants;
-import com.alibaba.csp.sentinel.config.SentinelConfig;
import com.alibaba.csp.sentinel.command.vo.NodeVo;
-import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity;
-import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity;
-import com.alibaba.csp.sentinel.dashboard.util.AsyncUtils;
-import com.alibaba.csp.sentinel.slots.block.Rule;
-import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
-import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
-import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
-import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
-import com.alibaba.csp.sentinel.slots.system.SystemRule;
-import com.alibaba.csp.sentinel.util.AssertUtil;
-import com.alibaba.csp.sentinel.util.StringUtil;
-import com.alibaba.fastjson.JSON;
+import com.alibaba.csp.sentinel.config.SentinelConfig;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.SentinelVersion;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
@@ -55,14 +27,36 @@
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity;
import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
import com.alibaba.csp.sentinel.dashboard.domain.cluster.ClusterClientInfoVO;
-import com.alibaba.csp.sentinel.dashboard.domain.cluster.state.ClusterServerStateVO;
-import com.alibaba.csp.sentinel.dashboard.domain.cluster.state.ClusterStateSimpleEntity;
import com.alibaba.csp.sentinel.dashboard.domain.cluster.config.ClusterClientConfig;
import com.alibaba.csp.sentinel.dashboard.domain.cluster.config.ServerFlowConfig;
import com.alibaba.csp.sentinel.dashboard.domain.cluster.config.ServerTransportConfig;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.state.ClusterServerStateVO;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.state.ClusterStateSimpleEntity;
+import com.alibaba.csp.sentinel.dashboard.util.AsyncUtils;
import com.alibaba.csp.sentinel.dashboard.util.VersionUtils;
-
-import org.apache.http.Consts;
+import com.alibaba.csp.sentinel.slots.block.Rule;
+import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
+import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
+import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
+import com.alibaba.csp.sentinel.slots.system.SystemRule;
+import com.alibaba.csp.sentinel.util.AssertUtil;
+import com.alibaba.csp.sentinel.util.StringUtil;
+import com.alibaba.fastjson.JSON;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
@@ -112,13 +106,6 @@ public class SentinelApiClient {
private static final String MODIFY_CLUSTER_SERVER_TRANSPORT_CONFIG_PATH = "cluster/server/modifyTransportConfig";
private static final String MODIFY_CLUSTER_SERVER_FLOW_CONFIG_PATH = "cluster/server/modifyFlowConfig";
private static final String MODIFY_CLUSTER_SERVER_NAMESPACE_SET_PATH = "cluster/server/modifyNamespaceSet";
-
- private static final String FETCH_GATEWAY_API_PATH = "gateway/getApiDefinitions";
- private static final String MODIFY_GATEWAY_API_PATH = "gateway/updateApiDefinitions";
-
- private static final String FETCH_GATEWAY_FLOW_RULE_PATH = "gateway/getRules";
- private static final String MODIFY_GATEWAY_FLOW_RULE_PATH = "gateway/updateRules";
-
private static final String FLOW_RULE_TYPE = "flow";
private static final String DEGRADE_RULE_TYPE = "degrade";
private static final String SYSTEM_RULE_TYPE = "system";
@@ -127,7 +114,7 @@ public class SentinelApiClient {
private CloseableHttpAsyncClient httpClient;
private static final SentinelVersion version160 = new SentinelVersion(1, 6, 0);
-
+
@Autowired
private AppManagement appManagement;
@@ -146,11 +133,11 @@ protected boolean isRedirectable(final String method) {
private boolean isSuccess(int statusCode) {
return statusCode >= 200 && statusCode < 300;
}
-
+
private boolean isCommandNotFound(int statusCode, String body) {
return statusCode == 400 && StringUtil.isNotEmpty(body) && body.contains(CommandConstants.MSG_UNKNOWN_COMMAND_PREFIX);
}
-
+
private StringBuilder queryString(Map params) {
StringBuilder queryStringBuilder = new StringBuilder();
for (Entry entry : params.entrySet()) {
@@ -168,7 +155,7 @@ private StringBuilder queryString(Map params) {
}
return queryStringBuilder;
}
-
+
private HttpUriRequest postRequest(String url, Map params) {
HttpPost httpPost = new HttpPost(url);
if (params != null && params.size() > 0) {
@@ -176,11 +163,16 @@ private HttpUriRequest postRequest(String url, Map params) {
for (Entry entry : params.entrySet()) {
list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
- httpPost.setEntity(new UrlEncodedFormEntity(list, Consts.UTF_8));
+ try {
+ httpPost.setEntity(new UrlEncodedFormEntity(list));
+ } catch (UnsupportedEncodingException e) {
+ logger.warn("httpPostContent encode entity error: {}", params, e);
+ return null;
+ }
}
return httpPost;
}
-
+
private String urlEncode(String str) {
try {
return URLEncoder.encode(str, DEFAULT_CHARSET.name());
@@ -189,7 +181,7 @@ private String urlEncode(String str) {
return null;
}
}
-
+
private String getBody(HttpResponse response) throws Exception {
Charset charset = null;
try {
@@ -202,10 +194,10 @@ private String getBody(HttpResponse response) throws Exception {
}
return EntityUtils.toString(response.getEntity(), charset != null ? charset : DEFAULT_CHARSET);
}
-
+
/**
* With no param
- *
+ *
* @param ip
* @param port
* @param api
@@ -214,10 +206,10 @@ private String getBody(HttpResponse response) throws Exception {
private CompletableFuture executeCommand(String ip, int port, String api, boolean useHttpPost) {
return executeCommand(ip, port, api, null, useHttpPost);
}
-
+
/**
* No app specified, force to GET
- *
+ *
* @param ip
* @param port
* @param api
@@ -230,7 +222,7 @@ private CompletableFuture executeCommand(String ip, int port, String api
/**
* Prefer to execute request using POST
- *
+ *
* @param app
* @param ip
* @param port
@@ -271,7 +263,7 @@ private CompletableFuture executeCommand(String app, String ip, int port
return executeCommand(postRequest(urlBuilder.toString(), params));
}
}
-
+
private CompletableFuture executeCommand(HttpUriRequest request) {
CompletableFuture future = new CompletableFuture<>();
httpClient.execute(request, new FutureCallback() {
@@ -309,11 +301,11 @@ public void cancelled() {
});
return future;
}
-
+
public void close() throws Exception {
httpClient.close();
}
-
+
@Nullable
private CompletableFuture> fetchItemsAsync(String ip, int port, String api, String type, Class ruleType) {
AssertUtil.notEmpty(ip, "Bad machine IP");
@@ -326,7 +318,7 @@ private CompletableFuture> fetchItemsAsync(String ip, int port, Stri
return executeCommand(ip, port, api, params, false)
.thenApply(json -> JSON.parseArray(json, ruleType));
}
-
+
@Nullable
private List fetchItems(String ip, int port, String api, String type, Class ruleType) {
try {
@@ -346,11 +338,11 @@ private List fetchItems(String ip, int port, String api, String type, Cla
return null;
}
}
-
+
private List fetchRules(String ip, int port, String type, Class ruleType) {
return fetchItems(ip, port, GET_RULES_PATH, type, ruleType);
}
-
+
private boolean setRules(String app, String ip, int port, String type, List extends RuleEntity> entities) {
if (entities == null) {
return true;
@@ -379,30 +371,6 @@ private boolean setRules(String app, String ip, int port, String type, List ex
}
}
- private CompletableFuture setRulesAsync(String app, String ip, int port, String type, List extends RuleEntity> entities) {
- try {
- AssertUtil.notNull(entities, "rules cannot be null");
- AssertUtil.notEmpty(app, "Bad app name");
- AssertUtil.notEmpty(ip, "Bad machine IP");
- AssertUtil.isTrue(port > 0, "Bad machine port");
- String data = JSON.toJSONString(
- entities.stream().map(r -> r.toRule()).collect(Collectors.toList()));
- Map params = new HashMap<>(2);
- params.put("type", type);
- params.put("data", data);
- return executeCommand(app, ip, port, SET_RULES_PATH, params, true)
- .thenCompose(r -> {
- if ("success".equalsIgnoreCase(r.trim())) {
- return CompletableFuture.completedFuture(null);
- }
- return AsyncUtils.newFailedFuture(new CommandFailedException(r));
- });
- } catch (Exception e) {
- logger.error("setRulesAsync API failed, type={}", type, e);
- return AsyncUtils.newFailedFuture(e);
- }
- }
-
public List fetchResourceOfMachine(String ip, int port, String type) {
return fetchItems(ip, port, RESOURCE_URL_PATH, type, NodeVo.class);
}
@@ -514,10 +482,6 @@ public boolean setFlowRuleOfMachine(String app, String ip, int port, List setFlowRuleOfMachineAsync(String app, String ip, int port, List rules) {
- return setRulesAsync(app, ip, port, FLOW_RULE_TYPE, rules);
- }
-
/**
* set rules of the machine. rules == null will return immediately;
* rules.isEmpty() means setting the rules to empty.
@@ -729,90 +693,4 @@ public CompletableFuture fetchClusterServerBasicInfo(Strin
return AsyncUtils.newFailedFuture(ex);
}
}
-
- public CompletableFuture> fetchApis(String app, String ip, int port) {
- if (StringUtil.isBlank(ip) || port <= 0) {
- return AsyncUtils.newFailedFuture(new IllegalArgumentException("Invalid parameter"));
- }
-
- try {
- return executeCommand(ip, port, FETCH_GATEWAY_API_PATH, false)
- .thenApply(r -> {
- List entities = JSON.parseArray(r, ApiDefinitionEntity.class);
- if (entities != null) {
- for (ApiDefinitionEntity entity : entities) {
- entity.setApp(app);
- entity.setIp(ip);
- entity.setPort(port);
- }
- }
- return entities;
- });
- } catch (Exception ex) {
- logger.warn("Error when fetching gateway apis", ex);
- return AsyncUtils.newFailedFuture(ex);
- }
- }
-
- public boolean modifyApis(String app, String ip, int port, List apis) {
- if (apis == null) {
- return true;
- }
-
- try {
- AssertUtil.notEmpty(app, "Bad app name");
- AssertUtil.notEmpty(ip, "Bad machine IP");
- AssertUtil.isTrue(port > 0, "Bad machine port");
- String data = JSON.toJSONString(
- apis.stream().map(r -> r.toApiDefinition()).collect(Collectors.toList()));
- Map params = new HashMap<>(2);
- params.put("data", data);
- String result = executeCommand(app, ip, port, MODIFY_GATEWAY_API_PATH, params, true).get();
- logger.info("Modify gateway apis: {}", result);
- return true;
- } catch (Exception e) {
- logger.warn("Error when modifying gateway apis", e);
- return false;
- }
- }
-
- public CompletableFuture> fetchGatewayFlowRules(String app, String ip, int port) {
- if (StringUtil.isBlank(ip) || port <= 0) {
- return AsyncUtils.newFailedFuture(new IllegalArgumentException("Invalid parameter"));
- }
-
- try {
- return executeCommand(ip, port, FETCH_GATEWAY_FLOW_RULE_PATH, false)
- .thenApply(r -> {
- List gatewayFlowRules = JSON.parseArray(r, GatewayFlowRule.class);
- List entities = gatewayFlowRules.stream().map(rule -> GatewayFlowRuleEntity.fromGatewayFlowRule(app, ip, port, rule)).collect(Collectors.toList());
- return entities;
- });
- } catch (Exception ex) {
- logger.warn("Error when fetching gateway flow rules", ex);
- return AsyncUtils.newFailedFuture(ex);
- }
- }
-
- public boolean modifyGatewayFlowRules(String app, String ip, int port, List rules) {
- if (rules == null) {
- return true;
- }
-
- try {
- AssertUtil.notEmpty(app, "Bad app name");
- AssertUtil.notEmpty(ip, "Bad machine IP");
- AssertUtil.isTrue(port > 0, "Bad machine port");
- String data = JSON.toJSONString(
- rules.stream().map(r -> r.toGatewayFlowRule()).collect(Collectors.toList()));
- Map params = new HashMap<>(2);
- params.put("data", data);
- String result = executeCommand(app, ip, port, MODIFY_GATEWAY_FLOW_RULE_PATH, params, true).get();
- logger.info("Modify gateway flow rules: {}", result);
- return true;
- } catch (Exception e) {
- logger.warn("Error when modifying gateway apis", e);
- return false;
- }
- }
}
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/DashboardConfig.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/DashboardConfig.java
index 92e0608ec3..ef53efc919 100644
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/DashboardConfig.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/DashboardConfig.java
@@ -47,6 +47,10 @@ public class DashboardConfig {
*/
public static final String CONFIG_AUTH_PASSWORD = "sentinel.dashboard.auth.password";
+ public static final String ADMIN_USERNAME = "sentinel.dashboard.auth.admin.username";
+
+ public static final String ADMIN_PASSWORD = "sentinel.dashboard.auth.admin.password";
+
/**
* Hide application name in sidebar when it has no healthy machines after specific period in millisecond.
*/
@@ -65,7 +69,7 @@ public class DashboardConfig {
public static final String CONFIG_AUTO_REMOVE_MACHINE_MILLIS = "sentinel.dashboard.autoRemoveMachineMillis";
private static final ConcurrentMap cacheMap = new ConcurrentHashMap<>();
-
+
@NonNull
private static String getConfig(String name) {
// env
@@ -121,19 +125,19 @@ public static String getAuthPassword() {
public static int getHideAppNoMachineMillis() {
return getConfigInt(CONFIG_HIDE_APP_NO_MACHINE_MILLIS, 0, 60000);
}
-
+
public static int getRemoveAppNoMachineMillis() {
return getConfigInt(CONFIG_REMOVE_APP_NO_MACHINE_MILLIS, 0, 120000);
}
-
+
public static int getAutoRemoveMachineMillis() {
return getConfigInt(CONFIG_AUTO_REMOVE_MACHINE_MILLIS, 0, 300000);
}
-
+
public static int getUnhealthyMachineMillis() {
return getConfigInt(CONFIG_UNHEALTHY_MACHINE_MILLIS, DEFAULT_MACHINE_HEALTHY_TIMEOUT_MS, 30000);
}
-
+
public static void clearCache() {
cacheMap.clear();
}
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/WebConfig.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/WebConfig.java
index 92e51e54ae..13aaa6019a 100755
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/WebConfig.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/WebConfig.java
@@ -25,6 +25,8 @@
import com.alibaba.csp.sentinel.dashboard.auth.LoginAuthenticationFilter;
import com.alibaba.csp.sentinel.util.StringUtil;
+import com.alibaba.csp.sentinel.dashboard.filter.AuthFilter;
+import javax.servlet.Filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -48,15 +50,7 @@ public class WebConfig implements WebMvcConfigurer {
private final Logger logger = LoggerFactory.getLogger(WebConfig.class);
@Autowired
- private LoginAuthenticationFilter loginAuthenticationFilter;
-
- @Autowired
- private AuthorizationInterceptor authorizationInterceptor;
-
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(authorizationInterceptor).addPathPatterns("/**");
- }
+ private AuthFilter authFilter;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
@@ -79,35 +73,16 @@ public FilterRegistrationBean sentinelFilterRegistration() {
registration.addUrlPatterns("/*");
registration.setName("sentinelFilter");
registration.setOrder(1);
- // If this is enabled, the entrance of all Web URL resources will be unified as a single context name.
- // In most scenarios that's enough, and it could reduce the memory footprint.
- registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "true");
logger.info("Sentinel servlet CommonFilter registered");
return registration;
}
- @PostConstruct
- public void doInit() {
- Set suffixSet = new HashSet<>(Arrays.asList(".js", ".css", ".html", ".ico", ".txt",
- ".woff", ".woff2"));
- // Example: register a UrlCleaner to exclude URLs of common static resources.
- WebCallbackManager.setUrlCleaner(url -> {
- if (StringUtil.isEmpty(url)) {
- return url;
- }
- if (suffixSet.stream().anyMatch(url::endsWith)) {
- return null;
- }
- return url;
- });
- }
-
@Bean
public FilterRegistrationBean authenticationFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean<>();
- registration.setFilter(loginAuthenticationFilter);
+ registration.setFilter(authFilter);
registration.addUrlPatterns("/*");
registration.setName("authenticationFilter");
registration.setOrder(0);
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AppController.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AppController.java
index 635489661e..ce2c776a75 100755
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AppController.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AppController.java
@@ -66,7 +66,7 @@ public Result> getMachinesByApp(@PathVariable("app") String
Collections.sort(list, Comparator.comparing(MachineInfo::getApp).thenComparing(MachineInfo::getIp).thenComparingInt(MachineInfo::getPort));
return Result.ofSuccess(MachineInfoVo.fromMachineInfoList(list));
}
-
+
@RequestMapping(value = "/{app}/machine/remove.json")
public Result removeMachineById(
@PathVariable("app") String app,
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthController.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthController.java
index 8b01aed232..118d0ffee7 100644
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthController.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthController.java
@@ -16,20 +16,20 @@
package com.alibaba.csp.sentinel.dashboard.controller;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.AuthUser;
import com.alibaba.csp.sentinel.dashboard.auth.SimpleWebAuthServiceImpl;
import com.alibaba.csp.sentinel.dashboard.config.DashboardConfig;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
+import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
-import javax.servlet.http.HttpServletRequest;
-
/**
* @author cdfive
* @since 1.6.0
@@ -46,11 +46,14 @@ public class AuthController {
@Value("${auth.password:sentinel}")
private String authPassword;
- @Autowired
- private AuthService authService;
+ @Value("${auth.admin.username}")
+ private String adminUsername;
+
+ @Value("${auth.admin.password}")
+ private String adminPassword;
@PostMapping("/login")
- public Result login(HttpServletRequest request, String username, String password) {
+ public Result login(HttpServletRequest request, String username, String password) {
if (StringUtils.isNotBlank(DashboardConfig.getAuthUsername())) {
authUsername = DashboardConfig.getAuthUsername();
}
@@ -64,29 +67,40 @@ public Result login(HttpServletRequest request, String use
* auth will pass, as the front side validate the input which can't be blank,
* so user can input any username or password(both are not blank) to login in that case.
*/
- if (StringUtils.isNotBlank(authUsername) && !authUsername.equals(username)
- || StringUtils.isNotBlank(authPassword) && !authPassword.equals(password)) {
- LOGGER.error("Login failed: Invalid username or password, username=" + username);
- return Result.ofFail(-1, "Invalid username or password");
+ if (StringUtils.isBlank(username)) {
+ LOGGER.error("Login failed: Invalid username is null");
+ return Result.ofFail(-1, "用户名不能为空!");
+ }
+ if (!authUsername.equals(username) && !adminUsername.equals(username)) {
+ LOGGER.error("Login failed: 用户名不正确");
+ return Result.ofFail(-1, "用户名不正确!");
+ }
+ if (adminUsername.equals(username)) {
+ if (StringUtils.isNotBlank(adminPassword) && !adminPassword.equals(password)) {
+ LOGGER.error("Login failed: 密码不正确, username=" + username);
+ return Result.ofFail(-1, "密码不正确");
+ }
+ AuthService.AuthUser authUser = new SimpleWebAuthServiceImpl.SimpleWebAuthUserImpl(username);
+ request.getSession()
+ .setAttribute(SimpleWebAuthServiceImpl.WEB_SESSION_KEY_ADMIN, authUser);
+ return Result.ofSuccess(authUser);
+ } else {
+ if (StringUtils.isNotBlank(authPassword) && !authPassword.equals(password)) {
+ LOGGER.error("Login failed: Invalid username or password, username=" + username);
+ return Result.ofFail(-1, "密码不正确");
+ }
+ AuthService.AuthUser authUser = new SimpleWebAuthServiceImpl.SimpleWebAuthUserImpl(username);
+ request.getSession()
+ .setAttribute(SimpleWebAuthServiceImpl.WEB_SESSION_KEY, authUser);
+ return Result.ofSuccess(authUser);
}
- AuthService.AuthUser authUser = new SimpleWebAuthServiceImpl.SimpleWebAuthUserImpl(username);
- request.getSession().setAttribute(SimpleWebAuthServiceImpl.WEB_SESSION_KEY, authUser);
- return Result.ofSuccess(authUser);
}
- @PostMapping(value = "/logout")
+ @RequestMapping(value = "/logout", method = RequestMethod.POST)
public Result> logout(HttpServletRequest request) {
- request.getSession().invalidate();
+ request.getSession()
+ .invalidate();
return Result.ofSuccess(null);
}
-
- @PostMapping(value = "/check")
- public Result> check(HttpServletRequest request) {
- AuthService.AuthUser authUser = authService.getAuthUser(request);
- if (authUser == null) {
- return Result.ofFail(-1, "Not logged in");
- }
- return Result.ofSuccess(authUser);
- }
}
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthorityRuleController.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthorityRuleController.java
index 294455f02a..c5dcfbca32 100644
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthorityRuleController.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthorityRuleController.java
@@ -15,23 +15,23 @@
*/
package com.alibaba.csp.sentinel.dashboard.controller;
-import java.util.Date;
-import java.util.List;
-
-import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
-import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
-import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.AuthUser;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
-import com.alibaba.csp.sentinel.slots.block.RuleConstant;
-import com.alibaba.csp.sentinel.util.StringUtil;
-
+import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
-
+import com.alibaba.csp.sentinel.slots.block.RuleConstant;
+import com.alibaba.csp.sentinel.util.StringUtil;
+import java.util.Date;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -57,11 +57,17 @@ public class AuthorityRuleController {
@Autowired
private RuleRepository repository;
+ @Autowired
+ private AuthService authService;
+
+ @Value("${auth.admin.username}")
+ private String adminUsername;
+
@GetMapping("/rules")
- @AuthAction(PrivilegeType.READ_RULE)
- public Result> apiQueryAllRulesForMachine(@RequestParam String app,
- @RequestParam String ip,
- @RequestParam Integer port) {
+ public Result> apiQueryAllRulesForMachine(HttpServletRequest request,
+ @RequestParam String app, @RequestParam String ip, @RequestParam Integer port) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.READ_RULE);
if (StringUtil.isEmpty(app)) {
return Result.ofFail(-1, "app cannot be null or empty");
}
@@ -104,15 +110,20 @@ private Result checkEntityInternal(AuthorityRuleEntity entity) {
return Result.ofFail(-1, "limitApp should be valid");
}
if (entity.getStrategy() != RuleConstant.AUTHORITY_WHITE
- && entity.getStrategy() != RuleConstant.AUTHORITY_BLACK) {
+ && entity.getStrategy() != RuleConstant.AUTHORITY_BLACK) {
return Result.ofFail(-1, "Unknown strategy (must be blacklist or whitelist)");
}
return null;
}
@PostMapping("/rule")
- @AuthAction(PrivilegeType.WRITE_RULE)
- public Result apiAddAuthorityRule(@RequestBody AuthorityRuleEntity entity) {
+ public Result apiAddAuthorityRule(HttpServletRequest request,
+ @RequestBody AuthorityRuleEntity entity) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (!adminUsername.equals(authUser.getLoginName())) {
+ return Result.ofFail(-2, "您不是管理员,没有该权限!");
+ }
+ authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE);
Result checkResult = checkEntityInternal(entity);
if (checkResult != null) {
return checkResult;
@@ -134,9 +145,13 @@ public Result apiAddAuthorityRule(@RequestBody AuthorityRul
}
@PutMapping("/rule/{id}")
- @AuthAction(PrivilegeType.WRITE_RULE)
- public Result apiUpdateParamFlowRule(@PathVariable("id") Long id,
- @RequestBody AuthorityRuleEntity entity) {
+ public Result apiUpdateParamFlowRule(HttpServletRequest request, @PathVariable("id") Long id,
+ @RequestBody AuthorityRuleEntity entity) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (!adminUsername.equals(authUser.getLoginName())) {
+ return Result.ofFail(-2, "您不是管理员,没有该权限!");
+ }
+ authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE);
if (id == null || id <= 0) {
return Result.ofFail(-1, "Invalid id");
}
@@ -164,8 +179,11 @@ public Result apiUpdateParamFlowRule(@PathVariable("id") Lo
}
@DeleteMapping("/rule/{id}")
- @AuthAction(PrivilegeType.DELETE_RULE)
- public Result apiDeleteRule(@PathVariable("id") Long id) {
+ public Result apiDeleteRule(HttpServletRequest request, @PathVariable("id") Long id) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (!adminUsername.equals(authUser.getLoginName())) {
+ return Result.ofFail(-2, "您不是管理员,没有该权限!");
+ }
if (id == null) {
return Result.ofFail(-1, "id cannot be null");
}
@@ -173,6 +191,7 @@ public Result apiDeleteRule(@PathVariable("id") Long id) {
if (oldEntity == null) {
return Result.ofSuccess(null);
}
+ authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE);
try {
repository.delete(id);
} catch (Exception e) {
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/DegradeController.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/DegradeController.java
index 61aaee68aa..d337114294 100755
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/DegradeController.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/DegradeController.java
@@ -15,30 +15,34 @@
*/
package com.alibaba.csp.sentinel.dashboard.controller;
-import java.util.Date;
-import java.util.List;
-
-import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
-import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
-import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.AuthUser;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
-import com.alibaba.csp.sentinel.slots.block.RuleConstant;
-import com.alibaba.csp.sentinel.util.StringUtil;
-
+import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemDegradeRuleStore;
-
+import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
+import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
+import com.alibaba.csp.sentinel.slots.block.RuleConstant;
+import com.alibaba.csp.sentinel.util.StringUtil;
+import java.util.Date;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
- * @author leyou
+ * Degrade rule controller
+ *
+ * @author guifei.qin
*/
@Controller
@RequestMapping(value = "/degrade", produces = MediaType.APPLICATION_JSON_VALUE)
@@ -51,10 +55,25 @@ public class DegradeController {
@Autowired
private SentinelApiClient sentinelApiClient;
+ @Autowired
+ private AuthService authService;
+
+ @Autowired
+ @Qualifier("degradeRuleZookeeperProvider")
+ private DynamicRuleProvider> ruleProvider;
+ @Autowired
+ @Qualifier("degradeRuleZookeeperPublisher")
+ private DynamicRulePublisher> rulePublisher;
+
+ @Value("${auth.admin.username}")
+ private String adminUsername;
+
@ResponseBody
@RequestMapping("/rules.json")
- @AuthAction(PrivilegeType.READ_RULE)
- public Result> queryMachineRules(String app, String ip, Integer port) {
+ public Result> queryMachineRules(HttpServletRequest request, String app, String ip,
+ Integer port) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.READ_RULE);
if (StringUtil.isEmpty(app)) {
return Result.ofFail(-1, "app can't be null or empty");
@@ -66,7 +85,14 @@ public Result> queryMachineRules(String app, String ip,
return Result.ofFail(-1, "port can't be null");
}
try {
- List rules = sentinelApiClient.fetchDegradeRuleOfMachine(app, ip, port);
+// List rules = sentinelApiClient.fetchDegradeRuleOfMachine(app, ip, port);
+ List rules = ruleProvider.getRules(app);
+ if (rules != null && !rules.isEmpty()) {
+ for (DegradeRuleEntity entity : rules) {
+ entity.setApp(app);
+ }
+ }
+
rules = repository.saveAll(rules);
return Result.ofSuccess(rules);
} catch (Throwable throwable) {
@@ -77,9 +103,14 @@ public Result> queryMachineRules(String app, String ip,
@ResponseBody
@RequestMapping("/new.json")
- @AuthAction(PrivilegeType.WRITE_RULE)
- public Result add(String app, String ip, Integer port, String limitApp, String resource,
- Double count, Integer timeWindow, Integer grade) {
+ public Result add(HttpServletRequest request, String app, String ip, Integer port,
+ String limitApp, String resource, Double count, Integer timeWindow, Integer grade) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (!adminUsername.equals(authUser.getLoginName())) {
+ return Result.ofFail(-2, "您不是管理员,没有该权限!");
+ }
+ authUser.authTarget(app, PrivilegeType.WRITE_RULE);
+
if (StringUtil.isBlank(app)) {
return Result.ofFail(-1, "app can't be null or empty");
}
@@ -121,21 +152,23 @@ public Result add(String app, String ip, Integer port, String
entity.setGmtModified(date);
try {
entity = repository.save(entity);
+ publishRules(app);
} catch (Throwable throwable) {
logger.error("add error:", throwable);
return Result.ofThrowable(-1, throwable);
}
- if (!publishRules(app, ip, port)) {
- logger.info("publish degrade rules fail after rule add");
- }
+
return Result.ofSuccess(entity);
}
@ResponseBody
@RequestMapping("/save.json")
- @AuthAction(PrivilegeType.WRITE_RULE)
- public Result updateIfNotNull(Long id, String app, String limitApp, String resource,
- Double count, Integer timeWindow, Integer grade) {
+ public Result updateIfNotNull(HttpServletRequest request, Long id, String app, String limitApp,
+ String resource, Double count, Integer timeWindow, Integer grade) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (!adminUsername.equals(authUser.getLoginName())) {
+ return Result.ofFail(-2, "您不是管理员,没有该权限!");
+ }
if (id == null) {
return Result.ofFail(-1, "id can't be null");
}
@@ -148,7 +181,7 @@ public Result updateIfNotNull(Long id, String app, String lim
if (entity == null) {
return Result.ofFail(-1, "id " + id + " dose not exist");
}
-
+ authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE);
if (StringUtil.isNotBlank(app)) {
entity.setApp(app.trim());
}
@@ -172,20 +205,24 @@ public Result updateIfNotNull(Long id, String app, String lim
entity.setGmtModified(date);
try {
entity = repository.save(entity);
+ if (entity == null) {
+ return Result.ofFail(-1, "save entity fail");
+ }
+ publishRules(entity.getApp());
} catch (Throwable throwable) {
logger.error("save error:", throwable);
return Result.ofThrowable(-1, throwable);
}
- if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
- logger.info("publish degrade rules fail after rule update");
- }
return Result.ofSuccess(entity);
}
@ResponseBody
@RequestMapping("/delete.json")
- @AuthAction(PrivilegeType.DELETE_RULE)
- public Result delete(Long id) {
+ public Result delete(HttpServletRequest request, Long id) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (!adminUsername.equals(authUser.getLoginName())) {
+ return Result.ofFail(-2, "您不是管理员,没有该权限!");
+ }
if (id == null) {
return Result.ofFail(-1, "id can't be null");
}
@@ -194,21 +231,24 @@ public Result delete(Long id) {
if (oldEntity == null) {
return Result.ofSuccess(null);
}
-
+ authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE);
try {
repository.delete(id);
+ publishRules(oldEntity.getApp());
} catch (Throwable throwable) {
logger.error("delete error:", throwable);
return Result.ofThrowable(-1, throwable);
}
- if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
- logger.info("publish degrade rules fail after rule delete");
- }
return Result.ofSuccess(id);
}
- private boolean publishRules(String app, String ip, Integer port) {
- List rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
- return sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules);
+// private boolean publishRules(String app, String ip, Integer port) {
+// List rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
+// return sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules);
+// }
+
+ private void publishRules(/*@NonNull*/ String app) throws Exception {
+ List rules = repository.findAllByApp(app);
+ rulePublisher.publish(app, rules);
}
}
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/FlowControllerV1.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/FlowControllerV1.java
index 50c4e32f66..803a68ffe0 100755
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/FlowControllerV1.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/FlowControllerV1.java
@@ -15,22 +15,18 @@
*/
package com.alibaba.csp.sentinel.dashboard.controller;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-
-import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.AuthUser;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
-import com.alibaba.csp.sentinel.util.StringUtil;
-
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemoryRuleRepositoryAdapter;
-
+import com.alibaba.csp.sentinel.util.StringUtil;
+import java.util.Date;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -57,15 +53,17 @@ public class FlowControllerV1 {
@Autowired
private InMemoryRuleRepositoryAdapter repository;
+ @Autowired
+ private AuthService authService;
@Autowired
private SentinelApiClient sentinelApiClient;
@GetMapping("/rules")
- @AuthAction(PrivilegeType.READ_RULE)
- public Result> apiQueryMachineRules(@RequestParam String app,
- @RequestParam String ip,
- @RequestParam Integer port) {
+ public Result> apiQueryMachineRules(HttpServletRequest request, @RequestParam String app,
+ @RequestParam String ip, @RequestParam Integer port) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.READ_RULE);
if (StringUtil.isEmpty(app)) {
return Result.ofFail(-1, "app can't be null or empty");
@@ -134,8 +132,10 @@ private Result checkEntityInternal(FlowRuleEntity entity) {
}
@PostMapping("/rule")
- @AuthAction(PrivilegeType.WRITE_RULE)
- public Result apiAddFlowRule(@RequestBody FlowRuleEntity entity) {
+ public Result apiAddFlowRule(HttpServletRequest request, @RequestBody FlowRuleEntity entity) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE);
+
Result checkResult = checkEntityInternal(entity);
if (checkResult != null) {
return checkResult;
@@ -148,23 +148,23 @@ public Result apiAddFlowRule(@RequestBody FlowRuleEntity entity)
entity.setResource(entity.getResource().trim());
try {
entity = repository.save(entity);
-
- publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get(5000, TimeUnit.MILLISECONDS);
- return Result.ofSuccess(entity);
- } catch (Throwable t) {
- Throwable e = t instanceof ExecutionException ? t.getCause() : t;
- logger.error("Failed to add new flow rule, app={}, ip={}", entity.getApp(), entity.getIp(), e);
- return Result.ofFail(-1, e.getMessage());
+ } catch (Throwable throwable) {
+ logger.error("Failed to add flow rule", throwable);
+ return Result.ofThrowable(-1, throwable);
}
+ if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
+ logger.error("Publish flow rules failed after rule add");
+ }
+ return Result.ofSuccess(entity);
}
@PutMapping("/save.json")
- @AuthAction(PrivilegeType.WRITE_RULE)
- public Result apiUpdateFlowRule(Long id, String app,
- String limitApp, String resource, Integer grade,
- Double count, Integer strategy, String refResource,
- Integer controlBehavior, Integer warmUpPeriodSec,
- Integer maxQueueingTimeMs) {
+ public Result updateIfNotNull(HttpServletRequest request, Long id, String app, String limitApp,
+ String resource, Integer grade, Double count, Integer strategy, String refResource, Integer controlBehavior,
+ Integer warmUpPeriodSec, Integer maxQueueingTimeMs) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.WRITE_RULE);
+
if (id == null) {
return Result.ofFail(-1, "id can't be null");
}
@@ -225,23 +225,21 @@ public Result apiUpdateFlowRule(Long id, String app,
try {
entity = repository.save(entity);
if (entity == null) {
- return Result.ofFail(-1, "save entity fail: null");
+ return Result.ofFail(-1, "save entity fail");
}
-
- publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get(5000, TimeUnit.MILLISECONDS);
- return Result.ofSuccess(entity);
- } catch (Throwable t) {
- Throwable e = t instanceof ExecutionException ? t.getCause() : t;
- logger.error("Error when updating flow rules, app={}, ip={}, ruleId={}", entity.getApp(),
- entity.getIp(), id, e);
- return Result.ofFail(-1, e.getMessage());
+ } catch (Throwable throwable) {
+ logger.error("save error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
+ logger.info("publish flow rules fail after rule update");
}
+ return Result.ofSuccess(entity);
}
@DeleteMapping("/delete.json")
- @AuthAction(PrivilegeType.WRITE_RULE)
- public Result apiDeleteFlowRule(Long id) {
-
+ public Result delete(HttpServletRequest request, Long id) {
+ AuthUser authUser = authService.getAuthUser(request);
if (id == null) {
return Result.ofFail(-1, "id can't be null");
}
@@ -249,25 +247,20 @@ public Result apiDeleteFlowRule(Long id) {
if (oldEntity == null) {
return Result.ofSuccess(null);
}
-
+ authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE);
try {
repository.delete(id);
} catch (Exception e) {
return Result.ofFail(-1, e.getMessage());
}
- try {
- publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort()).get(5000, TimeUnit.MILLISECONDS);
- return Result.ofSuccess(id);
- } catch (Throwable t) {
- Throwable e = t instanceof ExecutionException ? t.getCause() : t;
- logger.error("Error when deleting flow rules, app={}, ip={}, id={}", oldEntity.getApp(),
- oldEntity.getIp(), id, e);
- return Result.ofFail(-1, e.getMessage());
+ if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
+ logger.info("publish flow rules fail after rule delete");
}
+ return Result.ofSuccess(id);
}
- private CompletableFuture publishRules(String app, String ip, Integer port) {
+ private boolean publishRules(String app, String ip, Integer port) {
List rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
- return sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules);
+ return sentinelApiClient.setFlowRuleOfMachine(app, ip, port, rules);
}
}
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java
index 9a9a7f76a4..98ad3434ad 100755
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java
@@ -60,7 +60,6 @@ public Result> receiveHeartBeat(String app, @RequestParam(value = "app_type",
try {
MachineInfo machineInfo = new MachineInfo();
machineInfo.setApp(app);
- machineInfo.setAppType(appType);
machineInfo.setHostname(hostname);
machineInfo.setIp(ip);
machineInfo.setPort(port);
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ParamFlowRuleController.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ParamFlowRuleController.java
index 4039ca6746..a2543280f2 100644
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ParamFlowRuleController.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ParamFlowRuleController.java
@@ -15,30 +15,30 @@
*/
package com.alibaba.csp.sentinel.dashboard.controller;
-import java.util.Date;
-import java.util.List;
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-
-import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
-import com.alibaba.csp.sentinel.dashboard.client.CommandNotFoundException;
-import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
-import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
-import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.AuthUser;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
-import com.alibaba.csp.sentinel.slots.block.RuleConstant;
-import com.alibaba.csp.sentinel.util.StringUtil;
+import com.alibaba.csp.sentinel.dashboard.client.CommandNotFoundException;
+import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.SentinelVersion;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
+import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
import com.alibaba.csp.sentinel.dashboard.util.VersionUtils;
-
+import com.alibaba.csp.sentinel.slots.block.RuleConstant;
+import com.alibaba.csp.sentinel.util.StringUtil;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -65,6 +65,10 @@ public class ParamFlowRuleController {
private AppManagement appManagement;
@Autowired
private RuleRepository repository;
+ @Autowired
+ private AuthService authService;
+ @Value("${auth.admin.username}")
+ private String adminUsername;
private boolean checkIfSupported(String app, String ip, int port) {
try {
@@ -80,10 +84,10 @@ private boolean checkIfSupported(String app, String ip, int port) {
}
@GetMapping("/rules")
- @AuthAction(PrivilegeType.READ_RULE)
- public Result> apiQueryAllRulesForMachine(@RequestParam String app,
- @RequestParam String ip,
- @RequestParam Integer port) {
+ public Result> apiQueryAllRulesForMachine(HttpServletRequest request,
+ @RequestParam String app, @RequestParam String ip, @RequestParam Integer port) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.READ_RULE);
if (StringUtil.isEmpty(app)) {
return Result.ofFail(-1, "app cannot be null or empty");
}
@@ -119,8 +123,13 @@ private boolean isNotSupported(Throwable ex) {
}
@PostMapping("/rule")
- @AuthAction(AuthService.PrivilegeType.WRITE_RULE)
- public Result apiAddParamFlowRule(@RequestBody ParamFlowRuleEntity entity) {
+ public Result apiAddParamFlowRule(HttpServletRequest request,
+ @RequestBody ParamFlowRuleEntity entity) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (!adminUsername.equals(authUser.getLoginName())) {
+ return Result.ofFail(-2, "您不是管理员,没有该权限!");
+ }
+ authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE);
Result checkResult = checkEntityInternal(entity);
if (checkResult != null) {
return checkResult;
@@ -188,9 +197,12 @@ private Result checkEntityInternal(ParamFlowRuleEntity entity) {
}
@PutMapping("/rule/{id}")
- @AuthAction(AuthService.PrivilegeType.WRITE_RULE)
- public Result apiUpdateParamFlowRule(@PathVariable("id") Long id,
- @RequestBody ParamFlowRuleEntity entity) {
+ public Result apiUpdateParamFlowRule(HttpServletRequest request, @PathVariable("id") Long id,
+ @RequestBody ParamFlowRuleEntity entity) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (!adminUsername.equals(authUser.getLoginName())) {
+ return Result.ofFail(-2, "您不是管理员,没有该权限!");
+ }
if (id == null || id <= 0) {
return Result.ofFail(-1, "Invalid id");
}
@@ -198,7 +210,7 @@ public Result apiUpdateParamFlowRule(@PathVariable("id") Lo
if (oldEntity == null) {
return Result.ofFail(-1, "id " + id + " does not exist");
}
-
+ authUser.authTarget(oldEntity.getApp(), PrivilegeType.WRITE_RULE);
Result checkResult = checkEntityInternal(entity);
if (checkResult != null) {
return checkResult;
@@ -228,8 +240,11 @@ public Result apiUpdateParamFlowRule(@PathVariable("id") Lo
}
@DeleteMapping("/rule/{id}")
- @AuthAction(PrivilegeType.DELETE_RULE)
- public Result apiDeleteRule(@PathVariable("id") Long id) {
+ public Result apiDeleteRule(HttpServletRequest request, @PathVariable("id") Long id) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (!adminUsername.equals(authUser.getLoginName())) {
+ return Result.ofFail(-2, "您不是管理员,没有该权限!");
+ }
if (id == null) {
return Result.ofFail(-1, "id cannot be null");
}
@@ -237,7 +252,7 @@ public Result apiDeleteRule(@PathVariable("id") Long id) {
if (oldEntity == null) {
return Result.ofSuccess(null);
}
-
+ authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE);
try {
repository.delete(id);
publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort()).get();
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/SystemController.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/SystemController.java
index daa0b98b5a..c87ea41c6a 100755
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/SystemController.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/SystemController.java
@@ -15,41 +15,51 @@
*/
package com.alibaba.csp.sentinel.dashboard.controller;
-import java.util.Date;
-import java.util.List;
-
-import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.AuthUser;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
-import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
-import com.alibaba.csp.sentinel.util.StringUtil;
-
+import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity;
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
-import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.domain.Result;
-
+import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemSystemRuleStore;
+import com.alibaba.csp.sentinel.util.StringUtil;
+import java.util.Date;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author leyou(lihao)
*/
-@RestController
-@RequestMapping("/system")
+@Controller
+@RequestMapping(value = "/system", produces = MediaType.APPLICATION_JSON_VALUE)
public class SystemController {
- private final Logger logger = LoggerFactory.getLogger(SystemController.class);
+ private static Logger logger = LoggerFactory.getLogger(SystemController.class);
@Autowired
- private RuleRepository repository;
+ private InMemSystemRuleStore repository;
@Autowired
private SentinelApiClient sentinelApiClient;
+ @Autowired
+ private AuthService authService;
- private Result checkBasicParams(String app, String ip, Integer port) {
+ @Value("${auth.admin.username}")
+ private String adminUsername;
+
+ @ResponseBody
+ @RequestMapping("/rules.json")
+ Result> queryMachineRules(HttpServletRequest request, String app, String ip, Integer port) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.READ_RULE);
if (StringUtil.isEmpty(app)) {
return Result.ofFail(-1, "app can't be null or empty");
}
@@ -59,26 +69,12 @@ private Result checkBasicParams(String app, String ip, Integer port) {
if (port == null) {
return Result.ofFail(-1, "port can't be null");
}
- if (port <= 0 || port > 65535) {
- return Result.ofFail(-1, "port should be in (0, 65535)");
- }
- return null;
- }
-
- @GetMapping("/rules.json")
- @AuthAction(PrivilegeType.READ_RULE)
- public Result> apiQueryMachineRules(String app, String ip,
- Integer port) {
- Result> checkResult = checkBasicParams(app, ip, port);
- if (checkResult != null) {
- return checkResult;
- }
try {
List rules = sentinelApiClient.fetchSystemRuleOfMachine(app, ip, port);
rules = repository.saveAll(rules);
return Result.ofSuccess(rules);
} catch (Throwable throwable) {
- logger.error("Query machine system rules error", throwable);
+ logger.error("queryApps error:", throwable);
return Result.ofThrowable(-1, throwable);
}
}
@@ -93,42 +89,40 @@ private int countNotNullAndNotNegative(Number... values) {
return notNullCount;
}
+ @ResponseBody
@RequestMapping("/new.json")
- @AuthAction(PrivilegeType.WRITE_RULE)
- public Result apiAdd(String app, String ip, Integer port,
- Double highestSystemLoad, Double highestCpuUsage, Long avgRt,
- Long maxThread, Double qps) {
-
- Result checkResult = checkBasicParams(app, ip, port);
- if (checkResult != null) {
- return checkResult;
+ Result> add(HttpServletRequest request, String app, String ip, Integer port, Double avgLoad, Long avgRt,
+ Long maxThread, Double qps) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (!adminUsername.equals(authUser.getLoginName())) {
+ return Result.ofFail(-2, "您不是管理员,没有该权限!");
+ }
+ authUser.authTarget(app, PrivilegeType.WRITE_RULE);
+ if (StringUtil.isBlank(app)) {
+ return Result.ofFail(-1, "app can't be null or empty");
}
-
- int notNullCount = countNotNullAndNotNegative(highestSystemLoad, avgRt, maxThread, qps, highestCpuUsage);
- if (notNullCount != 1) {
- return Result.ofFail(-1, "only one of [highestSystemLoad, avgRt, maxThread, qps,highestCpuUsage] "
- + "value must be set > 0, but " + notNullCount + " values get");
+ if (StringUtil.isBlank(ip)) {
+ return Result.ofFail(-1, "ip can't be null or empty");
}
- if (null != highestCpuUsage && highestCpuUsage > 1) {
- return Result.ofFail(-1, "highestCpuUsage must between [0.0, 1.0]");
+ if (port == null) {
+ return Result.ofFail(-1, "port can't be null");
+ }
+ int notNullCount = countNotNullAndNotNegative(avgLoad, avgRt, maxThread, qps);
+ if (notNullCount != 1) {
+ return Result.ofFail(-1,
+ "only one of [avgLoad, avgRt, maxThread, qps] " + "value must be set >= 0, but " + notNullCount
+ + " values get");
}
SystemRuleEntity entity = new SystemRuleEntity();
entity.setApp(app.trim());
entity.setIp(ip.trim());
entity.setPort(port);
// -1 is a fake value
- if (null != highestSystemLoad) {
- entity.setHighestSystemLoad(highestSystemLoad);
- } else {
- entity.setHighestSystemLoad(-1D);
- }
-
- if (null != highestCpuUsage) {
- entity.setHighestCpuUsage(highestCpuUsage);
+ if (avgLoad != null) {
+ entity.setAvgLoad(avgLoad);
} else {
- entity.setHighestCpuUsage(-1D);
+ entity.setAvgLoad(-1D);
}
-
if (avgRt != null) {
entity.setAvgRt(avgRt);
} else {
@@ -150,19 +144,23 @@ public Result apiAdd(String app, String ip, Integer port,
try {
entity = repository.save(entity);
} catch (Throwable throwable) {
- logger.error("Add SystemRule error", throwable);
+ logger.error("add error:", throwable);
return Result.ofThrowable(-1, throwable);
}
if (!publishRules(app, ip, port)) {
- logger.warn("Publish system rules fail after rule add");
+ logger.info("publish system rules fail after rule add");
}
return Result.ofSuccess(entity);
}
- @GetMapping("/save.json")
- @AuthAction(PrivilegeType.WRITE_RULE)
- public Result apiUpdateIfNotNull(Long id, String app, Double highestSystemLoad,
- Double highestCpuUsage, Long avgRt, Long maxThread, Double qps) {
+ @ResponseBody
+ @RequestMapping("/save.json")
+ Result> updateIfNotNull(HttpServletRequest request, Long id, String app, Double avgLoad, Long avgRt,
+ Long maxThread, Double qps) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (!adminUsername.equals(authUser.getLoginName())) {
+ return Result.ofFail(-2, "您不是管理员,没有该权限!");
+ }
if (id == null) {
return Result.ofFail(-1, "id can't be null");
}
@@ -170,24 +168,15 @@ public Result apiUpdateIfNotNull(Long id, String app, Double h
if (entity == null) {
return Result.ofFail(-1, "id " + id + " dose not exist");
}
-
+ authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE);
if (StringUtil.isNotBlank(app)) {
entity.setApp(app.trim());
}
- if (highestSystemLoad != null) {
- if (highestSystemLoad < 0) {
- return Result.ofFail(-1, "highestSystemLoad must >= 0");
+ if (avgLoad != null) {
+ if (avgLoad < 0) {
+ return Result.ofFail(-1, "avgLoad must >= 0");
}
- entity.setHighestSystemLoad(highestSystemLoad);
- }
- if (highestCpuUsage != null) {
- if (highestCpuUsage < 0) {
- return Result.ofFail(-1, "highestCpuUsage must >= 0");
- }
- if (highestCpuUsage > 1) {
- return Result.ofFail(-1, "highestCpuUsage must <= 1");
- }
- entity.setHighestCpuUsage(highestCpuUsage);
+ entity.setAvgLoad(avgLoad);
}
if (avgRt != null) {
if (avgRt < 0) {
@@ -221,9 +210,13 @@ public Result apiUpdateIfNotNull(Long id, String app, Double h
return Result.ofSuccess(entity);
}
+ @ResponseBody
@RequestMapping("/delete.json")
- @AuthAction(PrivilegeType.DELETE_RULE)
- public Result> delete(Long id) {
+ Result> delete(HttpServletRequest request, Long id) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (!adminUsername.equals(authUser.getLoginName())) {
+ return Result.ofFail(-2, "您不是管理员,没有该权限!");
+ }
if (id == null) {
return Result.ofFail(-1, "id can't be null");
}
@@ -231,6 +224,7 @@ public Result> delete(Long id) {
if (oldEntity == null) {
return Result.ofSuccess(null);
}
+ authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE);
try {
repository.delete(id);
} catch (Throwable throwable) {
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayApiController.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayApiController.java
deleted file mode 100644
index c7a405d9c4..0000000000
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayApiController.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright 1999-2018 Alibaba Group Holding Ltd.
- *
- * 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 com.alibaba.csp.sentinel.dashboard.controller.gateway;
-
-import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
-import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
-import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
-import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity;
-import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiPredicateItemEntity;
-import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
-import com.alibaba.csp.sentinel.dashboard.domain.Result;
-import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.AddApiReqVo;
-import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.ApiPredicateItemVo;
-import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.UpdateApiReqVo;
-import com.alibaba.csp.sentinel.dashboard.repository.gateway.InMemApiDefinitionStore;
-import com.alibaba.csp.sentinel.util.StringUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.bind.annotation.*;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.*;
-
-import static com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants.*;
-
-/**
- * Gateway api Controller for manage gateway api definitions.
- *
- * @author cdfive
- * @since 1.7.0
- */
-@RestController
-@RequestMapping(value = "/gateway/api")
-public class GatewayApiController {
-
- private final Logger logger = LoggerFactory.getLogger(GatewayApiController.class);
-
- @Autowired
- private InMemApiDefinitionStore repository;
-
- @Autowired
- private SentinelApiClient sentinelApiClient;
-
- @GetMapping("/list.json")
- @AuthAction(AuthService.PrivilegeType.READ_RULE)
- public Result> queryApis(String app, String ip, Integer port) {
-
- if (StringUtil.isEmpty(app)) {
- return Result.ofFail(-1, "app can't be null or empty");
- }
- if (StringUtil.isEmpty(ip)) {
- return Result.ofFail(-1, "ip can't be null or empty");
- }
- if (port == null) {
- return Result.ofFail(-1, "port can't be null");
- }
-
- try {
- List apis = sentinelApiClient.fetchApis(app, ip, port).get();
- repository.saveAll(apis);
- return Result.ofSuccess(apis);
- } catch (Throwable throwable) {
- logger.error("queryApis error:", throwable);
- return Result.ofThrowable(-1, throwable);
- }
- }
-
- @PostMapping("/new.json")
- @AuthAction(AuthService.PrivilegeType.WRITE_RULE)
- public Result addApi(HttpServletRequest request, @RequestBody AddApiReqVo reqVo) {
-
- String app = reqVo.getApp();
- if (StringUtil.isBlank(app)) {
- return Result.ofFail(-1, "app can't be null or empty");
- }
-
- ApiDefinitionEntity entity = new ApiDefinitionEntity();
- entity.setApp(app.trim());
-
- String ip = reqVo.getIp();
- if (StringUtil.isBlank(ip)) {
- return Result.ofFail(-1, "ip can't be null or empty");
- }
- entity.setIp(ip.trim());
-
- Integer port = reqVo.getPort();
- if (port == null) {
- return Result.ofFail(-1, "port can't be null");
- }
- entity.setPort(port);
-
- // API名称
- String apiName = reqVo.getApiName();
- if (StringUtil.isBlank(apiName)) {
- return Result.ofFail(-1, "apiName can't be null or empty");
- }
- entity.setApiName(apiName.trim());
-
- // 匹配规则列表
- List predicateItems = reqVo.getPredicateItems();
- if (CollectionUtils.isEmpty(predicateItems)) {
- return Result.ofFail(-1, "predicateItems can't empty");
- }
-
- List predicateItemEntities = new ArrayList<>();
- for (ApiPredicateItemVo predicateItem : predicateItems) {
- ApiPredicateItemEntity predicateItemEntity = new ApiPredicateItemEntity();
-
- // 匹配模式
- Integer matchStrategy = predicateItem.getMatchStrategy();
- if (!Arrays.asList(URL_MATCH_STRATEGY_EXACT, URL_MATCH_STRATEGY_PREFIX, URL_MATCH_STRATEGY_REGEX).contains(matchStrategy)) {
- return Result.ofFail(-1, "invalid matchStrategy: " + matchStrategy);
- }
- predicateItemEntity.setMatchStrategy(matchStrategy);
-
- // 匹配串
- String pattern = predicateItem.getPattern();
- if (StringUtil.isBlank(pattern)) {
- return Result.ofFail(-1, "pattern can't be null or empty");
- }
- predicateItemEntity.setPattern(pattern);
-
- predicateItemEntities.add(predicateItemEntity);
- }
- entity.setPredicateItems(new LinkedHashSet<>(predicateItemEntities));
-
- // 检查API名称不能重复
- List allApis = repository.findAllByMachine(MachineInfo.of(app.trim(), ip.trim(), port));
- if (allApis.stream().map(o -> o.getApiName()).anyMatch(o -> o.equals(apiName.trim()))) {
- return Result.ofFail(-1, "apiName exists: " + apiName);
- }
-
- Date date = new Date();
- entity.setGmtCreate(date);
- entity.setGmtModified(date);
-
- try {
- entity = repository.save(entity);
- } catch (Throwable throwable) {
- logger.error("add gateway api error:", throwable);
- return Result.ofThrowable(-1, throwable);
- }
-
- if (!publishApis(app, ip, port)) {
- logger.warn("publish gateway apis fail after add");
- }
-
- return Result.ofSuccess(entity);
- }
-
- @PostMapping("/save.json")
- @AuthAction(AuthService.PrivilegeType.WRITE_RULE)
- public Result updateApi(@RequestBody UpdateApiReqVo reqVo) {
- String app = reqVo.getApp();
- if (StringUtil.isBlank(app)) {
- return Result.ofFail(-1, "app can't be null or empty");
- }
-
- Long id = reqVo.getId();
- if (id == null) {
- return Result.ofFail(-1, "id can't be null");
- }
-
- ApiDefinitionEntity entity = repository.findById(id);
- if (entity == null) {
- return Result.ofFail(-1, "api does not exist, id=" + id);
- }
-
- // 匹配规则列表
- List predicateItems = reqVo.getPredicateItems();
- if (CollectionUtils.isEmpty(predicateItems)) {
- return Result.ofFail(-1, "predicateItems can't empty");
- }
-
- List predicateItemEntities = new ArrayList<>();
- for (ApiPredicateItemVo predicateItem : predicateItems) {
- ApiPredicateItemEntity predicateItemEntity = new ApiPredicateItemEntity();
-
- // 匹配模式
- int matchStrategy = predicateItem.getMatchStrategy();
- if (!Arrays.asList(URL_MATCH_STRATEGY_EXACT, URL_MATCH_STRATEGY_PREFIX, URL_MATCH_STRATEGY_REGEX).contains(matchStrategy)) {
- return Result.ofFail(-1, "Invalid matchStrategy: " + matchStrategy);
- }
- predicateItemEntity.setMatchStrategy(matchStrategy);
-
- // 匹配串
- String pattern = predicateItem.getPattern();
- if (StringUtil.isBlank(pattern)) {
- return Result.ofFail(-1, "pattern can't be null or empty");
- }
- predicateItemEntity.setPattern(pattern);
-
- predicateItemEntities.add(predicateItemEntity);
- }
- entity.setPredicateItems(new LinkedHashSet<>(predicateItemEntities));
-
- Date date = new Date();
- entity.setGmtModified(date);
-
- try {
- entity = repository.save(entity);
- } catch (Throwable throwable) {
- logger.error("update gateway api error:", throwable);
- return Result.ofThrowable(-1, throwable);
- }
-
- if (!publishApis(app, entity.getIp(), entity.getPort())) {
- logger.warn("publish gateway apis fail after update");
- }
-
- return Result.ofSuccess(entity);
- }
-
- @PostMapping("/delete.json")
- @AuthAction(AuthService.PrivilegeType.DELETE_RULE)
-
- public Result deleteApi(Long id) {
- if (id == null) {
- return Result.ofFail(-1, "id can't be null");
- }
-
- ApiDefinitionEntity oldEntity = repository.findById(id);
- if (oldEntity == null) {
- return Result.ofSuccess(null);
- }
-
- try {
- repository.delete(id);
- } catch (Throwable throwable) {
- logger.error("delete gateway api error:", throwable);
- return Result.ofThrowable(-1, throwable);
- }
-
- if (!publishApis(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
- logger.warn("publish gateway apis fail after delete");
- }
-
- return Result.ofSuccess(id);
- }
-
- private boolean publishApis(String app, String ip, Integer port) {
- List apis = repository.findAllByMachine(MachineInfo.of(app, ip, port));
- return sentinelApiClient.modifyApis(app, ip, port, apis);
- }
-}
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayFlowRuleController.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayFlowRuleController.java
deleted file mode 100644
index 0189163781..0000000000
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayFlowRuleController.java
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * Copyright 1999-2018 Alibaba Group Holding Ltd.
- *
- * 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 com.alibaba.csp.sentinel.dashboard.controller.gateway;
-
-
-import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
-import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
-import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
-import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity;
-import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayParamFlowItemEntity;
-import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
-import com.alibaba.csp.sentinel.dashboard.domain.Result;
-import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.rule.AddFlowRuleReqVo;
-import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.rule.GatewayParamFlowItemVo;
-import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.rule.UpdateFlowRuleReqVo;
-import com.alibaba.csp.sentinel.dashboard.repository.gateway.InMemGatewayFlowRuleStore;
-import com.alibaba.csp.sentinel.util.StringUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-
-import static com.alibaba.csp.sentinel.slots.block.RuleConstant.*;
-import static com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants.*;
-import static com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity.*;
-
-/**
- * Gateway flow rule Controller for manage gateway flow rules.
- *
- * @author cdfive
- * @since 1.7.0
- */
-@RestController
-@RequestMapping(value = "/gateway/flow")
-public class GatewayFlowRuleController {
-
- private final Logger logger = LoggerFactory.getLogger(GatewayFlowRuleController.class);
-
- @Autowired
- private InMemGatewayFlowRuleStore repository;
-
- @Autowired
- private SentinelApiClient sentinelApiClient;
-
- @GetMapping("/list.json")
- @AuthAction(AuthService.PrivilegeType.READ_RULE)
- public Result> queryFlowRules(String app, String ip, Integer port) {
-
- if (StringUtil.isEmpty(app)) {
- return Result.ofFail(-1, "app can't be null or empty");
- }
- if (StringUtil.isEmpty(ip)) {
- return Result.ofFail(-1, "ip can't be null or empty");
- }
- if (port == null) {
- return Result.ofFail(-1, "port can't be null");
- }
-
- try {
- List rules = sentinelApiClient.fetchGatewayFlowRules(app, ip, port).get();
- repository.saveAll(rules);
- return Result.ofSuccess(rules);
- } catch (Throwable throwable) {
- logger.error("query gateway flow rules error:", throwable);
- return Result.ofThrowable(-1, throwable);
- }
- }
-
- @PostMapping("/new.json")
- @AuthAction(AuthService.PrivilegeType.WRITE_RULE)
- public Result addFlowRule(@RequestBody AddFlowRuleReqVo reqVo) {
-
- String app = reqVo.getApp();
- if (StringUtil.isBlank(app)) {
- return Result.ofFail(-1, "app can't be null or empty");
- }
-
- GatewayFlowRuleEntity entity = new GatewayFlowRuleEntity();
- entity.setApp(app.trim());
-
- String ip = reqVo.getIp();
- if (StringUtil.isBlank(ip)) {
- return Result.ofFail(-1, "ip can't be null or empty");
- }
- entity.setIp(ip.trim());
-
- Integer port = reqVo.getPort();
- if (port == null) {
- return Result.ofFail(-1, "port can't be null");
- }
- entity.setPort(port);
-
- // API类型, Route ID或API分组
- Integer resourceMode = reqVo.getResourceMode();
- if (resourceMode == null) {
- return Result.ofFail(-1, "resourceMode can't be null");
- }
- if (!Arrays.asList(RESOURCE_MODE_ROUTE_ID, RESOURCE_MODE_CUSTOM_API_NAME).contains(resourceMode)) {
- return Result.ofFail(-1, "invalid resourceMode: " + resourceMode);
- }
- entity.setResourceMode(resourceMode);
-
- // API名称
- String resource = reqVo.getResource();
- if (StringUtil.isBlank(resource)) {
- return Result.ofFail(-1, "resource can't be null or empty");
- }
- entity.setResource(resource.trim());
-
- // 针对请求属性
- GatewayParamFlowItemVo paramItem = reqVo.getParamItem();
- if (paramItem != null) {
- GatewayParamFlowItemEntity itemEntity = new GatewayParamFlowItemEntity();
- entity.setParamItem(itemEntity);
-
- // 参数属性 0-ClientIP 1-Remote Host 2-Header 3-URL参数 4-Cookie
- Integer parseStrategy = paramItem.getParseStrategy();
- if (!Arrays.asList(PARAM_PARSE_STRATEGY_CLIENT_IP, PARAM_PARSE_STRATEGY_HOST, PARAM_PARSE_STRATEGY_HEADER
- , PARAM_PARSE_STRATEGY_URL_PARAM, PARAM_PARSE_STRATEGY_COOKIE).contains(parseStrategy)) {
- return Result.ofFail(-1, "invalid parseStrategy: " + parseStrategy);
- }
- itemEntity.setParseStrategy(paramItem.getParseStrategy());
-
- // 当参数属性为2-Header 3-URL参数 4-Cookie时,参数名称必填
- if (Arrays.asList(PARAM_PARSE_STRATEGY_HEADER, PARAM_PARSE_STRATEGY_URL_PARAM, PARAM_PARSE_STRATEGY_COOKIE).contains(parseStrategy)) {
- // 参数名称
- String fieldName = paramItem.getFieldName();
- if (StringUtil.isBlank(fieldName)) {
- return Result.ofFail(-1, "fieldName can't be null or empty");
- }
- itemEntity.setFieldName(paramItem.getFieldName());
-
- String pattern = paramItem.getPattern();
- // 如果匹配串不为空,验证匹配模式
- if (StringUtil.isNotEmpty(pattern)) {
- itemEntity.setPattern(pattern);
-
- Integer matchStrategy = paramItem.getMatchStrategy();
- if (!Arrays.asList(PARAM_MATCH_STRATEGY_EXACT, PARAM_MATCH_STRATEGY_CONTAINS, PARAM_MATCH_STRATEGY_REGEX).contains(matchStrategy)) {
- return Result.ofFail(-1, "invalid matchStrategy: " + matchStrategy);
- }
- itemEntity.setMatchStrategy(matchStrategy);
- }
- }
- }
-
- // 阈值类型 0-线程数 1-QPS
- Integer grade = reqVo.getGrade();
- if (grade == null) {
- return Result.ofFail(-1, "grade can't be null");
- }
- if (!Arrays.asList(FLOW_GRADE_THREAD, FLOW_GRADE_QPS).contains(grade)) {
- return Result.ofFail(-1, "invalid grade: " + grade);
- }
- entity.setGrade(grade);
-
- // QPS阈值
- Double count = reqVo.getCount();
- if (count == null) {
- return Result.ofFail(-1, "count can't be null");
- }
- if (count < 0) {
- return Result.ofFail(-1, "count should be at lease zero");
- }
- entity.setCount(count);
-
- // 间隔
- Long interval = reqVo.getInterval();
- if (interval == null) {
- return Result.ofFail(-1, "interval can't be null");
- }
- if (interval <= 0) {
- return Result.ofFail(-1, "interval should be greater than zero");
- }
- entity.setInterval(interval);
-
- // 间隔单位
- Integer intervalUnit = reqVo.getIntervalUnit();
- if (intervalUnit == null) {
- return Result.ofFail(-1, "intervalUnit can't be null");
- }
- if (!Arrays.asList(INTERVAL_UNIT_SECOND, INTERVAL_UNIT_MINUTE, INTERVAL_UNIT_HOUR, INTERVAL_UNIT_DAY).contains(intervalUnit)) {
- return Result.ofFail(-1, "Invalid intervalUnit: " + intervalUnit);
- }
- entity.setIntervalUnit(intervalUnit);
-
- // 流控方式 0-快速失败 2-匀速排队
- Integer controlBehavior = reqVo.getControlBehavior();
- if (controlBehavior == null) {
- return Result.ofFail(-1, "controlBehavior can't be null");
- }
- if (!Arrays.asList(CONTROL_BEHAVIOR_DEFAULT, CONTROL_BEHAVIOR_RATE_LIMITER).contains(controlBehavior)) {
- return Result.ofFail(-1, "invalid controlBehavior: " + controlBehavior);
- }
- entity.setControlBehavior(controlBehavior);
-
- if (CONTROL_BEHAVIOR_DEFAULT == controlBehavior) {
- // 0-快速失败, 则Burst size必填
- Integer burst = reqVo.getBurst();
- if (burst == null) {
- return Result.ofFail(-1, "burst can't be null");
- }
- if (burst < 0) {
- return Result.ofFail(-1, "invalid burst: " + burst);
- }
- entity.setBurst(burst);
- } else if (CONTROL_BEHAVIOR_RATE_LIMITER == controlBehavior) {
- // 1-匀速排队, 则超时时间必填
- Integer maxQueueingTimeoutMs = reqVo.getMaxQueueingTimeoutMs();
- if (maxQueueingTimeoutMs == null) {
- return Result.ofFail(-1, "maxQueueingTimeoutMs can't be null");
- }
- if (maxQueueingTimeoutMs < 0) {
- return Result.ofFail(-1, "invalid maxQueueingTimeoutMs: " + maxQueueingTimeoutMs);
- }
- entity.setMaxQueueingTimeoutMs(maxQueueingTimeoutMs);
- }
-
- Date date = new Date();
- entity.setGmtCreate(date);
- entity.setGmtModified(date);
-
- try {
- entity = repository.save(entity);
- } catch (Throwable throwable) {
- logger.error("add gateway flow rule error:", throwable);
- return Result.ofThrowable(-1, throwable);
- }
-
- if (!publishRules(app, ip, port)) {
- logger.warn("publish gateway flow rules fail after add");
- }
-
- return Result.ofSuccess(entity);
- }
-
- @PostMapping("/save.json")
- @AuthAction(AuthService.PrivilegeType.WRITE_RULE)
- public Result updateFlowRule(@RequestBody UpdateFlowRuleReqVo reqVo) {
-
- String app = reqVo.getApp();
- if (StringUtil.isBlank(app)) {
- return Result.ofFail(-1, "app can't be null or empty");
- }
-
- Long id = reqVo.getId();
- if (id == null) {
- return Result.ofFail(-1, "id can't be null");
- }
-
- GatewayFlowRuleEntity entity = repository.findById(id);
- if (entity == null) {
- return Result.ofFail(-1, "gateway flow rule does not exist, id=" + id);
- }
-
- // 针对请求属性
- GatewayParamFlowItemVo paramItem = reqVo.getParamItem();
- if (paramItem != null) {
- GatewayParamFlowItemEntity itemEntity = new GatewayParamFlowItemEntity();
- entity.setParamItem(itemEntity);
-
- // 参数属性 0-ClientIP 1-Remote Host 2-Header 3-URL参数 4-Cookie
- Integer parseStrategy = paramItem.getParseStrategy();
- if (!Arrays.asList(PARAM_PARSE_STRATEGY_CLIENT_IP, PARAM_PARSE_STRATEGY_HOST, PARAM_PARSE_STRATEGY_HEADER
- , PARAM_PARSE_STRATEGY_URL_PARAM, PARAM_PARSE_STRATEGY_COOKIE).contains(parseStrategy)) {
- return Result.ofFail(-1, "invalid parseStrategy: " + parseStrategy);
- }
- itemEntity.setParseStrategy(paramItem.getParseStrategy());
-
- // 当参数属性为2-Header 3-URL参数 4-Cookie时,参数名称必填
- if (Arrays.asList(PARAM_PARSE_STRATEGY_HEADER, PARAM_PARSE_STRATEGY_URL_PARAM, PARAM_PARSE_STRATEGY_COOKIE).contains(parseStrategy)) {
- // 参数名称
- String fieldName = paramItem.getFieldName();
- if (StringUtil.isBlank(fieldName)) {
- return Result.ofFail(-1, "fieldName can't be null or empty");
- }
- itemEntity.setFieldName(paramItem.getFieldName());
-
- String pattern = paramItem.getPattern();
- // 如果匹配串不为空,验证匹配模式
- if (StringUtil.isNotEmpty(pattern)) {
- itemEntity.setPattern(pattern);
-
- Integer matchStrategy = paramItem.getMatchStrategy();
- if (!Arrays.asList(PARAM_MATCH_STRATEGY_EXACT, PARAM_MATCH_STRATEGY_CONTAINS, PARAM_MATCH_STRATEGY_REGEX).contains(matchStrategy)) {
- return Result.ofFail(-1, "invalid matchStrategy: " + matchStrategy);
- }
- itemEntity.setMatchStrategy(matchStrategy);
- }
- }
- } else {
- entity.setParamItem(null);
- }
-
- // 阈值类型 0-线程数 1-QPS
- Integer grade = reqVo.getGrade();
- if (grade == null) {
- return Result.ofFail(-1, "grade can't be null");
- }
- if (!Arrays.asList(FLOW_GRADE_THREAD, FLOW_GRADE_QPS).contains(grade)) {
- return Result.ofFail(-1, "invalid grade: " + grade);
- }
- entity.setGrade(grade);
-
- // QPS阈值
- Double count = reqVo.getCount();
- if (count == null) {
- return Result.ofFail(-1, "count can't be null");
- }
- if (count < 0) {
- return Result.ofFail(-1, "count should be at lease zero");
- }
- entity.setCount(count);
-
- // 间隔
- Long interval = reqVo.getInterval();
- if (interval == null) {
- return Result.ofFail(-1, "interval can't be null");
- }
- if (interval <= 0) {
- return Result.ofFail(-1, "interval should be greater than zero");
- }
- entity.setInterval(interval);
-
- // 间隔单位
- Integer intervalUnit = reqVo.getIntervalUnit();
- if (intervalUnit == null) {
- return Result.ofFail(-1, "intervalUnit can't be null");
- }
- if (!Arrays.asList(INTERVAL_UNIT_SECOND, INTERVAL_UNIT_MINUTE, INTERVAL_UNIT_HOUR, INTERVAL_UNIT_DAY).contains(intervalUnit)) {
- return Result.ofFail(-1, "Invalid intervalUnit: " + intervalUnit);
- }
- entity.setIntervalUnit(intervalUnit);
-
- // 流控方式 0-快速失败 2-匀速排队
- Integer controlBehavior = reqVo.getControlBehavior();
- if (controlBehavior == null) {
- return Result.ofFail(-1, "controlBehavior can't be null");
- }
- if (!Arrays.asList(CONTROL_BEHAVIOR_DEFAULT, CONTROL_BEHAVIOR_RATE_LIMITER).contains(controlBehavior)) {
- return Result.ofFail(-1, "invalid controlBehavior: " + controlBehavior);
- }
- entity.setControlBehavior(controlBehavior);
-
- if (CONTROL_BEHAVIOR_DEFAULT == controlBehavior) {
- // 0-快速失败, 则Burst size必填
- Integer burst = reqVo.getBurst();
- if (burst == null) {
- return Result.ofFail(-1, "burst can't be null");
- }
- if (burst < 0) {
- return Result.ofFail(-1, "invalid burst: " + burst);
- }
- entity.setBurst(burst);
- } else if (CONTROL_BEHAVIOR_RATE_LIMITER == controlBehavior) {
- // 2-匀速排队, 则超时时间必填
- Integer maxQueueingTimeoutMs = reqVo.getMaxQueueingTimeoutMs();
- if (maxQueueingTimeoutMs == null) {
- return Result.ofFail(-1, "maxQueueingTimeoutMs can't be null");
- }
- if (maxQueueingTimeoutMs < 0) {
- return Result.ofFail(-1, "invalid maxQueueingTimeoutMs: " + maxQueueingTimeoutMs);
- }
- entity.setMaxQueueingTimeoutMs(maxQueueingTimeoutMs);
- }
-
- Date date = new Date();
- entity.setGmtModified(date);
-
- try {
- entity = repository.save(entity);
- } catch (Throwable throwable) {
- logger.error("update gateway flow rule error:", throwable);
- return Result.ofThrowable(-1, throwable);
- }
-
- if (!publishRules(app, entity.getIp(), entity.getPort())) {
- logger.warn("publish gateway flow rules fail after update");
- }
-
- return Result.ofSuccess(entity);
- }
-
-
- @PostMapping("/delete.json")
- @AuthAction(AuthService.PrivilegeType.DELETE_RULE)
- public Result deleteFlowRule(Long id) {
-
- if (id == null) {
- return Result.ofFail(-1, "id can't be null");
- }
-
- GatewayFlowRuleEntity oldEntity = repository.findById(id);
- if (oldEntity == null) {
- return Result.ofSuccess(null);
- }
-
- try {
- repository.delete(id);
- } catch (Throwable throwable) {
- logger.error("delete gateway flow rule error:", throwable);
- return Result.ofThrowable(-1, throwable);
- }
-
- if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
- logger.warn("publish gateway flow rules fail after delete");
- }
-
- return Result.ofSuccess(id);
- }
-
- private boolean publishRules(String app, String ip, Integer port) {
- List rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
- return sentinelApiClient.modifyGatewayFlowRules(app, ip, port, rules);
- }
-}
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/SystemRuleEntity.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/SystemRuleEntity.java
index 483ebcb52f..478fe98086 100755
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/SystemRuleEntity.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/SystemRuleEntity.java
@@ -29,11 +29,10 @@ public class SystemRuleEntity implements RuleEntity {
private String app;
private String ip;
private Integer port;
- private Double highestSystemLoad;
+ private Double avgLoad;
private Long avgRt;
private Long maxThread;
private Double qps;
- private Double highestCpuUsage;
private Date gmtCreate;
private Date gmtModified;
@@ -43,8 +42,7 @@ public static SystemRuleEntity fromSystemRule(String app, String ip, Integer por
entity.setApp(app);
entity.setIp(ip);
entity.setPort(port);
- entity.setHighestSystemLoad(rule.getHighestSystemLoad());
- entity.setHighestCpuUsage(rule.getHighestCpuUsage());
+ entity.setAvgLoad(rule.getHighestSystemLoad());
entity.setAvgRt(rule.getAvgRt());
entity.setMaxThread(rule.getMaxThread());
entity.setQps(rule.getQps());
@@ -88,12 +86,12 @@ public void setApp(String app) {
this.app = app;
}
- public Double getHighestSystemLoad() {
- return highestSystemLoad;
+ public Double getAvgLoad() {
+ return avgLoad;
}
- public void setHighestSystemLoad(Double highestSystemLoad) {
- this.highestSystemLoad = highestSystemLoad;
+ public void setAvgLoad(Double avgLoad) {
+ this.avgLoad = avgLoad;
}
public Long getAvgRt() {
@@ -120,14 +118,6 @@ public void setQps(Double qps) {
this.qps = qps;
}
- public Double getHighestCpuUsage() {
- return highestCpuUsage;
- }
-
- public void setHighestCpuUsage(Double highestCpuUsage) {
- this.highestCpuUsage = highestCpuUsage;
- }
-
@Override
public Date getGmtCreate() {
return gmtCreate;
@@ -148,11 +138,10 @@ public void setGmtModified(Date gmtModified) {
@Override
public SystemRule toRule() {
SystemRule rule = new SystemRule();
- rule.setHighestSystemLoad(highestSystemLoad);
+ rule.setHighestSystemLoad(avgLoad);
rule.setAvgRt(avgRt);
rule.setMaxThread(maxThread);
rule.setQps(qps);
- rule.setHighestCpuUsage(highestCpuUsage);
return rule;
}
}
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/entity/rule/RuleEntity.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/entity/rule/RuleEntity.java
new file mode 100755
index 0000000000..43c756f194
--- /dev/null
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/entity/rule/RuleEntity.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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 com.alibaba.csp.sentinel.dashboard.entity.rule;
+
+import com.alibaba.csp.sentinel.slots.block.Rule;
+import java.util.Date;
+
+/**
+ * @author leyou
+ */
+public interface RuleEntity {
+
+ Long getId();
+
+ void setId(Long id);
+
+ String getApp();
+
+ String getIp();
+
+ Integer getPort();
+
+ Date getGmtCreate();
+
+ Rule toRule();
+}
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/filter/AuthFilter.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/filter/AuthFilter.java
new file mode 100644
index 0000000000..1a5c5f27a3
--- /dev/null
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/filter/AuthFilter.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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 com.alibaba.csp.sentinel.dashboard.filter;
+
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import java.io.IOException;
+import java.util.List;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+
+/**
+ * Servlet Filter that authenticate requests.
+ *
+ * Note: Some urls are excluded as they needn't auth, such as:
+ *
+ * Index url: / Authentication request url: /login,logout Used for client: /registry/machine Static resources:
+ * htm,html,js and so on.
+ *
+ * The excluded urls and urlSuffixes are configured in application.properties
+ *
+ * @author cdfive
+ * @since 1.6.0
+ */
+@Component
+public class AuthFilter implements Filter {
+
+ private static final String URL_SUFFIX_DOT = ".";
+
+ /**
+ * Some urls which needn't auth, such as /auth/login,/registry/machine and so on
+ */
+ @Value("#{'${auth.filter.exclude-urls}'.split(',')}")
+ private List authFilterExcludeUrls;
+
+ /**
+ * Some urls with suffixes which needn't auth, such as htm,html,js and so on
+ */
+ @Value("#{'${auth.filter.exclude-url-suffixes}'.split(',')}")
+ private List authFilterExcludeUrlSuffixes;
+
+ /**
+ * Authentication using AuthService interface
+ */
+ @Autowired
+ private AuthService authService;
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ HttpServletRequest httpRequest = (HttpServletRequest) request;
+
+ String requestURI = httpRequest.getRequestURI();
+
+ // Exclude the urls which needn't auth
+ if (authFilterExcludeUrls.contains(requestURI)) {
+ chain.doFilter(request, response);
+ return;
+ }
+
+ // Exclude the urls with suffixes which needn't auth
+ for (String authFilterExcludeUrlSuffix : authFilterExcludeUrlSuffixes) {
+ if (StringUtils.isBlank(authFilterExcludeUrlSuffix)) {
+ continue;
+ }
+
+ // Add . for url suffix so that we needn't add . in property file
+ if (!authFilterExcludeUrlSuffix.startsWith(URL_SUFFIX_DOT)) {
+ authFilterExcludeUrlSuffix = URL_SUFFIX_DOT + authFilterExcludeUrlSuffix;
+ }
+
+ if (requestURI.endsWith(authFilterExcludeUrlSuffix)) {
+ chain.doFilter(request, response);
+ return;
+ }
+ }
+
+ AuthService.AuthUser authUser = authService.getAuthUser(httpRequest);
+
+ HttpServletResponse httpResponse = (HttpServletResponse) response;
+ if (authUser == null) {
+ // If auth fail, set response status code to 401
+ httpResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
+ } else {
+ chain.doFilter(request, response);
+ }
+ }
+
+ @Override
+ public void destroy() {
+
+ }
+}
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/DegradeRuleZookeeperPublisher.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/DegradeRuleZookeeperPublisher.java
new file mode 100644
index 0000000000..0211f07fc1
--- /dev/null
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/DegradeRuleZookeeperPublisher.java
@@ -0,0 +1,43 @@
+package com.alibaba.csp.sentinel.dashboard.rule;
+
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
+import com.alibaba.csp.sentinel.datasource.Converter;
+import com.alibaba.csp.sentinel.util.AssertUtil;
+import java.util.List;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.data.Stat;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+
+@Component("degradeRuleZookeeperPublisher")
+public class DegradeRuleZookeeperPublisher implements DynamicRulePublisher> {
+
+ @Autowired
+ private CuratorFramework zkClient;
+ @Autowired
+ private Converter, String> converter;
+ @Autowired
+ private ZookeeperSentinelConfig zkConfig;
+
+ @Override
+ public void publish(String app, List rules) throws Exception {
+ AssertUtil.notEmpty(app, "app name cannot be empty");
+
+ String path = zkConfig.getDegradeRulePath(app);
+ Stat stat = zkClient.checkExists()
+ .forPath(path);
+ if (stat == null) {
+ zkClient.create()
+ .creatingParentContainersIfNeeded()
+ .withMode(CreateMode.PERSISTENT)
+ .forPath(path, null);
+ }
+ byte[] data = CollectionUtils.isEmpty(rules) ? "[]".getBytes() : converter.convert(rules)
+ .getBytes();
+ zkClient.setData()
+ .forPath(path, data);
+ }
+}
\ No newline at end of file
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/DegradeZookeeperProvider.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/DegradeZookeeperProvider.java
new file mode 100644
index 0000000000..6c9c6a2ec2
--- /dev/null
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/DegradeZookeeperProvider.java
@@ -0,0 +1,33 @@
+package com.alibaba.csp.sentinel.dashboard.rule;
+
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
+import com.alibaba.csp.sentinel.datasource.Converter;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.curator.framework.CuratorFramework;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component("degradeRuleZookeeperProvider")
+public class DegradeZookeeperProvider implements DynamicRuleProvider> {
+
+ @Autowired
+ private CuratorFramework zkClient;
+ @Autowired
+ private Converter> converter;
+ @Autowired
+ private ZookeeperSentinelConfig zkConfig;
+
+ @Override
+ public List getRules(String appName) throws Exception {
+ String zkPath = zkConfig.getDegradeRulePath(appName);
+ byte[] bytes = zkClient.getData()
+ .forPath(zkPath);
+ if (null == bytes || bytes.length == 0) {
+ return new ArrayList<>();
+ }
+ String s = new String(bytes);
+
+ return converter.convert(s);
+ }
+}
\ No newline at end of file
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/FlowRuleZookeeperProvider.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/FlowRuleZookeeperProvider.java
new file mode 100644
index 0000000000..cf895503c9
--- /dev/null
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/FlowRuleZookeeperProvider.java
@@ -0,0 +1,33 @@
+package com.alibaba.csp.sentinel.dashboard.rule;
+
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
+import com.alibaba.csp.sentinel.datasource.Converter;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.curator.framework.CuratorFramework;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component("flowRuleZookeeperProvider")
+public class FlowRuleZookeeperProvider implements DynamicRuleProvider> {
+
+ @Autowired
+ private CuratorFramework zkClient;
+ @Autowired
+ private Converter> converter;
+ @Autowired
+ private ZookeeperSentinelConfig zkConfig;
+
+ @Override
+ public List getRules(String appName) throws Exception {
+ String zkPath = zkConfig.getFlowRulePath(appName);
+ byte[] bytes = zkClient.getData()
+ .forPath(zkPath);
+ if (null == bytes || bytes.length == 0) {
+ return new ArrayList<>();
+ }
+ String s = new String(bytes);
+
+ return converter.convert(s);
+ }
+}
\ No newline at end of file
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/FlowRuleZookeeperPublisher.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/FlowRuleZookeeperPublisher.java
new file mode 100644
index 0000000000..9fbd18e44b
--- /dev/null
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/FlowRuleZookeeperPublisher.java
@@ -0,0 +1,42 @@
+package com.alibaba.csp.sentinel.dashboard.rule;
+
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
+import com.alibaba.csp.sentinel.datasource.Converter;
+import com.alibaba.csp.sentinel.util.AssertUtil;
+import java.util.List;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.data.Stat;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+@Component("flowRuleZookeeperPublisher")
+public class FlowRuleZookeeperPublisher implements DynamicRulePublisher> {
+
+ @Autowired
+ private CuratorFramework zkClient;
+ @Autowired
+ private Converter, String> converter;
+ @Autowired
+ private ZookeeperSentinelConfig zkConfig;
+
+ @Override
+ public void publish(String app, List rules) throws Exception {
+ AssertUtil.notEmpty(app, "app name cannot be empty");
+
+ String path = zkConfig.getFlowRulePath(app);
+ Stat stat = zkClient.checkExists()
+ .forPath(path);
+ if (stat == null) {
+ zkClient.create()
+ .creatingParentContainersIfNeeded()
+ .withMode(CreateMode.PERSISTENT)
+ .forPath(path, null);
+ }
+ byte[] data = CollectionUtils.isEmpty(rules) ? "[]".getBytes() : converter.convert(rules)
+ .getBytes();
+ zkClient.setData()
+ .forPath(path, data);
+ }
+}
\ No newline at end of file
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/ZookeeperConfig.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/ZookeeperConfig.java
new file mode 100644
index 0000000000..605e6770e8
--- /dev/null
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/ZookeeperConfig.java
@@ -0,0 +1,49 @@
+package com.alibaba.csp.sentinel.dashboard.rule;
+
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
+import com.alibaba.csp.sentinel.datasource.Converter;
+import com.alibaba.fastjson.JSON;
+import java.util.List;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.retry.ExponentialBackoffRetry;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ZookeeperConfig {
+
+ @Value("${zk.address}")
+ private String zkAddress;
+
+ @Bean
+ public Converter, String> flowRuleEntityEncoder() {
+ return JSON::toJSONString;
+ }
+
+ @Bean
+ public Converter> flowRuleEntityDecoder() {
+ return s -> JSON.parseArray(s, FlowRuleEntity.class);
+ }
+
+ @Bean
+ public Converter, String> degradeRuleEntityEncoder() {
+ return JSON::toJSONString;
+ }
+
+ @Bean
+ public Converter> degradeRuleEntityDecoder() {
+ return s -> JSON.parseArray(s, DegradeRuleEntity.class);
+ }
+
+ @Bean
+ public CuratorFramework zkClient() {
+ CuratorFramework zkClient = CuratorFrameworkFactory.newClient(zkAddress,
+ new ExponentialBackoffRetry(ZookeeperConfigUtil.SLEEP_TIME, ZookeeperConfigUtil.RETRY_TIMES));
+ zkClient.start();
+
+ return zkClient;
+ }
+}
\ No newline at end of file
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/ZookeeperConfigUtil.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/ZookeeperConfigUtil.java
new file mode 100644
index 0000000000..d15811e5b0
--- /dev/null
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/ZookeeperConfigUtil.java
@@ -0,0 +1,26 @@
+package com.alibaba.csp.sentinel.dashboard.rule;
+
+import org.apache.commons.lang.StringUtils;
+
+public class ZookeeperConfigUtil {
+
+ public static final String RULE_ROOT_PATH = "/sentinel_rules";
+
+ public static final int RETRY_TIMES = 3;
+ public static final int SLEEP_TIME = 1000;
+
+ public static String getPath(String appName) {
+ StringBuilder stringBuilder = new StringBuilder(RULE_ROOT_PATH);
+
+ if (StringUtils.isBlank(appName)) {
+ return stringBuilder.toString();
+ }
+ if (appName.startsWith("/")) {
+ stringBuilder.append(appName);
+ } else {
+ stringBuilder.append("/")
+ .append(appName);
+ }
+ return stringBuilder.toString();
+ }
+}
\ No newline at end of file
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/ZookeeperSentinelConfig.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/ZookeeperSentinelConfig.java
new file mode 100644
index 0000000000..1ac85c7cda
--- /dev/null
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/ZookeeperSentinelConfig.java
@@ -0,0 +1,76 @@
+package com.alibaba.csp.sentinel.dashboard.rule;
+
+import com.alibaba.csp.sentinel.datasource.Converter;
+import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
+import com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource;
+import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
+import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.TypeReference;
+import java.util.List;
+import javax.annotation.PostConstruct;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ZookeeperSentinelConfig {
+
+ private final Logger logger = LoggerFactory.getLogger(ZookeeperSentinelConfig.class);
+ private final String FLOW_PATH = "/flow";
+ private final String DEGRADE_PATH = "/degrade";
+ @Value("${zk.address}")
+ private String zkAddress;
+ @Value("${zk.sentinel.path}")
+ private String zkPath;
+ @Value("${zk.sentinel.appName}")
+ private String appName;
+
+ @PostConstruct
+ public void loadRules() {
+ //Flow
+ ReadableDataSource> flowRuleDataSource = new ZookeeperDataSource<>(zkAddress,
+ zkPath + appName, source -> JSON.parseObject(source, new TypeReference>() {
+ }));
+ FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
+
+ //Degrade
+ String degradePath = zkPath + appName + DEGRADE_PATH;
+ Converter> degradeRules = source -> JSON.parseObject(source,
+ new TypeReference>() {
+ });
+ ReadableDataSource> zkDataSourceDegrade = new ZookeeperDataSource<>(zkAddress,
+ degradePath, degradeRules);
+ DegradeRuleManager.register2Property(zkDataSourceDegrade.getProperty());
+ logger.info("----------------- Sentinel DataSource Zookeeper Init Success -------------------");
+ }
+
+
+ public String getFlowRulePath(String appName) {
+ if (appName.startsWith("/")) {
+ return zkPath + appName + FLOW_PATH;
+ } else {
+ return zkPath + "/" + appName + FLOW_PATH;
+ }
+ }
+
+ public String getDegradeRulePath(String appName) {
+ if (appName.startsWith("/")) {
+ return zkPath + appName + DEGRADE_PATH;
+ } else {
+ return zkPath + "/" + appName + DEGRADE_PATH;
+ }
+ }
+
+ public String getZkAddress() {
+ return zkAddress;
+ }
+
+ public String getZkPath() {
+ return zkPath;
+ }
+
+}
diff --git a/sentinel-dashboard/src/main/resources/application-stg.properties b/sentinel-dashboard/src/main/resources/application-stg.properties
new file mode 100755
index 0000000000..9a1c028224
--- /dev/null
+++ b/sentinel-dashboard/src/main/resources/application-stg.properties
@@ -0,0 +1,24 @@
+#spring settings
+spring.http.encoding.force=true
+spring.http.encoding.charset=UTF-8
+spring.http.encoding.enabled=true
+
+#logging settings
+logging.level.org.springframework.web=INFO
+logging.file=${user.home}/logs/csp/sentinel-dashboard.log
+logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
+#logging.pattern.console= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
+
+#auth settings
+auth.filter.exclude-urls=/,/auth/login,/auth/logout,/registry/machine,/version
+auth.filter.exclude-url-suffixes=htm,html,js,css,map,ico,ttf,woff,png
+auth.username=sentinel
+auth.password=sentinel
+auth.admin.username=admin
+auth.admin.password=admin
+# Inject the dashboard version. It's required to enable
+# filtering in pom.xml for this resource file.
+sentinel.dashboard.version=${project.version}
+zk.address=stg-dwhxenial001-stg-cloud008.phonepe.nm2:2181
+zk.sentinel.path=/sentinel_rules
+zk.sentinel.appName=/sentinel-dashboard
\ No newline at end of file
diff --git a/sentinel-dashboard/src/main/resources/application-test.properties b/sentinel-dashboard/src/main/resources/application-test.properties
new file mode 100755
index 0000000000..a089db3634
--- /dev/null
+++ b/sentinel-dashboard/src/main/resources/application-test.properties
@@ -0,0 +1,13 @@
+#spring settings
+spring.http.encoding.force=true
+spring.http.encoding.charset=UTF-8
+spring.http.encoding.enabled=true
+#logging settings
+logging.level.org.springframework.web=INFO
+logging.file=/tmp/logs/sentinel-dashboard.log
+logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
+#logging.pattern.console= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
+#Zookeeper
+zk.address=localhost:2181
+zk.sentinel.path=/sentinel_rules
+zk.sentinel.appName=/sentinel-dashboard
\ No newline at end of file
diff --git a/sentinel-dashboard/src/main/resources/application.properties b/sentinel-dashboard/src/main/resources/application.properties
index a2f84dec89..9a1c028224 100755
--- a/sentinel-dashboard/src/main/resources/application.properties
+++ b/sentinel-dashboard/src/main/resources/application.properties
@@ -12,10 +12,13 @@ logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %
#auth settings
auth.filter.exclude-urls=/,/auth/login,/auth/logout,/registry/machine,/version
auth.filter.exclude-url-suffixes=htm,html,js,css,map,ico,ttf,woff,png
-# If auth.enabled=false, Sentinel console disable login
auth.username=sentinel
auth.password=sentinel
-
+auth.admin.username=admin
+auth.admin.password=admin
# Inject the dashboard version. It's required to enable
# filtering in pom.xml for this resource file.
-sentinel.dashboard.version=${project.version}
\ No newline at end of file
+sentinel.dashboard.version=${project.version}
+zk.address=stg-dwhxenial001-stg-cloud008.phonepe.nm2:2181
+zk.sentinel.path=/sentinel_rules
+zk.sentinel.appName=/sentinel-dashboard
\ No newline at end of file
diff --git a/sentinel-dashboard/src/main/resources/application.yml b/sentinel-dashboard/src/main/resources/application.yml
new file mode 100644
index 0000000000..360bd95c96
--- /dev/null
+++ b/sentinel-dashboard/src/main/resources/application.yml
@@ -0,0 +1,7 @@
+my:
+ name: sentinel
+
+spring:
+ profiles:
+ active: test
+
\ No newline at end of file
diff --git a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayApiControllerTest.java b/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayApiControllerTest.java
deleted file mode 100644
index 9751c8311e..0000000000
--- a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayApiControllerTest.java
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright 1999-2018 Alibaba Group Holding Ltd.
- *
- * 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 com.alibaba.csp.sentinel.dashboard.controller.gateway;
-
-import com.alibaba.csp.sentinel.dashboard.auth.AuthorizationInterceptor;
-import com.alibaba.csp.sentinel.dashboard.auth.FakeAuthServiceImpl;
-import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
-import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity;
-import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiPredicateItemEntity;
-import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
-import com.alibaba.csp.sentinel.dashboard.discovery.SimpleMachineDiscovery;
-import com.alibaba.csp.sentinel.dashboard.domain.Result;
-import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.AddApiReqVo;
-import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.ApiPredicateItemVo;
-import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.UpdateApiReqVo;
-import com.alibaba.csp.sentinel.dashboard.repository.gateway.InMemApiDefinitionStore;
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import com.alibaba.fastjson.TypeReference;
-import org.apache.commons.lang3.time.DateUtils;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-import org.springframework.http.MediaType;
-import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.test.web.servlet.MvcResult;
-import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
-import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
-import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
-import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
-
-import java.util.*;
-import java.util.concurrent.CompletableFuture;
-
-import static com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants.*;
-import static org.junit.Assert.*;
-import static org.mockito.BDDMockito.*;
-
-/**
- * Test cases for {@link GatewayApiController}.
- *
- * @author cdfive
- */
-@RunWith(SpringRunner.class)
-@WebMvcTest(GatewayApiController.class)
-@Import({FakeAuthServiceImpl.class, InMemApiDefinitionStore.class, AppManagement.class, SimpleMachineDiscovery.class, AuthorizationInterceptor.class})
-public class GatewayApiControllerTest {
-
- private static final String TEST_APP = "test_app";
-
- private static final String TEST_IP = "localhost";
-
- private static final Integer TEST_PORT = 8719;
-
- @Autowired
- private MockMvc mockMvc;
-
- @Autowired
- private InMemApiDefinitionStore repository;
-
- @MockBean
- private SentinelApiClient sentinelApiClient;
-
- @Before
- public void before() {
- repository.clearAll();
- }
-
- @Test
- public void testQueryApis() throws Exception {
- String path = "/gateway/api/list.json";
-
- List entities = new ArrayList<>();
-
- // Mock two entities
- ApiDefinitionEntity entity = new ApiDefinitionEntity();
- entity.setId(1L);
- entity.setApp(TEST_APP);
- entity.setIp(TEST_IP);
- entity.setPort(TEST_PORT);
- entity.setApiName("foo");
- Date date = new Date();
- entity.setGmtCreate(date);
- entity.setGmtModified(date);
-
- Set itemEntities = new LinkedHashSet<>();
- entity.setPredicateItems(itemEntities);
- ApiPredicateItemEntity itemEntity = new ApiPredicateItemEntity();
- itemEntity.setPattern("/aaa");
- itemEntity.setMatchStrategy(URL_MATCH_STRATEGY_EXACT);
-
- itemEntities.add(itemEntity);
- entities.add(entity);
-
- ApiDefinitionEntity entity2 = new ApiDefinitionEntity();
- entity2.setId(2L);
- entity2.setApp(TEST_APP);
- entity2.setIp(TEST_IP);
- entity2.setPort(TEST_PORT);
- entity2.setApiName("biz");
- entity.setGmtCreate(date);
- entity.setGmtModified(date);
-
- Set itemEntities2 = new LinkedHashSet<>();
- entity2.setPredicateItems(itemEntities2);
- ApiPredicateItemEntity itemEntity2 = new ApiPredicateItemEntity();
- itemEntity2.setPattern("/bbb");
- itemEntity2.setMatchStrategy(URL_MATCH_STRATEGY_PREFIX);
-
- itemEntities2.add(itemEntity2);
- entities.add(entity2);
-
- CompletableFuture> completableFuture = mock(CompletableFuture.class);
- given(completableFuture.get()).willReturn(entities);
- given(sentinelApiClient.fetchApis(TEST_APP, TEST_IP, TEST_PORT)).willReturn(completableFuture);
-
- MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get(path);
- requestBuilder.param("app", TEST_APP);
- requestBuilder.param("ip", TEST_IP);
- requestBuilder.param("port", String.valueOf(TEST_PORT));
-
- // Do controller logic
- MvcResult mvcResult = mockMvc.perform(requestBuilder)
- .andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print()).andReturn();
-
- // Verify the fetchApis method has been called
- verify(sentinelApiClient).fetchApis(TEST_APP, TEST_IP, TEST_PORT);
-
- // Verify if two same entities are got
- Result> result = JSONObject.parseObject(mvcResult.getResponse().getContentAsString(), new TypeReference>>(){});
- assertTrue(result.isSuccess());
-
- List data = result.getData();
- assertEquals(2, data.size());
- assertEquals(entities, data);
-
- // Verify the entities are add into memory repository
- List entitiesInMem = repository.findAllByApp(TEST_APP);
- assertEquals(2, entitiesInMem.size());
- assertEquals(entities, entitiesInMem);
- }
-
- @Test
- public void testAddApi() throws Exception {
- String path = "/gateway/api/new.json";
-
- AddApiReqVo reqVo = new AddApiReqVo();
- reqVo.setApp(TEST_APP);
- reqVo.setIp(TEST_IP);
- reqVo.setPort(TEST_PORT);
-
- reqVo.setApiName("customized_api");
-
- List itemVos = new ArrayList<>();
- ApiPredicateItemVo itemVo = new ApiPredicateItemVo();
- itemVo.setMatchStrategy(URL_MATCH_STRATEGY_EXACT);
- itemVo.setPattern("/product");
- itemVos.add(itemVo);
- reqVo.setPredicateItems(itemVos);
-
- given(sentinelApiClient.modifyApis(eq(TEST_APP), eq(TEST_IP), eq(TEST_PORT), any())).willReturn(true);
-
- MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post(path);
- requestBuilder.content(JSON.toJSONString(reqVo)).contentType(MediaType.APPLICATION_JSON);
-
- // Do controller logic
- MvcResult mvcResult = mockMvc.perform(requestBuilder)
- .andExpect(MockMvcResultMatchers.status().isOk())
- .andDo(MockMvcResultHandlers.print()).andReturn();
-
- // Verify the modifyApis method has been called
- verify(sentinelApiClient).modifyApis(eq(TEST_APP), eq(TEST_IP), eq(TEST_PORT), any());
-
- Result result = JSONObject.parseObject(mvcResult.getResponse().getContentAsString(), new TypeReference>() {});
- assertTrue(result.isSuccess());
-
- // Verify the result
- ApiDefinitionEntity entity = result.getData();
- assertNotNull(entity);
- assertEquals(TEST_APP, entity.getApp());
- assertEquals(TEST_IP, entity.getIp());
- assertEquals(TEST_PORT, entity.getPort());
- assertEquals("customized_api", entity.getApiName());
- assertNotNull(entity.getId());
- assertNotNull(entity.getGmtCreate());
- assertNotNull(entity.getGmtModified());
-
- Set predicateItemEntities = entity.getPredicateItems();
- assertEquals(1, predicateItemEntities.size());
- ApiPredicateItemEntity predicateItemEntity = predicateItemEntities.iterator().next();
- assertEquals(URL_MATCH_STRATEGY_EXACT, predicateItemEntity.getMatchStrategy().intValue());
- assertEquals("/product", predicateItemEntity.getPattern());
-
- // Verify the entity which is add in memory repository
- List entitiesInMem = repository.findAllByApp(TEST_APP);
- assertEquals(1, entitiesInMem.size());
- assertEquals(entity, entitiesInMem.get(0));
- }
-
- @Test
- public void testUpdateApi() throws Exception {
- String path = "/gateway/api/save.json";
-
- // Add one entity to memory repository for update
- ApiDefinitionEntity addEntity = new ApiDefinitionEntity();
- addEntity.setApp(TEST_APP);
- addEntity.setIp(TEST_IP);
- addEntity.setPort(TEST_PORT);
- addEntity.setApiName("bbb");
- Date date = new Date();
- // To make the gmtModified different when do update
- date = DateUtils.addSeconds(date, -1);
- addEntity.setGmtCreate(date);
- addEntity.setGmtModified(date);
- Set addRedicateItemEntities = new HashSet<>();
- addEntity.setPredicateItems(addRedicateItemEntities);
- ApiPredicateItemEntity addPredicateItemEntity = new ApiPredicateItemEntity();
- addPredicateItemEntity.setMatchStrategy(URL_MATCH_STRATEGY_EXACT);
- addPredicateItemEntity.setPattern("/order");
- addEntity = repository.save(addEntity);
-
- UpdateApiReqVo reqVo = new UpdateApiReqVo();
- reqVo.setId(addEntity.getId());
- reqVo.setApp(TEST_APP);
- List itemVos = new ArrayList<>();
- ApiPredicateItemVo itemVo = new ApiPredicateItemVo();
- itemVo.setMatchStrategy(URL_MATCH_STRATEGY_PREFIX);
- itemVo.setPattern("/my_order");
- itemVos.add(itemVo);
- reqVo.setPredicateItems(itemVos);
-
- given(sentinelApiClient.modifyApis(eq(TEST_APP), eq(TEST_IP), eq(TEST_PORT), any())).willReturn(true);
-
- MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post(path);
- requestBuilder.content(JSON.toJSONString(reqVo)).contentType(MediaType.APPLICATION_JSON);
-
- // Do controller logic
- MvcResult mvcResult = mockMvc.perform(requestBuilder)
- .andExpect(MockMvcResultMatchers.status().isOk())
- .andDo(MockMvcResultHandlers.print()).andReturn();
-
- // Verify the modifyApis method has been called
- verify(sentinelApiClient).modifyApis(eq(TEST_APP), eq(TEST_IP), eq(TEST_PORT), any());
-
- Result result = JSONObject.parseObject(mvcResult.getResponse().getContentAsString(), new TypeReference>() {});
- assertTrue(result.isSuccess());
-
- ApiDefinitionEntity entity = result.getData();
- assertNotNull(entity);
- assertEquals("bbb", entity.getApiName());
- assertEquals(date, entity.getGmtCreate());
- // To make sure gmtModified has been set and it's different from gmtCreate
- assertNotNull(entity.getGmtModified());
- assertNotEquals(entity.getGmtCreate(), entity.getGmtModified());
-
- Set predicateItemEntities = entity.getPredicateItems();
- assertEquals(1, predicateItemEntities.size());
- ApiPredicateItemEntity predicateItemEntity = predicateItemEntities.iterator().next();
- assertEquals(URL_MATCH_STRATEGY_PREFIX, predicateItemEntity.getMatchStrategy().intValue());
- assertEquals("/my_order", predicateItemEntity.getPattern());
-
- // Verify the entity which is update in memory repository
- List entitiesInMem = repository.findAllByApp(TEST_APP);
- assertEquals(1, entitiesInMem.size());
- assertEquals(entity, entitiesInMem.get(0));
- }
-
- @Test
- public void testDeleteApi() throws Exception {
- String path = "/gateway/api/delete.json";
-
- // Add one entity into memory repository for delete
- ApiDefinitionEntity addEntity = new ApiDefinitionEntity();
- addEntity.setApp(TEST_APP);
- addEntity.setIp(TEST_IP);
- addEntity.setPort(TEST_PORT);
- addEntity.setApiName("ccc");
- Date date = new Date();
- addEntity.setGmtCreate(date);
- addEntity.setGmtModified(date);
- Set addRedicateItemEntities = new HashSet<>();
- addEntity.setPredicateItems(addRedicateItemEntities);
- ApiPredicateItemEntity addPredicateItemEntity = new ApiPredicateItemEntity();
- addPredicateItemEntity.setMatchStrategy(URL_MATCH_STRATEGY_EXACT);
- addPredicateItemEntity.setPattern("/user/add");
- addEntity = repository.save(addEntity);
-
- given(sentinelApiClient.modifyApis(eq(TEST_APP), eq(TEST_IP), eq(TEST_PORT), any())).willReturn(true);
-
- MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post(path);
- requestBuilder.param("id", String.valueOf(addEntity.getId()));
-
- // Do controller logic
- MvcResult mvcResult = mockMvc.perform(requestBuilder)
- .andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print()).andReturn();
-
- // Verify the modifyApis method has been called
- verify(sentinelApiClient).modifyApis(eq(TEST_APP), eq(TEST_IP), eq(TEST_PORT), any());
-
- // Verify the result
- Result result = JSONObject.parseObject(mvcResult.getResponse().getContentAsString(), new TypeReference>() {});
- assertTrue(result.isSuccess());
-
- assertEquals(addEntity.getId(), result.getData());
-
- // Now no entities in memory
- List entitiesInMem = repository.findAllByApp(TEST_APP);
- assertEquals(0, entitiesInMem.size());
- }
-}
diff --git a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayFlowRuleControllerTest.java b/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayFlowRuleControllerTest.java
deleted file mode 100644
index b9c2353e47..0000000000
--- a/sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayFlowRuleControllerTest.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright 1999-2018 Alibaba Group Holding Ltd.
- *
- * 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 com.alibaba.csp.sentinel.dashboard.controller.gateway;
-
-import com.alibaba.csp.sentinel.dashboard.auth.AuthorizationInterceptor;
-import com.alibaba.csp.sentinel.dashboard.auth.FakeAuthServiceImpl;
-import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
-import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity;
-import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayParamFlowItemEntity;
-import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
-import com.alibaba.csp.sentinel.dashboard.discovery.SimpleMachineDiscovery;
-import com.alibaba.csp.sentinel.dashboard.domain.Result;
-import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.rule.AddFlowRuleReqVo;
-import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.rule.GatewayParamFlowItemVo;
-import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.rule.UpdateFlowRuleReqVo;
-import com.alibaba.csp.sentinel.dashboard.repository.gateway.InMemGatewayFlowRuleStore;
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import com.alibaba.fastjson.TypeReference;
-import org.apache.commons.lang3.time.DateUtils;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-import org.springframework.http.MediaType;
-import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.test.web.servlet.MvcResult;
-import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
-import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
-import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
-import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-
-import static com.alibaba.csp.sentinel.slots.block.RuleConstant.*;
-import static com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants.*;
-import static org.junit.Assert.*;
-import static org.mockito.BDDMockito.*;
-
-/**
- * Test cases for {@link GatewayFlowRuleController}.
- *
- * @author cdfive
- */
-@RunWith(SpringRunner.class)
-@WebMvcTest(GatewayFlowRuleController.class)
-@Import({FakeAuthServiceImpl.class, InMemGatewayFlowRuleStore.class, AppManagement.class, SimpleMachineDiscovery.class,
- AuthorizationInterceptor.class })
-public class GatewayFlowRuleControllerTest {
-
- private static final String TEST_APP = "test_app";
-
- private static final String TEST_IP = "localhost";
-
- private static final Integer TEST_PORT = 8719;
-
- @Autowired
- private MockMvc mockMvc;
-
- @Autowired
- private InMemGatewayFlowRuleStore repository;
-
- @MockBean
- private SentinelApiClient sentinelApiClient;
-
- @Before
- public void before() {
- repository.clearAll();
- }
-
- @Test
- public void testQueryFlowRules() throws Exception {
- String path = "/gateway/flow/list.json";
-
- List entities = new ArrayList<>();
-
- // Mock two entities
- GatewayFlowRuleEntity entity = new GatewayFlowRuleEntity();
- entity.setId(1L);
- entity.setApp(TEST_APP);
- entity.setIp(TEST_IP);
- entity.setPort(TEST_PORT);
- entity.setResource("httpbin_route");
- entity.setResourceMode(RESOURCE_MODE_ROUTE_ID);
- entity.setGrade(FLOW_GRADE_QPS);
- entity.setCount(5D);
- entity.setInterval(30L);
- entity.setIntervalUnit(GatewayFlowRuleEntity.INTERVAL_UNIT_SECOND);
- entity.setControlBehavior(CONTROL_BEHAVIOR_DEFAULT);
- entity.setBurst(0);
- entity.setMaxQueueingTimeoutMs(0);
-
- GatewayParamFlowItemEntity itemEntity = new GatewayParamFlowItemEntity();
- entity.setParamItem(itemEntity);
- itemEntity.setParseStrategy(PARAM_PARSE_STRATEGY_CLIENT_IP);
- entities.add(entity);
-
- GatewayFlowRuleEntity entity2 = new GatewayFlowRuleEntity();
- entity2.setId(2L);
- entity2.setApp(TEST_APP);
- entity2.setIp(TEST_IP);
- entity2.setPort(TEST_PORT);
- entity2.setResource("some_customized_api");
- entity2.setResourceMode(RESOURCE_MODE_CUSTOM_API_NAME);
- entity2.setCount(30D);
- entity2.setInterval(2L);
- entity2.setIntervalUnit(GatewayFlowRuleEntity.INTERVAL_UNIT_MINUTE);
- entity2.setControlBehavior(CONTROL_BEHAVIOR_DEFAULT);
- entity2.setBurst(0);
- entity2.setMaxQueueingTimeoutMs(0);
-
- GatewayParamFlowItemEntity itemEntity2 = new GatewayParamFlowItemEntity();
- entity2.setParamItem(itemEntity2);
- itemEntity2.setParseStrategy(PARAM_PARSE_STRATEGY_CLIENT_IP);
- entities.add(entity2);
-
- CompletableFuture> completableFuture = mock(CompletableFuture.class);
- given(completableFuture.get()).willReturn(entities);
- given(sentinelApiClient.fetchGatewayFlowRules(TEST_APP, TEST_IP, TEST_PORT)).willReturn(completableFuture);
-
- MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get(path);
- requestBuilder.param("app", TEST_APP);
- requestBuilder.param("ip", TEST_IP);
- requestBuilder.param("port", String.valueOf(TEST_PORT));
-
- // Do controller logic
- MvcResult mvcResult = mockMvc.perform(requestBuilder)
- .andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print()).andReturn();
-
- // Verify the fetchGatewayFlowRules method has been called
- verify(sentinelApiClient).fetchGatewayFlowRules(TEST_APP, TEST_IP, TEST_PORT);
-
- // Verify if two same entities are got
- Result> result = JSONObject.parseObject(mvcResult.getResponse().getContentAsString(), new TypeReference>>(){});
- assertTrue(result.isSuccess());
-
- List data = result.getData();
- assertEquals(2, data.size());
- assertEquals(entities, data);
-
- // Verify the entities are add into memory repository
- List entitiesInMem = repository.findAllByApp(TEST_APP);
- assertEquals(2, entitiesInMem.size());
- assertEquals(entities, entitiesInMem);
- }
-
- @Test
- public void testAddFlowRule() throws Exception {
- String path = "/gateway/flow/new.json";
-
- AddFlowRuleReqVo reqVo = new AddFlowRuleReqVo();
- reqVo.setApp(TEST_APP);
- reqVo.setIp(TEST_IP);
- reqVo.setPort(TEST_PORT);
-
- reqVo.setResourceMode(RESOURCE_MODE_ROUTE_ID);
- reqVo.setResource("httpbin_route");
-
- reqVo.setGrade(FLOW_GRADE_QPS);
- reqVo.setCount(5D);
- reqVo.setInterval(30L);
- reqVo.setIntervalUnit(GatewayFlowRuleEntity.INTERVAL_UNIT_SECOND);
- reqVo.setControlBehavior(CONTROL_BEHAVIOR_DEFAULT);
- reqVo.setBurst(0);
- reqVo.setMaxQueueingTimeoutMs(0);
-
- given(sentinelApiClient.modifyGatewayFlowRules(eq(TEST_APP), eq(TEST_IP), eq(TEST_PORT), any())).willReturn(true);
-
- MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post(path);
- requestBuilder.content(JSON.toJSONString(reqVo)).contentType(MediaType.APPLICATION_JSON);
-
- // Do controller logic
- MvcResult mvcResult = mockMvc.perform(requestBuilder)
- .andExpect(MockMvcResultMatchers.status().isOk())
- .andDo(MockMvcResultHandlers.print()).andReturn();
-
- // Verify the modifyGatewayFlowRules method has been called
- verify(sentinelApiClient).modifyGatewayFlowRules(eq(TEST_APP), eq(TEST_IP), eq(TEST_PORT), any());
-
- Result result = JSONObject.parseObject(mvcResult.getResponse().getContentAsString(), new TypeReference>() {});
- assertTrue(result.isSuccess());
-
- // Verify the result
- GatewayFlowRuleEntity entity = result.getData();
- assertNotNull(entity);
- assertEquals(TEST_APP, entity.getApp());
- assertEquals(TEST_IP, entity.getIp());
- assertEquals(TEST_PORT, entity.getPort());
- assertEquals(RESOURCE_MODE_ROUTE_ID, entity.getResourceMode().intValue());
- assertEquals("httpbin_route", entity.getResource());
- assertNotNull(entity.getId());
- assertNotNull(entity.getGmtCreate());
- assertNotNull(entity.getGmtModified());
-
- // Verify the entity which is add in memory repository
- List entitiesInMem = repository.findAllByApp(TEST_APP);
- assertEquals(1, entitiesInMem.size());
- assertEquals(entity, entitiesInMem.get(0));
- }
-
- @Test
- public void testUpdateFlowRule() throws Exception {
- String path = "/gateway/flow/save.json";
-
- // Add one entity into memory repository for update
- GatewayFlowRuleEntity addEntity = new GatewayFlowRuleEntity();
- addEntity.setId(1L);
- addEntity.setApp(TEST_APP);
- addEntity.setIp(TEST_IP);
- addEntity.setPort(TEST_PORT);
- addEntity.setResource("httpbin_route");
- addEntity.setResourceMode(RESOURCE_MODE_ROUTE_ID);
- addEntity.setGrade(FLOW_GRADE_QPS);
- addEntity.setCount(5D);
- addEntity.setInterval(30L);
- addEntity.setIntervalUnit(GatewayFlowRuleEntity.INTERVAL_UNIT_SECOND);
- addEntity.setControlBehavior(CONTROL_BEHAVIOR_DEFAULT);
- addEntity.setBurst(0);
- addEntity.setMaxQueueingTimeoutMs(0);
- Date date = new Date();
- // To make the gmtModified different when do update
- date = DateUtils.addSeconds(date, -1);
- addEntity.setGmtCreate(date);
- addEntity.setGmtModified(date);
-
- GatewayParamFlowItemEntity addItemEntity = new GatewayParamFlowItemEntity();
- addEntity.setParamItem(addItemEntity);
- addItemEntity.setParseStrategy(PARAM_PARSE_STRATEGY_CLIENT_IP);
-
- repository.save(addEntity);
-
- UpdateFlowRuleReqVo reqVo = new UpdateFlowRuleReqVo();
- reqVo.setId(addEntity.getId());
- reqVo.setApp(TEST_APP);
- reqVo.setGrade(FLOW_GRADE_QPS);
- reqVo.setCount(6D);
- reqVo.setInterval(2L);
- reqVo.setIntervalUnit(GatewayFlowRuleEntity.INTERVAL_UNIT_MINUTE);
- reqVo.setControlBehavior(CONTROL_BEHAVIOR_RATE_LIMITER);
- reqVo.setMaxQueueingTimeoutMs(500);
-
- GatewayParamFlowItemVo itemVo = new GatewayParamFlowItemVo();
- reqVo.setParamItem(itemVo);
- itemVo.setParseStrategy(PARAM_PARSE_STRATEGY_URL_PARAM);
- itemVo.setFieldName("pa");
-
- given(sentinelApiClient.modifyGatewayFlowRules(eq(TEST_APP), eq(TEST_IP), eq(TEST_PORT), any())).willReturn(true);
-
- MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post(path);
- requestBuilder.content(JSON.toJSONString(reqVo)).contentType(MediaType.APPLICATION_JSON);
-
- // Do controller logic
- MvcResult mvcResult = mockMvc.perform(requestBuilder)
- .andExpect(MockMvcResultMatchers.status().isOk())
- .andDo(MockMvcResultHandlers.print()).andReturn();
-
- // Verify the modifyGatewayFlowRules method has been called
- verify(sentinelApiClient).modifyGatewayFlowRules(eq(TEST_APP), eq(TEST_IP), eq(TEST_PORT), any());
-
- Result result = JSONObject.parseObject(mvcResult.getResponse().getContentAsString(), new TypeReference>() {
- });
- assertTrue(result.isSuccess());
-
- GatewayFlowRuleEntity entity = result.getData();
- assertNotNull(entity);
- assertEquals(RESOURCE_MODE_ROUTE_ID, entity.getResourceMode().intValue());
- assertEquals("httpbin_route", entity.getResource());
- assertEquals(6D, entity.getCount().doubleValue(), 0);
- assertEquals(2L, entity.getInterval().longValue());
- assertEquals(GatewayFlowRuleEntity.INTERVAL_UNIT_MINUTE, entity.getIntervalUnit().intValue());
- assertEquals(CONTROL_BEHAVIOR_RATE_LIMITER, entity.getControlBehavior().intValue());
- assertEquals(0, entity.getBurst().intValue());
- assertEquals(500, entity.getMaxQueueingTimeoutMs().intValue());
- assertEquals(date, entity.getGmtCreate());
- // To make sure gmtModified has been set and it's different from gmtCreate
- assertNotNull(entity.getGmtModified());
- assertNotEquals(entity.getGmtCreate(), entity.getGmtModified());
-
- // Verify the entity which is update in memory repository
- GatewayParamFlowItemEntity itemEntity = entity.getParamItem();
- assertEquals(PARAM_PARSE_STRATEGY_URL_PARAM, itemEntity.getParseStrategy().intValue());
- assertEquals("pa", itemEntity.getFieldName());
- }
-
- @Test
- public void testDeleteFlowRule() throws Exception {
- String path = "/gateway/flow/delete.json";
-
- // Add one entity into memory repository for delete
- GatewayFlowRuleEntity addEntity = new GatewayFlowRuleEntity();
- addEntity.setId(1L);
- addEntity.setApp(TEST_APP);
- addEntity.setIp(TEST_IP);
- addEntity.setPort(TEST_PORT);
- addEntity.setResource("httpbin_route");
- addEntity.setResourceMode(RESOURCE_MODE_ROUTE_ID);
- addEntity.setGrade(FLOW_GRADE_QPS);
- addEntity.setCount(5D);
- addEntity.setInterval(30L);
- addEntity.setIntervalUnit(GatewayFlowRuleEntity.INTERVAL_UNIT_SECOND);
- addEntity.setControlBehavior(CONTROL_BEHAVIOR_DEFAULT);
- addEntity.setBurst(0);
- addEntity.setMaxQueueingTimeoutMs(0);
- Date date = new Date();
- date = DateUtils.addSeconds(date, -1);
- addEntity.setGmtCreate(date);
- addEntity.setGmtModified(date);
-
- GatewayParamFlowItemEntity addItemEntity = new GatewayParamFlowItemEntity();
- addEntity.setParamItem(addItemEntity);
- addItemEntity.setParseStrategy(PARAM_PARSE_STRATEGY_CLIENT_IP);
-
- repository.save(addEntity);
-
- given(sentinelApiClient.modifyGatewayFlowRules(eq(TEST_APP), eq(TEST_IP), eq(TEST_PORT), any())).willReturn(true);
-
- MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post(path);
- requestBuilder.param("id", String.valueOf(addEntity.getId()));
-
- // Do controller logic
- MvcResult mvcResult = mockMvc.perform(requestBuilder)
- .andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print()).andReturn();
-
- // Verify the modifyGatewayFlowRules method has been called
- verify(sentinelApiClient).modifyGatewayFlowRules(eq(TEST_APP), eq(TEST_IP), eq(TEST_PORT), any());
-
- // Verify the result
- Result result = JSONObject.parseObject(mvcResult.getResponse().getContentAsString(), new TypeReference>() {});
- assertTrue(result.isSuccess());
-
- assertEquals(addEntity.getId(), result.getData());
-
- // Now no entities in memory
- List entitiesInMem = repository.findAllByApp(TEST_APP);
- assertEquals(0, entitiesInMem.size());
- }
-}