From bf89974f7c7933661696013220a99fc9c3cb331c Mon Sep 17 00:00:00 2001 From: agapple Date: Tue, 27 Aug 2019 16:11:20 +0800 Subject: [PATCH] fixed issue #2099 , support remote config poll --- canal-admin/canal-admin-server/pom.xml | 35 ++- .../src/main/assembly/release.xml | 41 +++ .../src/main/bin/restart.sh | 5 + .../src/main/bin/startup.bat | 22 ++ .../src/main/bin/startup.sh | 84 ++++++ .../canal-admin-server/src/main/bin/stop.sh | 65 +++++ .../otter/canal/admin/config/WebConfig.java | 5 +- .../controller/CanalConfigController.java | 19 +- .../controller/PollConfigController.java | 155 ++++++++++ .../otter/canal/admin/model/CanalConfig.java | 10 + .../admin/model/CanalInstanceConfig.java | 12 +- .../otter/canal/admin/model/NodeServer.java | 41 +-- .../admin/service/CanalInstanceService.java | 6 +- .../impl/CanalInstanceServiceImpl.java | 19 +- .../service/impl/NodeServerServiceImpl.java | 16 +- .../src/main/resources/application.yml | 4 + .../src/main/resources/canal_manager.sql | 18 +- .../src/main/resources/public/index.html | 2 +- .../static/js/chunk-e1a839e4.7ee86dd8.js | 1 - .../static/js/chunk-e1a839e4.e9eb1b06.js | 1 + .../src/views/canalServer/NodeServer.vue | 40 ++- client-adapter/launcher/pom.xml | 2 +- deployer/manager_ddl.sql | 37 --- .../otter/canal/deployer/CanalConstants.java | 1 + .../otter/canal/deployer/CanalController.java | 84 +++--- .../otter/canal/deployer/CanalLauncher.java | 79 +++--- .../deployer/admin/CanalAdminController.java | 22 +- .../monitor/ManagerInstanceConfigMonitor.java | 171 +++++++++++- .../monitor/SpringInstanceConfigMonitor.java | 4 - .../deployer/monitor/remote/ConfigItem.java | 47 ---- .../monitor/remote/DbRemoteConfigLoader.java | 264 ------------------ .../remote/RemoteCanalConfigMonitor.java | 13 - .../monitor/remote/RemoteConfigLoader.java | 36 --- .../remote/RemoteConfigLoaderFactory.java | 42 --- .../monitor/remote/RemoteInstanceMonitor.java | 31 -- .../remote/RemoteInstanceMonitorImpl.java | 55 ---- .../remote/http/HttpRemoteConfigLoader.java | 257 ----------------- .../monitor/remote/http/ResponseModel.java | 38 --- deployer/src/main/resources/canal.properties | 10 +- instance/manager/pom.xml | 11 + .../manager/PlainCanalInstanceGenerator.java | 72 +++++ .../instance/manager/plain}/HttpHelper.java | 67 +++-- .../instance/manager/plain/PlainCanal.java | 55 ++++ .../manager/plain/PlainCanalConfigClient.java | 141 ++++++++++ .../PlainCanalConfigClientIntegration.java | 29 ++ .../spring/SpringCanalInstanceGenerator.java | 45 ++- .../PropertyPlaceholderConfigurer.java | 45 ++- .../otter/canal/protocol/SecurityUtil.java | 21 ++ 48 files changed, 1255 insertions(+), 1025 deletions(-) create mode 100644 canal-admin/canal-admin-server/src/main/assembly/release.xml create mode 100644 canal-admin/canal-admin-server/src/main/bin/restart.sh create mode 100755 canal-admin/canal-admin-server/src/main/bin/startup.bat create mode 100644 canal-admin/canal-admin-server/src/main/bin/startup.sh create mode 100644 canal-admin/canal-admin-server/src/main/bin/stop.sh create mode 100644 canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/PollConfigController.java delete mode 100644 canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-e1a839e4.7ee86dd8.js create mode 100644 canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-e1a839e4.e9eb1b06.js delete mode 100644 deployer/manager_ddl.sql delete mode 100644 deployer/src/main/java/com/alibaba/otter/canal/deployer/monitor/remote/ConfigItem.java delete mode 100644 deployer/src/main/java/com/alibaba/otter/canal/deployer/monitor/remote/DbRemoteConfigLoader.java delete mode 100644 deployer/src/main/java/com/alibaba/otter/canal/deployer/monitor/remote/RemoteCanalConfigMonitor.java delete mode 100644 deployer/src/main/java/com/alibaba/otter/canal/deployer/monitor/remote/RemoteConfigLoader.java delete mode 100644 deployer/src/main/java/com/alibaba/otter/canal/deployer/monitor/remote/RemoteConfigLoaderFactory.java delete mode 100644 deployer/src/main/java/com/alibaba/otter/canal/deployer/monitor/remote/RemoteInstanceMonitor.java delete mode 100644 deployer/src/main/java/com/alibaba/otter/canal/deployer/monitor/remote/RemoteInstanceMonitorImpl.java delete mode 100644 deployer/src/main/java/com/alibaba/otter/canal/deployer/monitor/remote/http/HttpRemoteConfigLoader.java delete mode 100644 deployer/src/main/java/com/alibaba/otter/canal/deployer/monitor/remote/http/ResponseModel.java create mode 100644 instance/manager/src/main/java/com/alibaba/otter/canal/instance/manager/PlainCanalInstanceGenerator.java rename {deployer/src/main/java/com/alibaba/otter/canal/deployer/monitor/remote/http => instance/manager/src/main/java/com/alibaba/otter/canal/instance/manager/plain}/HttpHelper.java (77%) create mode 100644 instance/manager/src/main/java/com/alibaba/otter/canal/instance/manager/plain/PlainCanal.java create mode 100644 instance/manager/src/main/java/com/alibaba/otter/canal/instance/manager/plain/PlainCanalConfigClient.java create mode 100644 instance/manager/src/test/java/com/alibaba/otter/canal/instance/manager/PlainCanalConfigClientIntegration.java diff --git a/canal-admin/canal-admin-server/pom.xml b/canal-admin/canal-admin-server/pom.xml index aa9c4c4c..9fcb1c86 100644 --- a/canal-admin/canal-admin-server/pom.xml +++ b/canal-admin/canal-admin-server/pom.xml @@ -8,9 +8,7 @@ 1.1.4-SNAPSHOT 4.0.0 - canal-admin-server - com.alibaba.otter @@ -199,6 +197,39 @@ + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + + + application.yml + canal_manager.sql + + + + + maven-assembly-plugin + 2.2.1 + + + assemble + + single + + package + + + + false + false + + ${basedir}/src/main/assembly/release.xml + + canal-admin-${project.version} + ${project.basedir}/../../target + + diff --git a/canal-admin/canal-admin-server/src/main/assembly/release.xml b/canal-admin/canal-admin-server/src/main/assembly/release.xml new file mode 100644 index 00000000..f7b66376 --- /dev/null +++ b/canal-admin/canal-admin-server/src/main/assembly/release.xml @@ -0,0 +1,41 @@ + + dist + + tar.gz + + false + + + . + / + + README* + + + + ./src/main/bin + bin + + **/* + + 0755 + + + ./src/main/resources + /conf + + application.yml + canal_manager.sql + + + + ./target + /lib + + canal-admin-*.jar + + + + \ No newline at end of file diff --git a/canal-admin/canal-admin-server/src/main/bin/restart.sh b/canal-admin/canal-admin-server/src/main/bin/restart.sh new file mode 100644 index 00000000..63749ce5 --- /dev/null +++ b/canal-admin/canal-admin-server/src/main/bin/restart.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +sh stop.sh + +sh startup.sh diff --git a/canal-admin/canal-admin-server/src/main/bin/startup.bat b/canal-admin/canal-admin-server/src/main/bin/startup.bat new file mode 100755 index 00000000..840f0c03 --- /dev/null +++ b/canal-admin/canal-admin-server/src/main/bin/startup.bat @@ -0,0 +1,22 @@ +@echo off +@if not "%ECHO%" == "" echo %ECHO% +@if "%OS%" == "Windows_NT" setlocal + +set ENV_PATH=.\ +if "%OS%" == "Windows_NT" set ENV_PATH=%~dp0% + +set conf_dir=%ENV_PATH%\..\conf + +set CLASSPATH=%conf_dir% +set CLASSPATH=%conf_dir%\..\lib\*;%CLASSPATH% + +set JAVA_MEM_OPTS= -Xms128m -Xmx512m +set JAVA_OPTS_EXT= -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dapplication.codeset=UTF-8 -Dfile.encoding=UTF-8 +set ADAPTER_OPTS= -DappName=canal-admin + +set JAVA_OPTS= %JAVA_MEM_OPTS% %JAVA_OPTS_EXT% %ADAPTER_OPTS% + +set CMD_STR= java %JAVA_OPTS% -classpath "%CLASSPATH%" com.alibaba.otter.canal.admin.CanalAdminApplication +echo start cmd : %CMD_STR% + +java %JAVA_OPTS% -classpath "%CLASSPATH%" com.alibaba.otter.canal.admin.CanalAdminApplication \ No newline at end of file diff --git a/canal-admin/canal-admin-server/src/main/bin/startup.sh b/canal-admin/canal-admin-server/src/main/bin/startup.sh new file mode 100644 index 00000000..ec18c408 --- /dev/null +++ b/canal-admin/canal-admin-server/src/main/bin/startup.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +current_path=`pwd` +case "`uname`" in + Linux) + bin_abs_path=$(readlink -f $(dirname $0)) + ;; + *) + bin_abs_path=`cd $(dirname $0); pwd` + ;; +esac +base=${bin_abs_path}/.. +export LANG=en_US.UTF-8 +export BASE=$base + +if [ -f $base/bin/adapter.pid ] ; then + echo "found adapter.pid , Please run stop.sh first ,then startup.sh" 2>&2 + exit 1 +fi + +if [ ! -d $base/logs ] ; then + mkdir -p $base/logs +fi + +## set java path +if [ -z "$JAVA" ] ; then + JAVA=$(which java) +fi + +ALIBABA_JAVA="/usr/alibaba/java/bin/java" +TAOBAO_JAVA="/opt/taobao/java/bin/java" +if [ -z "$JAVA" ]; then + if [ -f $ALIBABA_JAVA ] ; then + JAVA=$ALIBABA_JAVA + elif [ -f $TAOBAO_JAVA ] ; then + JAVA=$TAOBAO_JAVA + else + echo "Cannot find a Java JDK. Please set either set JAVA or put java (>=1.5) in your PATH." 2>&2 + exit 1 + fi +fi + +case "$#" +in +0 ) + ;; +2 ) + if [ "$1" = "debug" ]; then + DEBUG_PORT=$2 + DEBUG_SUSPEND="n" + JAVA_DEBUG_OPT="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=$DEBUG_SUSPEND" + fi + ;; +* ) + echo "THE PARAMETERS MUST BE TWO OR LESS.PLEASE CHECK AGAIN." + exit;; +esac + +str=`file -L $JAVA | grep 64-bit` +if [ -n "$str" ]; then + JAVA_OPTS="-server -Xms2048m -Xmx3072m" +else + JAVA_OPTS="-server -Xms1024m -Xmx1024m" +fi + +JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=250 -XX:+UseGCOverheadLimit -XX:+ExplicitGCInvokesConcurrent -XX:+PrintAdaptiveSizePolicy -XX:+PrintTenuringDistribution" +JAVA_OPTS=" $JAVA_OPTS -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8" +CANAL_OPTS="-DappName=canal-admin" + +for i in $base/lib/*; + do CLASSPATH=$i:"$CLASSPATH"; +done + +CLASSPATH="$base/conf:$CLASSPATH"; + +echo "cd to $bin_abs_path for workaround relative path" +cd $bin_abs_path + +echo CLASSPATH :$CLASSPATH +$JAVA $JAVA_OPTS $JAVA_DEBUG_OPT $CANAL_OPTS -classpath .:$CLASSPATH com.alibaba.otter.canal.admin.CanalAdminApplication 1>>/dev/null 2>&1 & +echo $! > $base/bin/admin.pid + +echo "cd to $current_path for continue" +cd $current_path \ No newline at end of file diff --git a/canal-admin/canal-admin-server/src/main/bin/stop.sh b/canal-admin/canal-admin-server/src/main/bin/stop.sh new file mode 100644 index 00000000..05415ad9 --- /dev/null +++ b/canal-admin/canal-admin-server/src/main/bin/stop.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +cygwin=false; +linux=false; +case "`uname`" in + CYGWIN*) + cygwin=true + ;; + Linux*) + linux=true + ;; +esac + +get_pid() { + STR=$1 + PID=$2 + if $cygwin; then + JAVA_CMD="$JAVA_HOME\bin\java" + JAVA_CMD=`cygpath --path --unix $JAVA_CMD` + JAVA_PID=`ps |grep $JAVA_CMD |awk '{print $1}'` + else + if $linux; then + if [ ! -z "$PID" ]; then + JAVA_PID=`ps -C java -f --width 1000|grep "$STR"|grep "$PID"|grep -v grep|awk '{print $2}'` + else + JAVA_PID=`ps -C java -f --width 1000|grep "$STR"|grep -v grep|awk '{print $2}'` + fi + else + if [ ! -z "$PID" ]; then + JAVA_PID=`ps aux |grep "$STR"|grep "$PID"|grep -v grep|awk '{print $2}'` + else + JAVA_PID=`ps aux |grep "$STR"|grep -v grep|awk '{print $2}'` + fi + fi + fi + echo $JAVA_PID; +} + +base=`dirname $0`/.. +pidfile=$base/bin/admin.pid +if [ ! -f "$pidfile" ];then + echo "canal-admin is not running. exists" + exit +fi + +pid=`cat $pidfile` +if [ "$pid" == "" ] ; then + pid=`get_pid "appName=canal-admin"` +fi + +echo -e "`hostname`: stopping canal $pid ... " +kill $pid + +LOOPS=0 +while (true); +do + gpid=`get_pid "appName=canal-admin" "$pid"` + if [ "$gpid" == "" ] ; then + echo "Oook! cost:$LOOPS" + `rm $pidfile` + break; + fi + let LOOPS=LOOPS+1 + sleep 1 +done \ No newline at end of file diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/WebConfig.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/WebConfig.java index fde7d6b4..07512fce 100644 --- a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/WebConfig.java +++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/config/WebConfig.java @@ -74,8 +74,8 @@ public class WebConfig implements WebMvcConfigurer { httpServletResponse.setContentType("application/json;charset=UTF-8"); PrintWriter out = httpServletResponse.getWriter(); out.print(json); - } catch (Exception e) { - e.printStackTrace(); + } catch (Throwable e) { + throw new RuntimeException(e); } return false; } @@ -84,6 +84,7 @@ public class WebConfig implements WebMvcConfigurer { } }) .addPathPatterns("/api/**") + .excludePathPatterns("/api/**/config/**") .excludePathPatterns("/api/**/user/login") .excludePathPatterns("/api/**/user/logout") .excludePathPatterns("/api/**/user/info"); diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/CanalConfigController.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/CanalConfigController.java index 1bc65b9a..3ebc392a 100644 --- a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/CanalConfigController.java +++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/CanalConfigController.java @@ -1,7 +1,12 @@ package com.alibaba.otter.canal.admin.controller; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import com.alibaba.otter.canal.admin.model.BaseModel; import com.alibaba.otter.canal.admin.model.CanalConfig; @@ -31,17 +36,6 @@ public class CanalConfigController { return BaseModel.getInstance(canalConfigService.getCanalConfig()); } - /** - * 获取配置信息摘要(无配置内容) - * - * @param env 环境变量 - * @return 配置信息摘要 - */ - @GetMapping(value = "/config/summary") - public BaseModel canalConfigSummary(@PathVariable String env) { - return BaseModel.getInstance(canalConfigService.getCanalConfigSummary()); - } - /** * 修改配置 * @@ -54,4 +48,5 @@ public class CanalConfigController { canalConfigService.updateContent(canalConfig); return BaseModel.getInstance("success"); } + } diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/PollConfigController.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/PollConfigController.java new file mode 100644 index 00000000..0ac74ef1 --- /dev/null +++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/PollConfigController.java @@ -0,0 +1,155 @@ +package com.alibaba.otter.canal.admin.controller; + +import java.security.NoSuchAlgorithmException; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.alibaba.otter.canal.admin.model.BaseModel; +import com.alibaba.otter.canal.admin.model.CanalConfig; +import com.alibaba.otter.canal.admin.model.CanalInstanceConfig; +import com.alibaba.otter.canal.admin.service.CanalConfigService; +import com.alibaba.otter.canal.admin.service.CanalInstanceService; +import com.alibaba.otter.canal.protocol.SecurityUtil; +import com.google.common.base.Joiner; + +/** + * Canal Instance配置管理控制层 + * + * @author rewerma 2019-07-13 下午05:12:16 + * @version 1.0.0 + */ +@RestController +@RequestMapping("/api/{env}/config") +public class PollConfigController { + + private static final byte[] seeds = "canal is best!".getBytes(); + + @Autowired + CanalInstanceService canalInstanceConfigService; + + @Autowired + CanalConfigService canalConfigService; + + @Value(value = "${canal.adminUser}") + String user; + + @Value(value = "${canal.adminPasswd}") + String passwd; + + /** + * 获取server全局配置 + */ + @GetMapping(value = "/server_poll") + public BaseModel canalConfigPoll(@RequestHeader String user, @RequestHeader String passwd, + @PathVariable String env, @RequestParam String md5) { + if (!auth(user, passwd)) { + throw new RuntimeException("auth :" + user + " is failed"); + } + + CanalConfig config = canalConfigService.getCanalConfig(); + if (StringUtils.isEmpty(md5)) { + return BaseModel.getInstance(config); + } else { + + try { + String newMd5 = SecurityUtil.md5String(config.getContent()); + if (StringUtils.equals(md5, newMd5)) { + config.setContent(null); + } + } catch (NoSuchAlgorithmException e) { + } + + return BaseModel.getInstance(config); + } + } + + /** + * 获取单个instance的配置 + */ + @GetMapping(value = "/instance_poll/{destination}") + public BaseModel instanceConfigPoll(@RequestHeader String user, @RequestHeader String passwd, + @PathVariable String env, + @PathVariable String destination, @RequestParam String md5) { + if (!auth(user, passwd)) { + throw new RuntimeException("auth :" + user + " is failed"); + } + + CanalInstanceConfig config = canalInstanceConfigService.findOne(destination); + if (StringUtils.isEmpty(md5)) { + return BaseModel.getInstance(config); + } else { + try { + String newMd5 = SecurityUtil.md5String(config.getContent()); + if (StringUtils.equals(md5, newMd5)) { + config.setContent(null); + } + } catch (NoSuchAlgorithmException e) { + } + + return BaseModel.getInstance(config); + } + } + + /** + * 获取对应server(ip+port)所需要运行的instance列表 + */ + @GetMapping(value = "/instances_poll") + public BaseModel instancesPoll(@RequestHeader String user, @RequestHeader String passwd, + @PathVariable String env, @RequestParam String ip, + @RequestParam String port, @RequestParam String md5) { + if (!auth(user, passwd)) { + throw new RuntimeException("auth :" + user + " is failed"); + } + + CanalInstanceConfig canalInstanceConfig = new CanalInstanceConfig(); + List configs = canalInstanceConfigService.findList(canalInstanceConfig); + List instances = configs.stream().map(config -> config.getName()).collect(Collectors.toList()); + String data = Joiner.on(',').join(instances); + canalInstanceConfig.setContent(data); + if (StringUtils.isEmpty(md5)) { + return BaseModel.getInstance(canalInstanceConfig); + } else { + try { + String newMd5 = SecurityUtil.md5String(canalInstanceConfig.getContent()); + if (StringUtils.equals(md5, newMd5)) { + canalInstanceConfig.setContent(null); + } + } catch (NoSuchAlgorithmException e) { + } + + return BaseModel.getInstance(canalInstanceConfig); + } + } + + private boolean auth(String user, String passwd) { + // 如果user/passwd密码为空,则任何用户账户都能登录 + if ((StringUtils.isEmpty(this.user) || StringUtils.equals(this.user, user))) { + if (StringUtils.isEmpty(this.passwd)) { + return true; + } else if (StringUtils.isEmpty(passwd)) { + // 如果server密码有配置,客户端密码为空,则拒绝 + return false; + } + + try { + // manager这里保存了原始密码,反过来和canal发送过来的进行校验 + byte[] passForClient = SecurityUtil.scramble411(this.passwd.getBytes(), seeds); + return SecurityUtil.scrambleServerAuth(passForClient, SecurityUtil.hexStr2Bytes(passwd), seeds); + } catch (NoSuchAlgorithmException e) { + return false; + } + } + + return false; + } +} diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/model/CanalConfig.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/model/CanalConfig.java index f9220afe..409d07e7 100644 --- a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/model/CanalConfig.java +++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/model/CanalConfig.java @@ -33,6 +33,7 @@ public class CanalConfig extends Model { private Long id; private String name; private String content; + private String status; private Date modifiedTime; public Long getId() { @@ -66,4 +67,13 @@ public class CanalConfig extends Model { public void setModifiedTime(Date modifiedTime) { this.modifiedTime = modifiedTime; } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + } diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/model/CanalInstanceConfig.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/model/CanalInstanceConfig.java index 490c0ea6..e103a1e6 100644 --- a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/model/CanalInstanceConfig.java +++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/model/CanalInstanceConfig.java @@ -2,10 +2,11 @@ package com.alibaba.otter.canal.admin.model; import io.ebean.Finder; +import java.util.Date; + import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Transient; -import java.util.Date; /** * Canal实例配置信息实体类 @@ -33,6 +34,7 @@ public class CanalInstanceConfig extends Model { private Long id; private String name; private String content; + private String status; private Date modifiedTime; @Transient @@ -64,6 +66,14 @@ public class CanalInstanceConfig extends Model { this.content = content; } + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + public Date getModifiedTime() { return modifiedTime; } diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/model/NodeServer.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/model/NodeServer.java index 20369c05..1f9834ee 100644 --- a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/model/NodeServer.java +++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/model/NodeServer.java @@ -1,13 +1,13 @@ package com.alibaba.otter.canal.admin.model; +import io.ebean.Finder; + import java.util.Date; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; -import io.ebean.Finder; - /** * 节点信息实体类 * @@ -35,13 +35,14 @@ public class NodeServer extends Model { private Long id; private String name; private String ip; - private Integer port; - private Integer port2; - private Integer status; + private Integer adminPort; + private Integer metricPort; + private Integer tcpPort; + private String status; private Date modifiedTime; public void init() { - status = -1; + status = "-1"; } public Long getId() { @@ -68,27 +69,35 @@ public class NodeServer extends Model { this.ip = ip; } - public Integer getPort() { - return port; + public Integer getAdminPort() { + return adminPort; } - public void setPort(Integer port) { - this.port = port; + public void setAdminPort(Integer adminPort) { + this.adminPort = adminPort; } - public Integer getPort2() { - return port2; + public Integer getMetricPort() { + return metricPort; } - public void setPort2(Integer port2) { - this.port2 = port2; + public void setMetricPort(Integer metricPort) { + this.metricPort = metricPort; } - public Integer getStatus() { + public Integer getTcpPort() { + return tcpPort; + } + + public void setTcpPort(Integer tcpPort) { + this.tcpPort = tcpPort; + } + + public String getStatus() { return status; } - public void setStatus(Integer status) { + public void setStatus(String status) { this.status = status; } diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/CanalInstanceService.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/CanalInstanceService.java index 5f7ae443..1bc9c29a 100644 --- a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/CanalInstanceService.java +++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/CanalInstanceService.java @@ -1,10 +1,10 @@ package com.alibaba.otter.canal.admin.service; -import com.alibaba.otter.canal.admin.model.CanalInstanceConfig; - import java.util.List; import java.util.Map; +import com.alibaba.otter.canal.admin.model.CanalInstanceConfig; + /** * Canal实例配置信息业务层接口 * @@ -19,6 +19,8 @@ public interface CanalInstanceService { CanalInstanceConfig detail(Long id); + CanalInstanceConfig findOne(String name); + void updateContent(CanalInstanceConfig canalInstanceConfig); void delete(Long id); diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalInstanceServiceImpl.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalInstanceServiceImpl.java index 659eff08..f60d767e 100644 --- a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalInstanceServiceImpl.java +++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalInstanceServiceImpl.java @@ -40,7 +40,7 @@ public class CanalInstanceServiceImpl implements CanalInstanceService { List nodeServers = NodeServer.find.query().findList(); for (NodeServer nodeServer : nodeServers) { String runningInstances = SimpleAdminConnectors.execute(nodeServer.getIp(), - nodeServer.getPort(), + nodeServer.getAdminPort(), AdminConnector::getRunningInstances); if (runningInstances == null) { continue; @@ -79,6 +79,16 @@ public class CanalInstanceServiceImpl implements CanalInstanceService { } } + @Override + public CanalInstanceConfig findOne(String name) { + CanalInstanceConfig config = CanalInstanceConfig.find.query() + .setDisableLazyLoading(true) + .where() + .eq("name", name) + .findOne(); + return config; + } + public Map remoteInstanceLog(Long id, Long nodeId) { Map result = new HashMap<>(); @@ -92,7 +102,7 @@ public class CanalInstanceServiceImpl implements CanalInstanceService { } String log = SimpleAdminConnectors.execute(nodeServer.getIp(), - nodeServer.getPort(), + nodeServer.getAdminPort(), adminConnector -> adminConnector.instanceLog(canalInstanceConfig.getName(), null, 100)); result.put("instance", canalInstanceConfig.getName()); @@ -124,11 +134,11 @@ public class CanalInstanceServiceImpl implements CanalInstanceService { Boolean resutl = null; if ("start".equals(option)) { resutl = SimpleAdminConnectors.execute(nodeServer.getIp(), - nodeServer.getPort(), + nodeServer.getAdminPort(), adminConnector -> adminConnector.startInstance(canalInstanceConfig.getName())); } else if ("stop".equals(option)) { resutl = SimpleAdminConnectors.execute(nodeServer.getIp(), - nodeServer.getPort(), + nodeServer.getAdminPort(), adminConnector -> adminConnector.stopInstance(canalInstanceConfig.getName())); } else { return false; @@ -139,4 +149,5 @@ public class CanalInstanceServiceImpl implements CanalInstanceService { } return resutl; } + } diff --git a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/impl/NodeServerServiceImpl.java b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/impl/NodeServerServiceImpl.java index d6b2ce8b..5f9610af 100644 --- a/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/impl/NodeServerServiceImpl.java +++ b/canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/impl/NodeServerServiceImpl.java @@ -31,7 +31,7 @@ public class NodeServerServiceImpl implements NodeServerService { int cnt = NodeServer.find.query() .where() .eq("ip", nodeServer.getIp()) - .eq("port", nodeServer.getPort()) + .eq("admin_port", nodeServer.getAdminPort()) .findCount(); if (cnt > 0) { throw new ServiceException("节点信息已存在"); @@ -48,14 +48,14 @@ public class NodeServerServiceImpl implements NodeServerService { int cnt = NodeServer.find.query() .where() .eq("ip", nodeServer.getIp()) - .eq("port", nodeServer.getPort()) + .eq("admin_port", nodeServer.getAdminPort()) .ne("id", nodeServer.getId()) .findCount(); if (cnt > 0) { throw new ServiceException("节点信息已存在"); } - nodeServer.update("name", "ip", "port", "port2"); + nodeServer.update("name", "ip", "admin_port", "tcp_port", "metric_port"); } public void delete(Long id) { @@ -86,8 +86,8 @@ public class NodeServerServiceImpl implements NodeServerService { // get all nodes status for (NodeServer ns : nodeServers) { futures.add(executorService.submit(() -> { - boolean status = SimpleAdminConnectors.execute(ns.getIp(), ns.getPort(), AdminConnector::check); - ns.setStatus(status ? 1 : 0); + boolean status = SimpleAdminConnectors.execute(ns.getIp(), ns.getAdminPort(), AdminConnector::check); + ns.setStatus(status ? "1" : "0"); return !status; })); } @@ -115,7 +115,7 @@ public class NodeServerServiceImpl implements NodeServerService { return ""; } return SimpleAdminConnectors.execute(nodeServer.getIp(), - nodeServer.getPort(), + nodeServer.getAdminPort(), adminConnector -> adminConnector.canalLog(100)); } @@ -126,9 +126,9 @@ public class NodeServerServiceImpl implements NodeServerService { } Boolean result = null; if ("start".equals(option)) { - result = SimpleAdminConnectors.execute(nodeServer.getIp(), nodeServer.getPort(), AdminConnector::start); + result = SimpleAdminConnectors.execute(nodeServer.getIp(), nodeServer.getAdminPort(), AdminConnector::start); } else if ("stop".equals(option)) { - result = SimpleAdminConnectors.execute(nodeServer.getIp(), nodeServer.getPort(), AdminConnector::stop); + result = SimpleAdminConnectors.execute(nodeServer.getIp(), nodeServer.getAdminPort(), AdminConnector::stop); } else { return false; } diff --git a/canal-admin/canal-admin-server/src/main/resources/application.yml b/canal-admin/canal-admin-server/src/main/resources/application.yml index d241e35a..7adc1c7a 100644 --- a/canal-admin/canal-admin-server/src/main/resources/application.yml +++ b/canal-admin/canal-admin-server/src/main/resources/application.yml @@ -13,3 +13,7 @@ spring.datasource: hikari: maximum-pool-size: 10 minimum-idle: 1 + +canal: + adminUser: admin + adminPasswd: admin diff --git a/canal-admin/canal-admin-server/src/main/resources/canal_manager.sql b/canal-admin/canal-admin-server/src/main/resources/canal_manager.sql index 9ca6de4f..a926380d 100644 --- a/canal-admin/canal-admin-server/src/main/resources/canal_manager.sql +++ b/canal-admin/canal-admin-server/src/main/resources/canal_manager.sql @@ -13,10 +13,11 @@ CREATE TABLE `canal_adapter_config` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `category` varchar(45) NOT NULL, `name` varchar(45) NOT NULL, + `status` varchar(45) DEFAULT NULL, `content` text NOT NULL, `modified_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Table structure for canal_config @@ -25,11 +26,12 @@ DROP TABLE IF EXISTS `canal_config`; CREATE TABLE `canal_config` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, + `status` varchar(45) DEFAULT NULL, `content` text NOT NULL, `modified_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `name_UNIQUE` (`name`) -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Table structure for canal_instance_config @@ -38,11 +40,12 @@ DROP TABLE IF EXISTS `canal_instance_config`; CREATE TABLE `canal_instance_config` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, + `status` varchar(45) DEFAULT NULL, `content` text NOT NULL, `modified_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `name_UNIQUE` (`name`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Table structure for canal_node_server @@ -52,9 +55,10 @@ CREATE TABLE `canal_node_server` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(63) NOT NULL, `ip` varchar(63) NOT NULL, - `port` int(11) DEFAULT NULL, - `port2` int(11) DEFAULT NULL, - `status` int(11) NOT NULL, + `admin_port` int(11) DEFAULT NULL, + `tcp_port` int(11) DEFAULT NULL, + `metric_port` int(11) DEFAULT NULL, + `status` varchar(45) DEFAULT NULL, `modified_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4; @@ -73,7 +77,7 @@ CREATE TABLE `canal_user` ( `avatar` varchar(255) DEFAULT NULL, `creation_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Records of canal_user diff --git a/canal-admin/canal-admin-server/src/main/resources/public/index.html b/canal-admin/canal-admin-server/src/main/resources/public/index.html index b76917f2..6f6beecc 100644 --- a/canal-admin/canal-admin-server/src/main/resources/public/index.html +++ b/canal-admin/canal-admin-server/src/main/resources/public/index.html @@ -1 +1 @@ -Canal Admin
\ No newline at end of file +Canal Admin
\ No newline at end of file diff --git a/canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-e1a839e4.7ee86dd8.js b/canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-e1a839e4.7ee86dd8.js deleted file mode 100644 index 33f85501..00000000 --- a/canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-e1a839e4.7ee86dd8.js +++ /dev/null @@ -1 +0,0 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-e1a839e4"],{"9f66":function(e,t,n){"use strict";n.r(t);var r=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"app-container"},[n("div",{staticClass:"filter-container"},[n("el-button",{staticClass:"filter-item",attrs:{type:"primary"},on:{click:function(t){return e.handleCreate()}}},[e._v("新建Server")]),e._v(" "),n("el-button",{staticClass:"filter-item",attrs:{type:"info"},on:{click:function(t){return e.fetchData()}}},[e._v("刷新列表")])],1),e._v(" "),n("el-table",{directives:[{name:"loading",rawName:"v-loading",value:e.listLoading,expression:"listLoading"}],attrs:{data:e.list,"element-loading-text":"Loading",border:"",fit:"","highlight-current-row":""}},[n("el-table-column",{attrs:{label:"Server 名称","min-width":"200",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.name)+"\n ")]}}])}),e._v(" "),n("el-table-column",{attrs:{label:"Server IP","min-width":"200",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[n("span",[e._v(e._s(t.row.ip))])]}}])}),e._v(" "),n("el-table-column",{attrs:{label:"Admin 端口","min-width":"100",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.port)+"\n ")]}}])}),e._v(" "),n("el-table-column",{attrs:{label:"监控端口","min-width":"100",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.port2)+"\n ")]}}])}),e._v(" "),n("el-table-column",{attrs:{"class-name":"status-col",label:"状态","min-width":"150",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[n("el-tag",{attrs:{type:e._f("statusFilter")(t.row.status)}},[e._v(e._s(e._f("statusLabel")(t.row.status)))])]}}])}),e._v(" "),n("el-table-column",{attrs:{align:"center",prop:"created_at",label:"操作","min-width":"150"},scopedSlots:e._u([{key:"default",fn:function(t){return[n("el-dropdown",{attrs:{trigger:"click"}},[n("el-button",{attrs:{type:"primary",size:"mini"}},[e._v("\n 操作"),n("i",{staticClass:"el-icon-arrow-down el-icon--right"})]),e._v(" "),n("el-dropdown-menu",{attrs:{slot:"dropdown"},slot:"dropdown"},[n("el-dropdown-item",{nativeOn:{click:function(n){return e.handleUpdate(t.row)}}},[e._v("修改")]),e._v(" "),n("el-dropdown-item",{nativeOn:{click:function(n){return e.handleDelete(t.row)}}},[e._v("删除")]),e._v(" "),n("el-dropdown-item",{nativeOn:{click:function(n){return e.handleStart(t.row)}}},[e._v("启动")]),e._v(" "),n("el-dropdown-item",{nativeOn:{click:function(n){return e.handleStop(t.row)}}},[e._v("停止")]),e._v(" "),n("el-dropdown-item",{nativeOn:{click:function(n){return e.handleLog(t.row)}}},[e._v("日志")])],1)],1)]}}])})],1),e._v(" "),n("el-dialog",{attrs:{visible:e.dialogFormVisible,title:e.textMap[e.dialogStatus],width:"600px"},on:{"update:visible":function(t){e.dialogFormVisible=t}}},[n("el-form",{ref:"dataForm",staticStyle:{width:"400px","margin-left":"30px"},attrs:{rules:e.rules,model:e.nodeModel,"label-position":"left","label-width":"120px"}},[n("el-form-item",{attrs:{label:"Server 名称",prop:"name"}},[n("el-input",{model:{value:e.nodeModel.name,callback:function(t){e.$set(e.nodeModel,"name",t)},expression:"nodeModel.name"}})],1),e._v(" "),n("el-form-item",{attrs:{label:"Server IP",prop:"ip"}},[n("el-input",{model:{value:e.nodeModel.ip,callback:function(t){e.$set(e.nodeModel,"ip",t)},expression:"nodeModel.ip"}})],1),e._v(" "),n("el-form-item",{attrs:{label:"Admin 端口",prop:"port"}},[n("el-input",{attrs:{placeholder:"11110",type:"number"},model:{value:e.nodeModel.port,callback:function(t){e.$set(e.nodeModel,"port",t)},expression:"nodeModel.port"}})],1),e._v(" "),n("el-form-item",{attrs:{label:"监控端口",prop:"port2"}},[n("el-input",{attrs:{placeholder:"11112",type:"number"},model:{value:e.nodeModel.port2,callback:function(t){e.$set(e.nodeModel,"port2",t)},expression:"nodeModel.port2"}})],1)],1),e._v(" "),n("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[n("el-button",{on:{click:function(t){e.dialogFormVisible=!1}}},[e._v("取消")]),e._v(" "),n("el-button",{attrs:{type:"primary"},on:{click:function(t){return e.dataOperation()}}},[e._v("确定")])],1)],1)],1)},o=[],a=n("c6ed"),i={filters:{statusFilter:function(e){var t={1:"success",0:"gray","-1":"danger"};return t[e]},statusLabel:function(e){var t={1:"启动",0:"停止","-1":"断开"};return t[e]}},data:function(){return{list:null,listLoading:!0,listQuery:{name:"",ip:""},dialogFormVisible:!1,textMap:{create:"新建Server信息",update:"修改Server信息"},nodeModel:{id:void 0,name:null,ip:null,port:11110,port2:11112},rules:{name:[{required:!0,message:"Server 名称不能为空",trigger:"change"}],ip:[{required:!0,message:"Server IP不能为空",trigger:"change"}],port:[{required:!0,message:"Server Admin端口不能为空",trigger:"change"}]},dialogStatus:"create"}},created:function(){this.fetchData()},methods:{fetchData:function(){var e=this;this.listLoading=!0,Object(a["c"])(this.listQuery).then(function(t){e.list=t.data,e.listLoading=!1})},resetModel:function(){this.nodeModel={id:void 0,name:null,ip:null,port:null,port2:null}},handleCreate:function(){var e=this;this.resetModel(),this.dialogStatus="create",this.dialogFormVisible=!0,this.$nextTick(function(){e.$refs["dataForm"].clearValidate()})},dataOperation:function(){var e=this;this.$refs["dataForm"].validate(function(t){t&&("create"===e.dialogStatus&&Object(a["a"])(e.nodeModel).then(function(t){e.operationRes(t)}),"update"===e.dialogStatus&&Object(a["g"])(e.nodeModel).then(function(t){e.operationRes(t)}))})},operationRes:function(e){"success"===e.data?(this.fetchData(),this.dialogFormVisible=!1,this.$message({message:this.textMap[this.dialogStatus]+"成功",type:"success"})):this.$message({message:this.textMap[this.dialogStatus]+"失败",type:"error"})},handleUpdate:function(e){var t=this;this.resetModel(),this.nodeModel=Object.assign({},e),this.dialogStatus="update",this.dialogFormVisible=!0,this.$nextTick(function(){t.$refs["dataForm"].clearValidate()})},handleDelete:function(e){var t=this;this.$confirm("删除Server信息并不会导致节点服务停止","确定删除Server信息",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}).then(function(){Object(a["b"])(e.id).then(function(e){"success"===e.data?(t.fetchData(),t.$message({message:"删除Server信息成功",type:"success"})):t.$message({message:"删除Server信息失败",type:"error"})})})},handleStart:function(e){var t=this;0===e.status?this.$confirm("启动Server服务","确定启动Server服务",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}).then(function(){Object(a["e"])(e.id).then(function(e){e.data?(t.fetchData(),t.$message({message:"启动成功",type:"success"})):t.$message({message:"启动Server服务出现异常",type:"error"})})}):this.$message({message:"当前Server不是停止状态,无法启动",type:"error"})},handleStop:function(e){var t=this;1===e.status?this.$confirm("停止 Server 服务","确定停止Server服务",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}).then(function(){Object(a["f"])(e.id).then(function(e){e.data?(t.fetchData(),t.$message({message:"停止成功",type:"success"})):t.$message({message:"停止Server服务出现异常",type:"error"})})}):this.$message({message:"当前Server不是启动状态,无法停止",type:"error"})},handleLog:function(e){this.$router.push("nodeServer/log?id="+e.id)}}},l=i,s=n("2877"),d=Object(s["a"])(l,r,o,!1,null,null,null);t["default"]=d.exports},c6ed:function(e,t,n){"use strict";n.d(t,"c",function(){return o}),n.d(t,"a",function(){return a}),n.d(t,"g",function(){return i}),n.d(t,"b",function(){return l}),n.d(t,"e",function(){return s}),n.d(t,"f",function(){return d}),n.d(t,"d",function(){return u});var r=n("b775");function o(e){return Object(r["a"])({url:"/nodeServers",method:"get",params:e})}function a(e){return Object(r["a"])({url:"/nodeServer",method:"post",data:e})}function i(e){return Object(r["a"])({url:"/nodeServer",method:"put",data:e})}function l(e){return Object(r["a"])({url:"/nodeServer/"+e,method:"delete"})}function s(e){return Object(r["a"])({url:"/nodeServer/start/"+e,method:"put"})}function d(e){return Object(r["a"])({url:"/nodeServer/stop/"+e,method:"put"})}function u(e){return Object(r["a"])({url:"/nodeServer/log/"+e,method:"get"})}}}]); \ No newline at end of file diff --git a/canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-e1a839e4.e9eb1b06.js b/canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-e1a839e4.e9eb1b06.js new file mode 100644 index 00000000..33ec1b50 --- /dev/null +++ b/canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-e1a839e4.e9eb1b06.js @@ -0,0 +1 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-e1a839e4"],{"9f66":function(e,t,n){"use strict";n.r(t);var r=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"app-container"},[n("div",{staticClass:"filter-container"},[n("el-button",{staticClass:"filter-item",attrs:{type:"primary"},on:{click:function(t){return e.handleCreate()}}},[e._v("新建Server")]),e._v(" "),n("el-button",{staticClass:"filter-item",attrs:{type:"info"},on:{click:function(t){return e.fetchData()}}},[e._v("刷新列表")])],1),e._v(" "),n("el-table",{directives:[{name:"loading",rawName:"v-loading",value:e.listLoading,expression:"listLoading"}],attrs:{data:e.list,"element-loading-text":"Loading",border:"",fit:"","highlight-current-row":""}},[n("el-table-column",{attrs:{label:"Server 名称","min-width":"200",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.name)+"\n ")]}}])}),e._v(" "),n("el-table-column",{attrs:{label:"Server IP","min-width":"200",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[n("span",[e._v(e._s(t.row.ip))])]}}])}),e._v(" "),n("el-table-column",{attrs:{label:"admin 端口","min-width":"100",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.adminPort)+"\n ")]}}])}),e._v(" "),n("el-table-column",{attrs:{label:"tcp 端口","min-width":"100",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.tcpPort)+"\n ")]}}])}),e._v(" "),n("el-table-column",{attrs:{label:"metric 端口","min-width":"100",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.metricPort)+"\n ")]}}])}),e._v(" "),n("el-table-column",{attrs:{"class-name":"status-col",label:"状态","min-width":"150",align:"center"},scopedSlots:e._u([{key:"default",fn:function(t){return[n("el-tag",{attrs:{type:e._f("statusFilter")(t.row.status)}},[e._v(e._s(e._f("statusLabel")(t.row.status)))])]}}])}),e._v(" "),n("el-table-column",{attrs:{align:"center",prop:"created_at",label:"操作","min-width":"150"},scopedSlots:e._u([{key:"default",fn:function(t){return[n("el-dropdown",{attrs:{trigger:"click"}},[n("el-button",{attrs:{type:"primary",size:"mini"}},[e._v("\n 操作"),n("i",{staticClass:"el-icon-arrow-down el-icon--right"})]),e._v(" "),n("el-dropdown-menu",{attrs:{slot:"dropdown"},slot:"dropdown"},[n("el-dropdown-item",{nativeOn:{click:function(n){return e.handleUpdate(t.row)}}},[e._v("修改")]),e._v(" "),n("el-dropdown-item",{nativeOn:{click:function(n){return e.handleDelete(t.row)}}},[e._v("删除")]),e._v(" "),n("el-dropdown-item",{nativeOn:{click:function(n){return e.handleStart(t.row)}}},[e._v("启动")]),e._v(" "),n("el-dropdown-item",{nativeOn:{click:function(n){return e.handleStop(t.row)}}},[e._v("停止")]),e._v(" "),n("el-dropdown-item",{nativeOn:{click:function(n){return e.handleLog(t.row)}}},[e._v("日志")])],1)],1)]}}])})],1),e._v(" "),n("el-dialog",{attrs:{visible:e.dialogFormVisible,title:e.textMap[e.dialogStatus],width:"600px"},on:{"update:visible":function(t){e.dialogFormVisible=t}}},[n("el-form",{ref:"dataForm",staticStyle:{width:"400px","margin-left":"30px"},attrs:{rules:e.rules,model:e.nodeModel,"label-position":"left","label-width":"120px"}},[n("el-form-item",{attrs:{label:"Server 名称",prop:"name"}},[n("el-input",{model:{value:e.nodeModel.name,callback:function(t){e.$set(e.nodeModel,"name",t)},expression:"nodeModel.name"}})],1),e._v(" "),n("el-form-item",{attrs:{label:"Server IP",prop:"ip"}},[n("el-input",{model:{value:e.nodeModel.ip,callback:function(t){e.$set(e.nodeModel,"ip",t)},expression:"nodeModel.ip"}})],1),e._v(" "),n("el-form-item",{attrs:{label:"admin 端口",prop:"adminPort"}},[n("el-input",{attrs:{placeholder:"11110",type:"number"},model:{value:e.nodeModel.adminPort,callback:function(t){e.$set(e.nodeModel,"adminPort",t)},expression:"nodeModel.adminPort"}})],1),e._v(" "),n("el-form-item",{attrs:{label:"tcp 端口",prop:"tcpPort"}},[n("el-input",{attrs:{placeholder:"11111",type:"number"},model:{value:e.nodeModel.tcpPort,callback:function(t){e.$set(e.nodeModel,"tcpPort",t)},expression:"nodeModel.tcpPort"}})],1),e._v(" "),n("el-form-item",{attrs:{label:"metric 端口",prop:"metricPort"}},[n("el-input",{attrs:{placeholder:"11112",type:"number"},model:{value:e.nodeModel.metricPort,callback:function(t){e.$set(e.nodeModel,"metricPort",t)},expression:"nodeModel.metricPort"}})],1)],1),e._v(" "),n("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[n("el-button",{on:{click:function(t){e.dialogFormVisible=!1}}},[e._v("取消")]),e._v(" "),n("el-button",{attrs:{type:"primary"},on:{click:function(t){return e.dataOperation()}}},[e._v("确定")])],1)],1)],1)},o=[],a=n("c6ed"),i={filters:{statusFilter:function(e){var t={1:"success",0:"gray","-1":"danger"};return t[e]},statusLabel:function(e){var t={1:"启动",0:"停止","-1":"断开"};return t[e]}},data:function(){return{list:null,listLoading:!0,listQuery:{name:"",ip:""},dialogFormVisible:!1,textMap:{create:"新建Server信息",update:"修改Server信息"},nodeModel:{id:void 0,name:null,ip:null,adminPort:11110,tcpPort:11111,metricPort:11112},rules:{name:[{required:!0,message:"Server 名称不能为空",trigger:"change"}],ip:[{required:!0,message:"Server IP不能为空",trigger:"change"}],port:[{required:!0,message:"Server admin端口不能为空",trigger:"change"}]},dialogStatus:"create"}},created:function(){this.fetchData()},methods:{fetchData:function(){var e=this;this.listLoading=!0,Object(a["c"])(this.listQuery).then(function(t){e.list=t.data,e.listLoading=!1})},resetModel:function(){this.nodeModel={id:void 0,name:null,ip:null,adminPort:null,tcpPort:null,metricPort:null}},handleCreate:function(){var e=this;this.resetModel(),this.dialogStatus="create",this.dialogFormVisible=!0,this.$nextTick(function(){e.$refs["dataForm"].clearValidate()})},dataOperation:function(){var e=this;this.$refs["dataForm"].validate(function(t){t&&("create"===e.dialogStatus&&Object(a["a"])(e.nodeModel).then(function(t){e.operationRes(t)}),"update"===e.dialogStatus&&Object(a["g"])(e.nodeModel).then(function(t){e.operationRes(t)}))})},operationRes:function(e){"success"===e.data?(this.fetchData(),this.dialogFormVisible=!1,this.$message({message:this.textMap[this.dialogStatus]+"成功",type:"success"})):this.$message({message:this.textMap[this.dialogStatus]+"失败",type:"error"})},handleUpdate:function(e){var t=this;this.resetModel(),this.nodeModel=Object.assign({},e),this.dialogStatus="update",this.dialogFormVisible=!0,this.$nextTick(function(){t.$refs["dataForm"].clearValidate()})},handleDelete:function(e){var t=this;this.$confirm("删除Server信息并不会导致节点服务停止","确定删除Server信息",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}).then(function(){Object(a["b"])(e.id).then(function(e){"success"===e.data?(t.fetchData(),t.$message({message:"删除Server信息成功",type:"success"})):t.$message({message:"删除Server信息失败",type:"error"})})})},handleStart:function(e){var t=this;"0"===e.status?this.$confirm("启动Server服务","确定启动Server服务",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}).then(function(){Object(a["e"])(e.id).then(function(e){e.data?(t.fetchData(),t.$message({message:"启动成功",type:"success"})):t.$message({message:"启动Server服务出现异常",type:"error"})})}):this.$message({message:"当前Server不是停止状态,无法启动",type:"error"})},handleStop:function(e){var t=this;"1"===e.status?this.$confirm("停止 Server 服务","确定停止Server服务",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}).then(function(){Object(a["f"])(e.id).then(function(e){e.data?(t.fetchData(),t.$message({message:"停止成功",type:"success"})):t.$message({message:"停止Server服务出现异常",type:"error"})})}):this.$message({message:"当前Server不是启动状态,无法停止",type:"error"})},handleLog:function(e){this.$router.push("nodeServer/log?id="+e.id)}}},l=i,s=n("2877"),c=Object(s["a"])(l,r,o,!1,null,null,null);t["default"]=c.exports},c6ed:function(e,t,n){"use strict";n.d(t,"c",function(){return o}),n.d(t,"a",function(){return a}),n.d(t,"g",function(){return i}),n.d(t,"b",function(){return l}),n.d(t,"e",function(){return s}),n.d(t,"f",function(){return c}),n.d(t,"d",function(){return d});var r=n("b775");function o(e){return Object(r["a"])({url:"/nodeServers",method:"get",params:e})}function a(e){return Object(r["a"])({url:"/nodeServer",method:"post",data:e})}function i(e){return Object(r["a"])({url:"/nodeServer",method:"put",data:e})}function l(e){return Object(r["a"])({url:"/nodeServer/"+e,method:"delete"})}function s(e){return Object(r["a"])({url:"/nodeServer/start/"+e,method:"put"})}function c(e){return Object(r["a"])({url:"/nodeServer/stop/"+e,method:"put"})}function d(e){return Object(r["a"])({url:"/nodeServer/log/"+e,method:"get"})}}}]); \ No newline at end of file diff --git a/canal-admin/canal-admin-ui/src/views/canalServer/NodeServer.vue b/canal-admin/canal-admin-ui/src/views/canalServer/NodeServer.vue index c639547f..cdc05369 100644 --- a/canal-admin/canal-admin-ui/src/views/canalServer/NodeServer.vue +++ b/canal-admin/canal-admin-ui/src/views/canalServer/NodeServer.vue @@ -25,14 +25,19 @@ {{ scope.row.ip }} - + - + + + + @@ -65,11 +70,14 @@ - - + + - - + + + + +