From 24d1e4aec7c52f4c50b547346501e06c2930bf52 Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Thu, 5 Dec 2019 15:38:45 +0800 Subject: [PATCH 001/238] change azkaban load from appjoint --- .../service/impl/ApplicationServiceImpl.java | 7 +- dss-azkaban-scheduler-appjoint/pom.xml | 43 +++++- .../src/main/assembly/distribution.xml | 136 ++++++++++++++++++ .../azkaban/AzkabanSchedulerAppJoint.java | 49 ++++--- .../hooks/LinkisAzkabanFlowPublishHook.java | 11 +- .../hooks/LinkisAzkabanNodePublishHook.java | 11 +- .../LinkisAzkabanProjectPublishHook.java | 10 +- .../linkisjob/AzkabanSubFlowJobTuning.java | 4 +- .../azkaban/linkisjob/LinkisJobConverter.java | 10 +- .../azkaban/parser/AzkabanFlowParser.java | 15 +- .../azkaban/parser/AzkabanProjectParser.java | 11 +- .../parser/LinkisAzkabanNodeParser.java | 2 - .../LinkisAzkabanSendEmailNodeParser.java | 4 +- .../azkaban/tuning/AzkabanProjectTuning.java | 16 ++- .../tuning/LinkisAzkabanFlowTuning.java | 4 - .../tuning/LinkisShareNodeFlowTuning.java | 4 +- .../src/main/resources/appjoint.properties | 21 +++ .../src/main/resources/log4j.properties | 37 +++++ .../src/main/resources/log4j2.xml | 39 +++++ .../appjoint/scheduler/SchedulerAppJoint.java | 9 ++ dss-server/pom.xml | 35 +++-- .../service/impl/DWSProjectServiceImpl.java | 107 ++++++++------ 22 files changed, 454 insertions(+), 131 deletions(-) create mode 100644 dss-azkaban-scheduler-appjoint/src/main/assembly/distribution.xml create mode 100644 dss-azkaban-scheduler-appjoint/src/main/resources/appjoint.properties create mode 100644 dss-azkaban-scheduler-appjoint/src/main/resources/log4j.properties create mode 100644 dss-azkaban-scheduler-appjoint/src/main/resources/log4j2.xml diff --git a/dss-application/src/main/java/com/webank/wedatasphere/dss/application/service/impl/ApplicationServiceImpl.java b/dss-application/src/main/java/com/webank/wedatasphere/dss/application/service/impl/ApplicationServiceImpl.java index 36fcde3eb..271acac86 100644 --- a/dss-application/src/main/java/com/webank/wedatasphere/dss/application/service/impl/ApplicationServiceImpl.java +++ b/dss-application/src/main/java/com/webank/wedatasphere/dss/application/service/impl/ApplicationServiceImpl.java @@ -65,7 +65,12 @@ public class ApplicationServiceImpl implements ApplicationService { @Override public AppJoint getAppjoint(String nodeType) throws AppJointErrorException { - Application application = getApplicationbyNodeType(nodeType); + Application application; + if(nodeType.equals("schedulis")){ + application = getApplication(nodeType); + }else { + application = getApplicationbyNodeType(nodeType); + } AppJoint appJoint = null; try { appJoint = loadAppjoint(application); diff --git a/dss-azkaban-scheduler-appjoint/pom.xml b/dss-azkaban-scheduler-appjoint/pom.xml index 56215f52f..05518dcf9 100644 --- a/dss-azkaban-scheduler-appjoint/pom.xml +++ b/dss-azkaban-scheduler-appjoint/pom.xml @@ -29,15 +29,17 @@ dss-azkaban-scheduler-appjoint - - org.springframework.boot - spring-boot-autoconfigure - 2.0.3.RELEASE - + + + + + com.webank.wedatasphere.dss dss-scheduler-appjoint-core ${dss.version} + provided + true org.apache.httpcomponents @@ -48,6 +50,8 @@ com.webank.wedatasphere.dss dss-application ${dss.version} + provided + true @@ -66,6 +70,35 @@ org.apache.maven.plugins maven-jar-plugin + + org.apache.maven.plugins + maven-assembly-plugin + 2.3 + false + + + make-assembly + package + + single + + + + src/main/assembly/distribution.xml + + + + + + false + dss-azkaban-appjoint + false + false + + src/main/assembly/distribution.xml + + + diff --git a/dss-azkaban-scheduler-appjoint/src/main/assembly/distribution.xml b/dss-azkaban-scheduler-appjoint/src/main/assembly/distribution.xml new file mode 100644 index 000000000..289856124 --- /dev/null +++ b/dss-azkaban-scheduler-appjoint/src/main/assembly/distribution.xml @@ -0,0 +1,136 @@ + + + + dss-azkaban-appjoint + + zip + + true + schedulis + + + + + + lib + true + true + false + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${basedir}/src/main/resources + + appjoint.properties + + 0777 + / + unix + + + + ${basedir}/src/main/resources + + log4j.properties + log4j2.xml + + 0777 + conf + unix + + + + + + diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/AzkabanSchedulerAppJoint.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/AzkabanSchedulerAppJoint.java index 9a062d5c9..8f6e4bb8a 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/AzkabanSchedulerAppJoint.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/AzkabanSchedulerAppJoint.java @@ -2,33 +2,34 @@ package com.webank.wedatasphere.dss.appjoint.scheduler.azkaban; import com.webank.wedatasphere.dss.appjoint.scheduler.SchedulerAppJoint; import com.webank.wedatasphere.dss.appjoint.scheduler.azkaban.conf.AzkabanConf; +import com.webank.wedatasphere.dss.appjoint.scheduler.azkaban.hooks.LinkisAzkabanProjectPublishHook; +import com.webank.wedatasphere.dss.appjoint.scheduler.azkaban.parser.AzkabanProjectParser; +import com.webank.wedatasphere.dss.appjoint.scheduler.azkaban.tuning.AzkabanProjectTuning; +import com.webank.wedatasphere.dss.appjoint.scheduler.hooks.ProjectPublishHook; +import com.webank.wedatasphere.dss.appjoint.scheduler.parser.ProjectParser; import com.webank.wedatasphere.dss.appjoint.scheduler.service.SchedulerProjectService; import com.webank.wedatasphere.dss.appjoint.scheduler.service.SchedulerSecurityService; import com.webank.wedatasphere.dss.appjoint.scheduler.azkaban.service.AzkabanProjectService; import com.webank.wedatasphere.dss.appjoint.scheduler.azkaban.service.AzkabanSecurityService; -import com.webank.wedatasphere.dss.application.entity.Application; +import com.webank.wedatasphere.dss.appjoint.scheduler.tuning.ProjectTuning; +import com.webank.wedatasphere.dss.appjoint.service.AppJointUrlImpl; import com.webank.wedatasphere.dss.application.service.ApplicationService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; - -import javax.annotation.PostConstruct; import java.io.IOException; import java.util.Map; /** * Created by cooperyang on 2019/9/16. */ -@Component -public final class AzkabanSchedulerAppJoint implements SchedulerAppJoint { + +public final class AzkabanSchedulerAppJoint extends AppJointUrlImpl implements SchedulerAppJoint { private static final Logger LOGGER = LoggerFactory.getLogger(AzkabanSchedulerAppJoint.class); private SchedulerSecurityService securityService; private SchedulerProjectService projectService; - @Autowired private ApplicationService applicationService; @Override @@ -36,25 +37,17 @@ public final class AzkabanSchedulerAppJoint implements SchedulerAppJoint { return "schedulis"; } - @PostConstruct - public void beforeInit(){ - Application schedulis = applicationService.getApplication("schedulis"); - String basicUrl = null; - if(schedulis != null){ - basicUrl = schedulis.getUrl(); - } + + @Override + public void init(String basicUrl, Map params) { LOGGER.info("read schedulerAppJoint url from db{}",basicUrl); if(StringUtils.isEmpty(basicUrl)){ basicUrl = AzkabanConf.AZKABAN_BASE_URL.getValue(); LOGGER.warn("basic url in db is empty,read it from conf{}",basicUrl); } - init(basicUrl,null); - } - - @Override - public void init(String basicUrl, Map params) { securityService = new AzkabanSecurityService(); securityService.setBaseUrl(basicUrl); + projectService = new AzkabanProjectService(); projectService.setBaseUrl(basicUrl); } @@ -64,6 +57,22 @@ public final class AzkabanSchedulerAppJoint implements SchedulerAppJoint { return this.securityService; } + @Override + public ProjectParser getProjectParser() { + return new AzkabanProjectParser(); + } + + @Override + public ProjectTuning getProjectTuning() { + return new AzkabanProjectTuning(); + } + + @Override + public ProjectPublishHook[] getProjectPublishHooks() { + ProjectPublishHook[] projectPublishHooks = {new LinkisAzkabanProjectPublishHook()}; + return projectPublishHooks; + } + @Override public SchedulerProjectService getProjectService() { return this.projectService; diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/hooks/LinkisAzkabanFlowPublishHook.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/hooks/LinkisAzkabanFlowPublishHook.java index 813c30e26..73cec2164 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/hooks/LinkisAzkabanFlowPublishHook.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/hooks/LinkisAzkabanFlowPublishHook.java @@ -13,9 +13,6 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - import java.io.File; import java.io.FileOutputStream; import java.util.List; @@ -24,11 +21,15 @@ import java.util.Map; /** * Created by allenlliu on 2019/9/20. */ -@Component + public class LinkisAzkabanFlowPublishHook extends AbstractFlowPublishHook { private static final Logger LOGGER = LoggerFactory.getLogger(LinkisAzkabanFlowPublishHook.class); + public LinkisAzkabanFlowPublishHook(){ + NodePublishHook[] nodePublishHooks = {new LinkisAzkabanNodePublishHook()}; + setNodeHooks(nodePublishHooks); + } @Override public void prePublish(SchedulerFlow flow) throws DSSErrorException { @@ -102,7 +103,7 @@ public class LinkisAzkabanFlowPublishHook extends AbstractFlowPublishHook { super.postPublish(flow); } - @Autowired + @Override public void setNodeHooks(NodePublishHook[] nodePublishHooks) { super.setNodeHooks(nodePublishHooks); diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/hooks/LinkisAzkabanNodePublishHook.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/hooks/LinkisAzkabanNodePublishHook.java index 1e3480248..852f9a817 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/hooks/LinkisAzkabanNodePublishHook.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/hooks/LinkisAzkabanNodePublishHook.java @@ -13,21 +13,20 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - import java.io.File; import java.io.FileOutputStream; import java.util.List; -@Component + public class LinkisAzkabanNodePublishHook extends AbstractNodePublishHook { private static final Logger LOGGER = LoggerFactory.getLogger(LinkisAzkabanNodePublishHook.class); - - @Autowired private LinkisJobConverter linkisJobConverter; + public LinkisAzkabanNodePublishHook(){ + this.linkisJobConverter = new LinkisJobConverter(); + } + @Override public void prePublish(SchedulerNode schedulerNode) throws DSSErrorException { writeNodeTojobLocal(schedulerNode); diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/hooks/LinkisAzkabanProjectPublishHook.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/hooks/LinkisAzkabanProjectPublishHook.java index 6e9b164c1..e6eb9dd62 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/hooks/LinkisAzkabanProjectPublishHook.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/hooks/LinkisAzkabanProjectPublishHook.java @@ -14,9 +14,6 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; @@ -25,13 +22,16 @@ import java.util.List; /** * Created by cooperyang on 2019/9/18 */ -@Component + public class LinkisAzkabanProjectPublishHook extends AbstractProjectPublishHook { private static final Logger LOGGER = LoggerFactory.getLogger( LinkisAzkabanProjectPublishHook.class); + public LinkisAzkabanProjectPublishHook(){ + FlowPublishHook[] flowPublishHooks = {new LinkisAzkabanFlowPublishHook()}; + setFlowPublishHooks(flowPublishHooks); + } @Override - @Autowired public void setFlowPublishHooks(FlowPublishHook[] flowPublishHooks) { super.setFlowPublishHooks(flowPublishHooks); } diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/linkisjob/AzkabanSubFlowJobTuning.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/linkisjob/AzkabanSubFlowJobTuning.java index d7028ccea..4b31aa9dd 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/linkisjob/AzkabanSubFlowJobTuning.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/linkisjob/AzkabanSubFlowJobTuning.java @@ -1,11 +1,11 @@ package com.webank.wedatasphere.dss.appjoint.scheduler.azkaban.linkisjob; -import org.springframework.stereotype.Component; + /** * Created by cooperyang on 2019/11/1. */ -@Component + public class AzkabanSubFlowJobTuning implements LinkisJobTuning { @Override diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/linkisjob/LinkisJobConverter.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/linkisjob/LinkisJobConverter.java index 6f497c8cd..b13044c6d 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/linkisjob/LinkisJobConverter.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/linkisjob/LinkisJobConverter.java @@ -7,9 +7,6 @@ import com.webank.wedatasphere.dss.appjoint.scheduler.azkaban.entity.LinkisAzkab import com.webank.wedatasphere.dss.appjoint.scheduler.azkaban.entity.LinkisAzkabanShareNode; import com.webank.wedatasphere.dss.appjoint.scheduler.constant.SchedulerAppJointConstant; import org.apache.commons.lang.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -18,10 +15,13 @@ import java.util.Map; /** * Created by cooperyang on 2019/11/1. */ -@Component + public class LinkisJobConverter { - @Autowired + public LinkisJobConverter(){ + LinkisJobTuning[] linkisJobTunings = {new AzkabanSubFlowJobTuning()}; + this.linkisJobTunings = linkisJobTunings; + } private LinkisJobTuning[] linkisJobTunings; public String conversion(LinkisAzkabanSchedulerNode schedulerNode){ diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/AzkabanFlowParser.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/AzkabanFlowParser.java index 57934278d..3da66206d 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/AzkabanFlowParser.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/AzkabanFlowParser.java @@ -5,19 +5,26 @@ import com.webank.wedatasphere.dss.appjoint.scheduler.parser.NodeParser; import com.webank.wedatasphere.dss.appjoint.scheduler.azkaban.entity.AzkabanSchedulerFlow; import com.webank.wedatasphere.dss.common.entity.flow.DWSJSONFlow; import com.webank.wedatasphere.dss.appjoint.scheduler.entity.SchedulerFlow; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; +import java.util.ArrayList; + -@Component public class AzkabanFlowParser extends AbstractFlowParser { + public AzkabanFlowParser(){ + ArrayList list = new ArrayList<>(); + list.add(new LinkisAzkabanNodeParser()); + list.add(new LinkisAzkabanSendEmailNodeParser()); + NodeParser[] nodeParsers =new NodeParser[list.size()]; + list.toArray(nodeParsers); + setNodeParsers(nodeParsers); + } + @Override protected SchedulerFlow createSchedulerFlow() { return new AzkabanSchedulerFlow(); } @Override - @Autowired public void setNodeParsers(NodeParser[] nodeParsers) { super.setNodeParsers(nodeParsers); } diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/AzkabanProjectParser.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/AzkabanProjectParser.java index 14952e465..3895d7c68 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/AzkabanProjectParser.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/AzkabanProjectParser.java @@ -6,15 +6,17 @@ import com.webank.wedatasphere.dss.appjoint.scheduler.parser.AbstractProjectPars import com.webank.wedatasphere.dss.appjoint.scheduler.parser.FlowParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - /** * Created by allenlliu on 2019/9/16. */ -@Component + public class AzkabanProjectParser extends AbstractProjectParser { + public AzkabanProjectParser(){ + FlowParser[] flowParsers = {new AzkabanFlowParser()}; + setFlowParsers(flowParsers); + } + private static final Logger logger = LoggerFactory.getLogger(AzkabanProjectParser.class); @Override @@ -23,7 +25,6 @@ public class AzkabanProjectParser extends AbstractProjectParser { } @Override - @Autowired public void setFlowParsers(FlowParser[] flowParsers) { super.setFlowParsers(flowParsers); } diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/LinkisAzkabanNodeParser.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/LinkisAzkabanNodeParser.java index c6084b66d..dcbd92d0f 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/LinkisAzkabanNodeParser.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/LinkisAzkabanNodeParser.java @@ -5,9 +5,7 @@ import com.webank.wedatasphere.dss.common.entity.node.DWSNode; import com.webank.wedatasphere.dss.appjoint.scheduler.entity.SchedulerNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; -@Component public class LinkisAzkabanNodeParser extends AzkabanNodeParser { private static final Logger LOGGER = LoggerFactory.getLogger(LinkisAzkabanNodeParser.class); diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/LinkisAzkabanSendEmailNodeParser.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/LinkisAzkabanSendEmailNodeParser.java index a46dd0be8..723b35f7e 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/LinkisAzkabanSendEmailNodeParser.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/parser/LinkisAzkabanSendEmailNodeParser.java @@ -5,9 +5,9 @@ import com.webank.wedatasphere.dss.appjoint.scheduler.azkaban.entity.LinkisAzkab import com.webank.wedatasphere.dss.appjoint.scheduler.entity.ReadNode; import com.webank.wedatasphere.dss.appjoint.scheduler.entity.SchedulerNode; import com.webank.wedatasphere.dss.appjoint.scheduler.parser.SendEmailNodeParser; -import org.springframework.stereotype.Component; -@Component + + public class LinkisAzkabanSendEmailNodeParser extends SendEmailNodeParser { @Override diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/tuning/AzkabanProjectTuning.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/tuning/AzkabanProjectTuning.java index d930a513f..55f0ddf59 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/tuning/AzkabanProjectTuning.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/tuning/AzkabanProjectTuning.java @@ -7,20 +7,26 @@ import com.webank.wedatasphere.dss.appjoint.scheduler.entity.SchedulerFlow; import com.webank.wedatasphere.dss.appjoint.scheduler.entity.SchedulerProject; import com.webank.wedatasphere.dss.appjoint.scheduler.tuning.AbstractProjectTuning; import com.webank.wedatasphere.dss.appjoint.scheduler.tuning.FlowTuning; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - import java.io.File; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; import java.util.List; /** * Created by cooperyang on 2019/9/26. */ -@Component + public class AzkabanProjectTuning extends AbstractProjectTuning { + public AzkabanProjectTuning(){ + ArrayList list = new ArrayList<>(); + list.add(new LinkisAzkabanFlowTuning()); + list.add(new LinkisShareNodeFlowTuning()); + FlowTuning[] flowTunings =new FlowTuning[list.size()]; + setFlowTunings(list.toArray(flowTunings)); + } + @Override public SchedulerProject tuningSchedulerProject(SchedulerProject schedulerProject) { if(ifProjectCanTuning(schedulerProject)){ @@ -39,7 +45,7 @@ public class AzkabanProjectTuning extends AbstractProjectTuning { azkabanSchedulerFlow.setStorePath(projectStorePath + File.separator + azkabanSchedulerFlow.getName()); } - @Autowired + @Override public void setFlowTunings(FlowTuning[] flowTunings) { super.setFlowTunings(flowTunings); diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/tuning/LinkisAzkabanFlowTuning.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/tuning/LinkisAzkabanFlowTuning.java index 4cf5248e4..4f218ce7d 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/tuning/LinkisAzkabanFlowTuning.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/tuning/LinkisAzkabanFlowTuning.java @@ -10,16 +10,12 @@ import com.webank.wedatasphere.dss.appjoint.scheduler.entity.SchedulerNode; import com.webank.wedatasphere.dss.appjoint.scheduler.tuning.AbstractFlowTuning; import com.webank.wedatasphere.dss.appjoint.scheduler.tuning.NodeTuning; import com.webank.wedatasphere.dss.common.entity.node.DWSNodeDefault; -import org.apache.commons.lang.StringUtils; -import org.springframework.stereotype.Component; - import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Map; //DefaultFlowTuning修改为AzkabanFlowTuning -@Component public class LinkisAzkabanFlowTuning extends AbstractFlowTuning { diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/tuning/LinkisShareNodeFlowTuning.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/tuning/LinkisShareNodeFlowTuning.java index 8d84bb1e1..2e01c2582 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/tuning/LinkisShareNodeFlowTuning.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/tuning/LinkisShareNodeFlowTuning.java @@ -7,9 +7,9 @@ import com.webank.wedatasphere.dss.appjoint.scheduler.entity.SchedulerFlow; import com.webank.wedatasphere.dss.appjoint.scheduler.entity.ShareNode; import com.webank.wedatasphere.dss.appjoint.scheduler.tuning.AbstractShareNodeFlowTuning; import com.webank.wedatasphere.dss.appjoint.scheduler.tuning.NodeTuning; -import org.springframework.stereotype.Component; -@Component + + public class LinkisShareNodeFlowTuning extends AbstractShareNodeFlowTuning { @Override diff --git a/dss-azkaban-scheduler-appjoint/src/main/resources/appjoint.properties b/dss-azkaban-scheduler-appjoint/src/main/resources/appjoint.properties new file mode 100644 index 000000000..e5983a459 --- /dev/null +++ b/dss-azkaban-scheduler-appjoint/src/main/resources/appjoint.properties @@ -0,0 +1,21 @@ +# +# Copyright 2019 WeBank +# +# 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. +# +# + + + + + diff --git a/dss-azkaban-scheduler-appjoint/src/main/resources/log4j.properties b/dss-azkaban-scheduler-appjoint/src/main/resources/log4j.properties new file mode 100644 index 000000000..0807e6087 --- /dev/null +++ b/dss-azkaban-scheduler-appjoint/src/main/resources/log4j.properties @@ -0,0 +1,37 @@ +# +# Copyright 2019 WeBank +# +# 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. +# +# + +### set log levels ### + +log4j.rootCategory=INFO,console + +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.Threshold=INFO +log4j.appender.console.layout=org.apache.log4j.PatternLayout +#log4j.appender.console.layout.ConversionPattern= %d{ISO8601} %-5p (%t) [%F:%M(%L)] - %m%n +log4j.appender.console.layout.ConversionPattern= %d{ISO8601} %-5p (%t) %p %c{1} - %m%n + + +log4j.appender.com.webank.bdp.ide.core=org.apache.log4j.DailyRollingFileAppender +log4j.appender.com.webank.bdp.ide.core.Threshold=INFO +log4j.additivity.com.webank.bdp.ide.core=false +log4j.appender.com.webank.bdp.ide.core.layout=org.apache.log4j.PatternLayout +log4j.appender.com.webank.bdp.ide.core.Append=true +log4j.appender.com.webank.bdp.ide.core.File=logs/linkis.log +log4j.appender.com.webank.bdp.ide.core.layout.ConversionPattern= %d{ISO8601} %-5p (%t) [%F:%M(%L)] - %m%n + +log4j.logger.org.springframework=INFO diff --git a/dss-azkaban-scheduler-appjoint/src/main/resources/log4j2.xml b/dss-azkaban-scheduler-appjoint/src/main/resources/log4j2.xml new file mode 100644 index 000000000..3923cd9f3 --- /dev/null +++ b/dss-azkaban-scheduler-appjoint/src/main/resources/log4j2.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dss-scheduler-appjoint-core/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/SchedulerAppJoint.java b/dss-scheduler-appjoint-core/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/SchedulerAppJoint.java index 28450d82e..9923d90c7 100644 --- a/dss-scheduler-appjoint-core/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/SchedulerAppJoint.java +++ b/dss-scheduler-appjoint-core/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/SchedulerAppJoint.java @@ -18,8 +18,11 @@ package com.webank.wedatasphere.dss.appjoint.scheduler; import com.webank.wedatasphere.dss.appjoint.AppJoint; +import com.webank.wedatasphere.dss.appjoint.scheduler.hooks.ProjectPublishHook; +import com.webank.wedatasphere.dss.appjoint.scheduler.parser.ProjectParser; import com.webank.wedatasphere.dss.appjoint.scheduler.service.SchedulerProjectService; import com.webank.wedatasphere.dss.appjoint.scheduler.service.SchedulerSecurityService; +import com.webank.wedatasphere.dss.appjoint.scheduler.tuning.ProjectTuning; import java.io.Closeable; @@ -32,4 +35,10 @@ public interface SchedulerAppJoint extends AppJoint, Closeable { SchedulerSecurityService getSecurityService(); + ProjectParser getProjectParser(); + ProjectTuning getProjectTuning(); + + ProjectPublishHook[] getProjectPublishHooks(); + + } diff --git a/dss-server/pom.xml b/dss-server/pom.xml index 1da0c251e..ff8eebdba 100644 --- a/dss-server/pom.xml +++ b/dss-server/pom.xml @@ -60,21 +60,21 @@ ${dss.version} - - com.webank.wedatasphere.dss - dss-azkaban-scheduler-appjoint - - - spring-cloud-starter-openfeign - org.springframework.cloud - - - spring-cloud-starter-netflix-eureka-client - org.springframework.cloud - - - ${dss.version} - + + + + + + + + + + + + + + + org.springframework.cloud @@ -142,6 +142,11 @@ 4.12 test + + com.webank.wedatasphere.dss + dss-scheduler-appjoint-core + 0.5.0 + diff --git a/dss-server/src/main/java/com/webank/wedatasphere/dss/server/service/impl/DWSProjectServiceImpl.java b/dss-server/src/main/java/com/webank/wedatasphere/dss/server/service/impl/DWSProjectServiceImpl.java index 9934d2373..e58674b47 100644 --- a/dss-server/src/main/java/com/webank/wedatasphere/dss/server/service/impl/DWSProjectServiceImpl.java +++ b/dss-server/src/main/java/com/webank/wedatasphere/dss/server/service/impl/DWSProjectServiceImpl.java @@ -79,14 +79,7 @@ public class DWSProjectServiceImpl implements DWSProjectService { private DWSFlowService flowService; @Autowired private ProjectMapper projectMapper; - @Autowired - private SchedulerAppJoint schedulerAppJoint; - @Autowired - private ProjectParser projectParser; - @Autowired - private ProjectTuning projectTuning; - @Autowired - private ProjectPublishHook[] projectPublishHooks; + @Autowired private BMLService bmlService; @Autowired @@ -94,6 +87,8 @@ public class DWSProjectServiceImpl implements DWSProjectService { @Autowired private FunctionInvoker functionInvoker; + private SchedulerAppJoint schedulerAppJoint=null; + @Override public DWSProject getProjectByID(Long id) { /*JdbcProjectImpl instance = wtssdbConnector.getInjector().getInstance(JdbcProjectImpl.class); @@ -162,7 +157,11 @@ public class DWSProjectServiceImpl implements DWSProjectService { private void createSchedulerProject(DWSProject dwsProject) throws DSSErrorException { try { - functionInvoker.projectServiceAddFunction(dwsProject,ProjectService::createProject,Arrays.asList(schedulerAppJoint)); + if(getSchedulerAppJoint() != null) { + functionInvoker.projectServiceAddFunction(dwsProject, ProjectService::createProject, Arrays.asList(getSchedulerAppJoint())); + }else{ + logger.error("Add scheduler project failed for scheduler appjoint is null"); + } } catch (Exception e) { logger.error("add scheduler project failed,", e); throw new DSSErrorException(90002, "add scheduler project failed" + e.getMessage()); @@ -179,7 +178,7 @@ public class DWSProjectServiceImpl implements DWSProjectService { project.setUserName(userName); project.setDescription(description); if(existSchesulis()){ - functionInvoker.projectServiceFunction(project,ProjectService::updateProject,Arrays.asList(schedulerAppJoint)); + functionInvoker.projectServiceFunction(project,ProjectService::updateProject,Arrays.asList(getSchedulerAppJoint())); } functionInvoker.projectServiceFunction(project,ProjectService::updateProject,applicationService.listAppjoint()); } @@ -194,7 +193,7 @@ public class DWSProjectServiceImpl implements DWSProjectService { project.setUserName(userName); if(ifDelScheduler){ if(existSchesulis()){ - functionInvoker.projectServiceFunction(project,ProjectService::deleteProject,Arrays.asList(schedulerAppJoint)); + functionInvoker.projectServiceFunction(project,ProjectService::deleteProject,Arrays.asList(getSchedulerAppJoint())); } } functionInvoker.projectServiceFunction(project,ProjectService::deleteProject,applicationService.listAppjoint()); @@ -252,40 +251,50 @@ public class DWSProjectServiceImpl implements DWSProjectService { @Transactional(rollbackFor = {DSSErrorException.class, InterruptedException.class,AppJointErrorException.class}) @Override public void publish(Long projectVersionID, String userName, String comment) throws DSSErrorException, InterruptedException, AppJointErrorException { - // TODO: 2019/9/24 try catch 下载json要挪到parser去 - //1.封装dwsProject - DWSProject dwsProject = projectMapper.selectProjectByVersionID(projectVersionID); - dwsProject.setUserName(dwsUserMapper.getuserName(dwsProject.getUserID())); - logger.info(userName + "-开始发布工程:" + dwsProject.getName() + "版本ID为:" + projectVersionID); - ArrayList dwsFlows = new ArrayList<>(); - List dwsFlowVersionList = flowMapper.listLatestRootFlowVersionByProjectVersionID(projectVersionID); - for (DWSFlowVersion dwsFlowVersion : dwsFlowVersionList) { - DWSFlow dwsFlow = flowMapper.selectFlowByID(dwsFlowVersion.getFlowID()); - String json = (String) bmlService.query(userName, dwsFlowVersion.getJsonPath(), dwsFlowVersion.getVersion()).get("string"); - if (!dwsFlow.getHasSaved()) { - logger.info("工作流{}从未保存过,忽略",dwsFlow.getName()); - } else if(StringUtils.isNotBlank(json)){ - dwsFlowVersion.setJson(json); - dwsFlow.setLatestVersion(dwsFlowVersion); - createPublishProject(userName, dwsFlowVersion.getFlowID(), dwsFlow, projectVersionID); - dwsFlows.add(dwsFlow); - } else { - String warnMsg = String.format(DSSServerConstant.PUBLISH_FLOW_REPORT_FORMATE, dwsFlow.getName(), dwsFlowVersion.getVersion()); - logger.info(warnMsg); - throw new DSSErrorException(90013, warnMsg); + + SchedulerAppJoint schedulerAppJoint = getSchedulerAppJoint(); + if(schedulerAppJoint != null) { + ProjectParser projectParser = schedulerAppJoint.getProjectParser(); + ProjectTuning projectTuning = schedulerAppJoint.getProjectTuning(); + ProjectPublishHook[] projectPublishHooks = schedulerAppJoint.getProjectPublishHooks(); + // TODO: 2019/9/24 try catch 下载json要挪到parser去 + //1.封装dwsProject + DWSProject dwsProject = projectMapper.selectProjectByVersionID(projectVersionID); + dwsProject.setUserName(dwsUserMapper.getuserName(dwsProject.getUserID())); + logger.info(userName + "-开始发布工程:" + dwsProject.getName() + "版本ID为:" + projectVersionID); + ArrayList dwsFlows = new ArrayList<>(); + List dwsFlowVersionList = flowMapper.listLatestRootFlowVersionByProjectVersionID(projectVersionID); + for (DWSFlowVersion dwsFlowVersion : dwsFlowVersionList) { + DWSFlow dwsFlow = flowMapper.selectFlowByID(dwsFlowVersion.getFlowID()); + String json = (String) bmlService.query(userName, dwsFlowVersion.getJsonPath(), dwsFlowVersion.getVersion()).get("string"); + if (!dwsFlow.getHasSaved()) { + logger.info("工作流{}从未保存过,忽略", dwsFlow.getName()); + } else if (StringUtils.isNotBlank(json)) { + dwsFlowVersion.setJson(json); + dwsFlow.setLatestVersion(dwsFlowVersion); + createPublishProject(userName, dwsFlowVersion.getFlowID(), dwsFlow, projectVersionID); + dwsFlows.add(dwsFlow); + } else { + String warnMsg = String.format(DSSServerConstant.PUBLISH_FLOW_REPORT_FORMATE, dwsFlow.getName(), dwsFlowVersion.getVersion()); + logger.info(warnMsg); + throw new DSSErrorException(90013, warnMsg); + } } + if (dwsFlows.isEmpty()) throw new DSSErrorException(90007, "该工程没有可以发布的工作流,请检查工作流是否都为空"); + dwsProject.setFlows(dwsFlows); + //2.封装dwsProject完成,开始发布 + SchedulerProject schedulerProject = projectParser.parseProject(dwsProject); + projectTuning.tuningSchedulerProject(schedulerProject); + Stream.of(projectPublishHooks).forEach(DSSExceptionUtils.handling(hook -> hook.prePublish(schedulerProject))); + (schedulerAppJoint.getProjectService()).publishProject(schedulerProject, schedulerAppJoint.getSecurityService().login(userName)); + Stream.of(projectPublishHooks).forEach(DSSExceptionUtils.handling(hook -> hook.postPublish(schedulerProject))); + //3.发布完成后复制工程 + DWSProjectVersion dwsProjectVersion = projectMapper.selectProjectVersionByID(projectVersionID); + copyProjectVersionMax(projectVersionID, dwsProjectVersion, dwsProjectVersion, userName, null); + }else { + logger.error("SchedulerAppJoint is null"); + throw new DSSErrorException(90014, "SchedulerAppJoint is null"); } - if (dwsFlows.isEmpty()) throw new DSSErrorException(90007, "该工程没有可以发布的工作流,请检查工作流是否都为空"); - dwsProject.setFlows(dwsFlows); - //2.封装dwsProject完成,开始发布 - SchedulerProject schedulerProject = projectParser.parseProject(dwsProject); - projectTuning.tuningSchedulerProject(schedulerProject); - Stream.of(projectPublishHooks).forEach(DSSExceptionUtils.handling(hook -> hook.prePublish(schedulerProject))); - (schedulerAppJoint.getProjectService()).publishProject(schedulerProject, schedulerAppJoint.getSecurityService().login(userName)); - Stream.of(projectPublishHooks).forEach(DSSExceptionUtils.handling(hook -> hook.postPublish(schedulerProject))); - //3.发布完成后复制工程 - DWSProjectVersion dwsProjectVersion = projectMapper.selectProjectVersionByID(projectVersionID); - copyProjectVersionMax(projectVersionID, dwsProjectVersion, dwsProjectVersion, userName, null); } @Override @@ -576,4 +585,16 @@ public class DWSProjectServiceImpl implements DWSProjectService { }).collect(Collectors.toList()); } + + private SchedulerAppJoint getSchedulerAppJoint(){ + if(schedulerAppJoint == null){ + try { + schedulerAppJoint = (SchedulerAppJoint)applicationService.getAppjoint("schedulis"); + } catch (AppJointErrorException e) { + logger.error("Schedule system init failed!", e); + } + } + return schedulerAppJoint; + } + } -- Gitee From 99d87c4c2e17f4f053c04f6de96fdb7bb3320c54 Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Thu, 5 Dec 2019 15:52:06 +0800 Subject: [PATCH 002/238] change azkaban load from appjoint --- .../server/service/impl/DWSProjectServiceImpl.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/dss-server/src/main/java/com/webank/wedatasphere/dss/server/service/impl/DWSProjectServiceImpl.java b/dss-server/src/main/java/com/webank/wedatasphere/dss/server/service/impl/DWSProjectServiceImpl.java index e58674b47..3d0393e0c 100644 --- a/dss-server/src/main/java/com/webank/wedatasphere/dss/server/service/impl/DWSProjectServiceImpl.java +++ b/dss-server/src/main/java/com/webank/wedatasphere/dss/server/service/impl/DWSProjectServiceImpl.java @@ -178,7 +178,11 @@ public class DWSProjectServiceImpl implements DWSProjectService { project.setUserName(userName); project.setDescription(description); if(existSchesulis()){ - functionInvoker.projectServiceFunction(project,ProjectService::updateProject,Arrays.asList(getSchedulerAppJoint())); + if(getSchedulerAppJoint() != null) { + functionInvoker.projectServiceFunction(project,ProjectService::updateProject,Arrays.asList(getSchedulerAppJoint())); + }else{ + logger.error("Update scheduler project failed for scheduler appjoint is null"); + } } functionInvoker.projectServiceFunction(project,ProjectService::updateProject,applicationService.listAppjoint()); } @@ -193,7 +197,11 @@ public class DWSProjectServiceImpl implements DWSProjectService { project.setUserName(userName); if(ifDelScheduler){ if(existSchesulis()){ - functionInvoker.projectServiceFunction(project,ProjectService::deleteProject,Arrays.asList(getSchedulerAppJoint())); + if(getSchedulerAppJoint() != null) { + functionInvoker.projectServiceFunction(project, ProjectService::deleteProject, Arrays.asList(getSchedulerAppJoint())); + }else{ + logger.error("Delete scheduler project failed for scheduler appjoint is null"); + } } } functionInvoker.projectServiceFunction(project,ProjectService::deleteProject,applicationService.listAppjoint()); -- Gitee From cd954c8fabac615e491dda4d9ef6355506249d97 Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Thu, 5 Dec 2019 17:03:48 +0800 Subject: [PATCH 003/238] change azkaban load from appjoint --- assembly/src/main/assembly/assembly.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/assembly/src/main/assembly/assembly.xml b/assembly/src/main/assembly/assembly.xml index 56f67f1e2..de757f0d8 100644 --- a/assembly/src/main/assembly/assembly.xml +++ b/assembly/src/main/assembly/assembly.xml @@ -112,6 +112,16 @@ + + + ${project.parent.basedir}/dss-azkaban-scheduler-appjoint/target/ + + share/appjoints/schedulis + + *.zip + + + ${project.parent.basedir}/dss-flow-execution-entrance/target/ -- Gitee From 3cbeb04cf1ebc0f934a012d06e3b0dde6d503003 Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Thu, 5 Dec 2019 18:04:29 +0800 Subject: [PATCH 004/238] change azkaban load from appjoint --- .../scheduler/azkaban/service/AzkabanSecurityService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/service/AzkabanSecurityService.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/service/AzkabanSecurityService.java index 5e8d0bcdc..4e111fb03 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/service/AzkabanSecurityService.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/service/AzkabanSecurityService.java @@ -98,6 +98,7 @@ public final class AzkabanSecurityService extends AppJointUrlImpl implements Sch httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build(); context = HttpClientContext.create(); response = httpClient.execute(httpPost, context); + LOGGER.info("Get azkaban response code is "+ response.getStatusLine().getStatusCode()); } finally { IOUtils.closeQuietly(response); IOUtils.closeQuietly(httpClient); -- Gitee From d6dd6d86c04e4d90f982f58cd77f8d04340bc3c8 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 5 Dec 2019 18:05:28 +0800 Subject: [PATCH 005/238] install.sh Update --- bin/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/install.sh b/bin/install.sh index 81770ba98..4a4da50d1 100644 --- a/bin/install.sh +++ b/bin/install.sh @@ -320,7 +320,7 @@ ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.server.mybatis.datasource.u ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.server.mybatis.datasource.password.*#wds.linkis.server.mybatis.datasource.password=$MYSQL_PASSWORD#g\" $SERVER_CONF_PATH" ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.dss.appjoint.scheduler.azkaban.address.*#wds.dss.appjoint.scheduler.azkaban.address=http://${AZKABAN_ADRESS_IP}:${AZKABAN_ADRESS_PORT}#g\" $SERVER_CONF_PATH" ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.gateway.ip.*#wds.linkis.gateway.ip=$GATEWAY_INSTALL_IP#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.dataworlcloud.gateway.port.*#wds.dataworlcloud.gateway.port=$GATEWAY_PORT#g\" $SERVER_CONF_PATH" +ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.gateway.port.*#wds.linkis.gateway.port=$GATEWAY_PORT#g\" $SERVER_CONF_PATH" ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.dss.appjoint.scheduler.project.store.dir.*#wds.dss.appjoint.scheduler.project.store.dir=$WDS_SCHEDULER_PATH#g\" $SERVER_CONF_PATH" isSuccess "subsitution linkis.properties of $SERVERNAME" echo "<----------------$SERVERNAME:end------------------->" -- Gitee From 3685b00648f67fe9c0fe9464a351f81109a0a38a Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Thu, 5 Dec 2019 20:38:14 +0800 Subject: [PATCH 006/238] change azkaban load from appjoint --- bin/install.sh | 8 ++++++++ .../scheduler/azkaban/conf/AzkabanConf.java | 1 + .../azkaban/service/AzkabanSecurityService.java | 17 +++++++++++++---- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/bin/install.sh b/bin/install.sh index ec70f0b41..23d177c86 100644 --- a/bin/install.sh +++ b/bin/install.sh @@ -431,4 +431,12 @@ installAppjoints APPJOINTNAME_CONF_PATH_PATENT=$SERVER_HOME/$APPJOINTPARENT/$APPJOINTNAME/appjoint.properties ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#baseUrl=http://127.0.0.1:8090#baseUrl=http://$QUALITIS_ADRESS_IP:$QUALITIS_ADRESS_PORT#g\" $APPJOINTNAME_CONF_PATH_PATENT" isSuccess "subsitution conf of $SERVERNAME" +echo "<----------------$APPJOINTNAME:end------------------->" + +echo "" +echo "<----------------schedulis appjoint install start------------------->" +APPJOINTPARENT=dss-appjoints +APPJOINTNAME=schedulis +#schedulis appjoint install +installAppjoints echo "<----------------$APPJOINTNAME:end------------------->" \ No newline at end of file diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/conf/AzkabanConf.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/conf/AzkabanConf.java index 40fe989b5..49ea9948a 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/conf/AzkabanConf.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/conf/AzkabanConf.java @@ -10,4 +10,5 @@ public class AzkabanConf { public static final CommonVars AZKABAN_BASE_URL = CommonVars.apply("wds.dss.appjoint.scheduler.azkaban.address", ""); public static final CommonVars DEFAULT_STORE_PATH = CommonVars.apply("wds.dss.appjoint.scheduler.project.store.dir", "/appcom/tmp/wds/dss"); + public static final CommonVars AZKABAN_LOGIN_PWD = CommonVars.apply("wds.dss.appjoint.scheduler.azkaban.login.passwd", "password"); } diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/service/AzkabanSecurityService.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/service/AzkabanSecurityService.java index 4e111fb03..ab9de4608 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/service/AzkabanSecurityService.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/service/AzkabanSecurityService.java @@ -1,12 +1,14 @@ package com.webank.wedatasphere.dss.appjoint.scheduler.azkaban.service; import com.webank.wedatasphere.dss.appjoint.exception.AppJointErrorException; +import com.webank.wedatasphere.dss.appjoint.scheduler.azkaban.conf.AzkabanConf; import com.webank.wedatasphere.dss.appjoint.scheduler.service.SchedulerSecurityService; import com.webank.wedatasphere.dss.appjoint.service.AppJointUrlImpl; import com.webank.wedatasphere.dss.appjoint.service.session.Session; import com.webank.wedatasphere.dss.appjoint.scheduler.azkaban.constant.AzkabanConstant; import com.webank.wedatasphere.linkis.common.utils.Utils; import org.apache.commons.io.IOUtils; +import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; import org.apache.http.client.CookieStore; import org.apache.http.client.entity.UrlEncodedFormEntity; @@ -18,6 +20,7 @@ import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,7 +43,7 @@ public final class AzkabanSecurityService extends AppJointUrlImpl implements Sch private ConcurrentHashMap sessionCache = new ConcurrentHashMap<>(); private String securityUrl; private static final String USER_NAME_KEY = "username"; - private static final String USER_TOKEN_KEY = "userpwd"; + private static final String USER_TOKEN_KEY = AzkabanConf.AZKABAN_LOGIN_PWD.getValue(); private static final String SESSION_ID_KEY = "azkaban.browser.session.id"; private static Properties userToken ; @@ -83,7 +86,7 @@ public final class AzkabanSecurityService extends AppJointUrlImpl implements Sch } } - private Session getSession(String user, String token) throws IOException { + private Session getSession(String user, String token) throws IOException, AppJointErrorException { HttpPost httpPost = new HttpPost(securityUrl); List params = new ArrayList<>(); params.add(new BasicNameValuePair(USER_NAME_KEY, user)); @@ -94,18 +97,24 @@ public final class AzkabanSecurityService extends AppJointUrlImpl implements Sch CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; HttpClientContext context; + String responseContent; try { httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build(); context = HttpClientContext.create(); response = httpClient.execute(httpPost, context); - LOGGER.info("Get azkaban response code is "+ response.getStatusLine().getStatusCode()); + HttpEntity entity = response.getEntity(); + responseContent = EntityUtils.toString(entity,"utf-8"); + LOGGER.info("Get azkaban response code is "+ response.getStatusLine().getStatusCode()+",response: "+responseContent); + if(response.getStatusLine().getStatusCode() != 200){ + throw new AppJointErrorException(90041, responseContent); + } } finally { IOUtils.closeQuietly(response); IOUtils.closeQuietly(httpClient); } List cookies = context.getCookieStore().getCookies(); Optional session = cookies.stream().filter(this::findSessionId).map(this::cookieToSession).findFirst(); - return session.orElseThrow(() -> new IllegalAccessError("azkaban登录失败:无此用户")); + return session.orElseThrow(() -> new AppJointErrorException(90041,"Get azkaban session is null : "+ responseContent)); } private boolean findSessionId(Cookie cookie) { -- Gitee From 507d882312d64e6981ad09cbbe505b1fc525d623 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 5 Dec 2019 21:42:33 +0800 Subject: [PATCH 007/238] install.sh Update --- bin/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/install.sh b/bin/install.sh index 18c263d3e..e8f955fd7 100644 --- a/bin/install.sh +++ b/bin/install.sh @@ -299,7 +299,7 @@ fi echo "$APPJOINTNAME-step2:copy install package" scp -P $SSH_PORT $workDir/share/appjoints/$APPJOINTNAME/*.zip $SERVER_IP:$SERVER_HOME/$APPJOINTPARENT isSuccess "copy ${APPJOINTNAME}.zip" -ssh -p $SSH_PORT $SERVER_IP "cd $SERVER_HOME/$APPJOINTPARENT/;unzip -o dss-$APPJOINTNAME-appjoint.zip > /dev/null;rm -rf dss-$APPJOINTNAME-appjoint.zip" +ssh -p $SSH_PORT $SERVER_IP "cd $SERVER_HOME/$APPJOINTPARENT/;unzip -o dss-*-appjoint.zip > /dev/null;rm -rf dss-*-appjoint.zip" isSuccess "install ${APPJOINTNAME}.zip" } ##function end -- Gitee From 249a1987d257c1b43907d808ea943e965dd9bb59 Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Thu, 5 Dec 2019 22:16:15 +0800 Subject: [PATCH 008/238] Fix issue If the submission user of Azkaban is empty, modify the submission user to a proxy user close #7 --- .../linkis/jobtype/job/AzkabanAppJointLinkisJob.java | 4 ++++ .../linkis/jobtype/job/AzkabanCommonLinkisJob.java | 4 ++++ .../linkis-jobtype/src/main/resources/assembly.xml | 9 --------- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanAppJointLinkisJob.java b/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanAppJointLinkisJob.java index e39556745..46064b6f6 100644 --- a/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanAppJointLinkisJob.java +++ b/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanAppJointLinkisJob.java @@ -19,6 +19,7 @@ package com.webank.wedatasphere.dss.plugins.azkaban.linkis.jobtype.job; import com.webank.wedatasphere.dss.linkis.node.execution.job.AbstractAppJointLinkisJob; import com.webank.wedatasphere.dss.plugins.azkaban.linkis.jobtype.conf.LinkisJobTypeConf; +import org.apache.commons.lang.StringUtils; /** @@ -29,6 +30,9 @@ public class AzkabanAppJointLinkisJob extends AbstractAppJointLinkisJob { @Override public String getSubmitUser() { + if (StringUtils.isEmpty(getJobProps().get(LinkisJobTypeConf.FLOW_SUBMIT_USER))){ + return getJobProps().get(LinkisJobTypeConf.PROXY_USER); + } return getJobProps().get(LinkisJobTypeConf.FLOW_SUBMIT_USER); } diff --git a/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanCommonLinkisJob.java b/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanCommonLinkisJob.java index dd46a8bd2..cf398810c 100644 --- a/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanCommonLinkisJob.java +++ b/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanCommonLinkisJob.java @@ -19,6 +19,7 @@ package com.webank.wedatasphere.dss.plugins.azkaban.linkis.jobtype.job; import com.webank.wedatasphere.dss.linkis.node.execution.job.AbstractCommonLinkisJob; import com.webank.wedatasphere.dss.plugins.azkaban.linkis.jobtype.conf.LinkisJobTypeConf; +import org.apache.commons.lang.StringUtils; /** @@ -29,6 +30,9 @@ public class AzkabanCommonLinkisJob extends AbstractCommonLinkisJob { @Override public String getSubmitUser() { + if (StringUtils.isEmpty(getJobProps().get(LinkisJobTypeConf.FLOW_SUBMIT_USER))){ + return getJobProps().get(LinkisJobTypeConf.PROXY_USER); + } return getJobProps().get(LinkisJobTypeConf.FLOW_SUBMIT_USER); } diff --git a/plugins/azkaban/linkis-jobtype/src/main/resources/assembly.xml b/plugins/azkaban/linkis-jobtype/src/main/resources/assembly.xml index 72594e53c..a5d8302db 100644 --- a/plugins/azkaban/linkis-jobtype/src/main/resources/assembly.xml +++ b/plugins/azkaban/linkis-jobtype/src/main/resources/assembly.xml @@ -59,15 +59,6 @@ unix - - ${basedir}/target - - *.jar - - 0777 - / - unix - ${basedir}/bin -- Gitee From f23e6be5002b31cb15dc9e900cc2fc99e43f984d Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Fri, 6 Dec 2019 09:35:24 +0800 Subject: [PATCH 009/238] Switch the master version to 0.6.0 --- assembly/pom.xml | 2 +- conf/config.sh | 2 +- datachecker-appjoint/pom.xml | 2 +- docs/en_US/ch1/DataSphereStudio_Compile_Manual.md | 2 +- docs/en_US/ch2/Azkaban_LinkisJobType_Deployment_Manual.md | 2 +- .../DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" | 2 +- dss-appjoint-auth/pom.xml | 2 +- dss-appjoint-core/pom.xml | 2 +- dss-appjoint-loader/pom.xml | 4 ++-- dss-application/pom.xml | 2 +- dss-azkaban-scheduler-appjoint/pom.xml | 2 +- dss-common/pom.xml | 2 +- dss-flow-execution-entrance/pom.xml | 2 +- dss-linkis-node-execution/pom.xml | 2 +- dss-scheduler-appjoint-core/pom.xml | 2 +- dss-server/pom.xml | 4 ++-- eventchecker-appjoint/pom.xml | 2 +- plugins/azkaban/linkis-jobtype/pom.xml | 2 +- plugins/linkis/linkis-appjoint-entrance/pom.xml | 2 +- pom.xml | 4 ++-- qualitis-appjoint/appjoint/pom.xml | 2 +- sendemail-appjoint/sendemail-core/pom.xml | 2 +- visualis-appjoint/appjoint/pom.xml | 2 +- 23 files changed, 26 insertions(+), 26 deletions(-) diff --git a/assembly/pom.xml b/assembly/pom.xml index f41a98357..8ba8adfde 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 4.0.0 diff --git a/conf/config.sh b/conf/config.sh index b0310192e..b5a00f706 100644 --- a/conf/config.sh +++ b/conf/config.sh @@ -72,4 +72,4 @@ AZKABAN_ADRESS_PORT=8091 QUALITIS_ADRESS_IP=127.0.0.1 QUALITIS_ADRESS_PORT=8090 -DSS_VERSION=0.5.0 \ No newline at end of file +DSS_VERSION=0.6.0 \ No newline at end of file diff --git a/datachecker-appjoint/pom.xml b/datachecker-appjoint/pom.xml index ce032823d..5ef5b7806 100644 --- a/datachecker-appjoint/pom.xml +++ b/datachecker-appjoint/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 4.0.0 diff --git a/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md b/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md index da81b87fa..1225b0f99 100644 --- a/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md +++ b/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md @@ -6,7 +6,7 @@ ```xml - 0.5.0 + 0.6.0 0.9.1 2.11.8 1.8 diff --git a/docs/en_US/ch2/Azkaban_LinkisJobType_Deployment_Manual.md b/docs/en_US/ch2/Azkaban_LinkisJobType_Deployment_Manual.md index 2560b0674..098673adf 100644 --- a/docs/en_US/ch2/Azkaban_LinkisJobType_Deployment_Manual.md +++ b/docs/en_US/ch2/Azkaban_LinkisJobType_Deployment_Manual.md @@ -2,7 +2,7 @@ ## 1. Ready work -1.Click [release](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.5.0/linkis-jobtype-0.5.0.zip) to select the corresponding installation package to download: +1.Click [release](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.6.0/linkis-jobtype-0.6.0.zip) to select the corresponding installation package to download: - linkis-jobtype-$version.zip diff --git "a/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" "b/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" index 040fec9bc..d68ec401b 100644 --- "a/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" @@ -6,7 +6,7 @@ ```xml - 0.5.0 + 0.6.0 0.9.1 2.11.8 1.8 diff --git a/dss-appjoint-auth/pom.xml b/dss-appjoint-auth/pom.xml index cbf74d631..4815bd70a 100644 --- a/dss-appjoint-auth/pom.xml +++ b/dss-appjoint-auth/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 4.0.0 diff --git a/dss-appjoint-core/pom.xml b/dss-appjoint-core/pom.xml index 70a534b66..1d70a3825 100644 --- a/dss-appjoint-core/pom.xml +++ b/dss-appjoint-core/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 4.0.0 diff --git a/dss-appjoint-loader/pom.xml b/dss-appjoint-loader/pom.xml index c3045655c..98acd9f6e 100644 --- a/dss-appjoint-loader/pom.xml +++ b/dss-appjoint-loader/pom.xml @@ -22,12 +22,12 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 4.0.0 dss-appjoint-loader - 0.5.0 + 0.6.0 diff --git a/dss-application/pom.xml b/dss-application/pom.xml index 2b6fd94fc..b12fbea75 100644 --- a/dss-application/pom.xml +++ b/dss-application/pom.xml @@ -23,7 +23,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 dss-application diff --git a/dss-azkaban-scheduler-appjoint/pom.xml b/dss-azkaban-scheduler-appjoint/pom.xml index 05518dcf9..2391dd429 100644 --- a/dss-azkaban-scheduler-appjoint/pom.xml +++ b/dss-azkaban-scheduler-appjoint/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 4.0.0 diff --git a/dss-common/pom.xml b/dss-common/pom.xml index 1502a7674..5fe13c32b 100644 --- a/dss-common/pom.xml +++ b/dss-common/pom.xml @@ -23,7 +23,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 dss-common diff --git a/dss-flow-execution-entrance/pom.xml b/dss-flow-execution-entrance/pom.xml index b50e61c3b..7e03605ad 100644 --- a/dss-flow-execution-entrance/pom.xml +++ b/dss-flow-execution-entrance/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 4.0.0 diff --git a/dss-linkis-node-execution/pom.xml b/dss-linkis-node-execution/pom.xml index f09266cdf..dac6c0aa5 100644 --- a/dss-linkis-node-execution/pom.xml +++ b/dss-linkis-node-execution/pom.xml @@ -24,7 +24,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 dss-linkis-node-execution diff --git a/dss-scheduler-appjoint-core/pom.xml b/dss-scheduler-appjoint-core/pom.xml index 1af112fdb..95bf0e4c4 100644 --- a/dss-scheduler-appjoint-core/pom.xml +++ b/dss-scheduler-appjoint-core/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 4.0.0 diff --git a/dss-server/pom.xml b/dss-server/pom.xml index ff8eebdba..e7470f350 100644 --- a/dss-server/pom.xml +++ b/dss-server/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 4.0.0 @@ -145,7 +145,7 @@ com.webank.wedatasphere.dss dss-scheduler-appjoint-core - 0.5.0 + 0.6.0 diff --git a/eventchecker-appjoint/pom.xml b/eventchecker-appjoint/pom.xml index 6eab212ff..e7a5a7c21 100644 --- a/eventchecker-appjoint/pom.xml +++ b/eventchecker-appjoint/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 4.0.0 diff --git a/plugins/azkaban/linkis-jobtype/pom.xml b/plugins/azkaban/linkis-jobtype/pom.xml index 1bd28b54c..dfc73b728 100644 --- a/plugins/azkaban/linkis-jobtype/pom.xml +++ b/plugins/azkaban/linkis-jobtype/pom.xml @@ -23,7 +23,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 com.webank.wedatasphere.dss linkis-jobtype diff --git a/plugins/linkis/linkis-appjoint-entrance/pom.xml b/plugins/linkis/linkis-appjoint-entrance/pom.xml index 8443216f9..5b721b862 100644 --- a/plugins/linkis/linkis-appjoint-entrance/pom.xml +++ b/plugins/linkis/linkis-appjoint-entrance/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 4.0.0 diff --git a/pom.xml b/pom.xml index 000a11f38..5f3078cc2 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ pom com.webank.wedatasphere.dss dss - 0.5.0 + 0.6.0 dss-common @@ -47,7 +47,7 @@ - 0.5.0 + 0.6.0 0.9.1 2.11.8 1.8 diff --git a/qualitis-appjoint/appjoint/pom.xml b/qualitis-appjoint/appjoint/pom.xml index 5082eafa6..226419bac 100644 --- a/qualitis-appjoint/appjoint/pom.xml +++ b/qualitis-appjoint/appjoint/pom.xml @@ -5,7 +5,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 4.0.0 diff --git a/sendemail-appjoint/sendemail-core/pom.xml b/sendemail-appjoint/sendemail-core/pom.xml index 7a76cc235..81e946f15 100644 --- a/sendemail-appjoint/sendemail-core/pom.xml +++ b/sendemail-appjoint/sendemail-core/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 4.0.0 diff --git a/visualis-appjoint/appjoint/pom.xml b/visualis-appjoint/appjoint/pom.xml index 4ac917e90..33e921f8d 100644 --- a/visualis-appjoint/appjoint/pom.xml +++ b/visualis-appjoint/appjoint/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.5.0 + 0.6.0 4.0.0 -- Gitee From fcacd2b2a3ac6d7ee39f763112e3cfc87aa5a387 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Fri, 6 Dec 2019 18:30:31 +0800 Subject: [PATCH 010/238] One-click deployment optimization close #13 --- bin/install.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bin/install.sh b/bin/install.sh index e8f955fd7..4efc7199c 100644 --- a/bin/install.sh +++ b/bin/install.sh @@ -423,6 +423,8 @@ APPJOINTNAME=visualis #visualis appjoint install installAppjoints echo "<----------------$APPJOINTNAME:end------------------->" +##sample version does not install qualitis APPJoint and scheduis APPJoint +if [[ '2' = "$INSTALL_MODE" ]];then echo "" echo "<----------------qualitis appjoint install start------------------->" APPJOINTPARENT=dss-appjoints @@ -440,4 +442,5 @@ APPJOINTNAME=schedulis #schedulis appjoint install installAppjoints isSuccess "subsitution conf of qualitis" -echo "<----------------$APPJOINTNAME:end------------------->" \ No newline at end of file +echo "<----------------$APPJOINTNAME:end------------------->" +fi \ No newline at end of file -- Gitee From 3f2b2e78b30fc6ef53ca76189eb1f6e98f40d683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B6=E5=AE=B6=E8=B1=AA?= <360782885@qq.com> Date: Fri, 6 Dec 2019 20:32:31 +0800 Subject: [PATCH 011/238] Update QualitisNodeExecution.java --- .../wedatasphere/appjoint/QualitisNodeExecution.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/qualitis-appjoint/appjoint/src/main/java/com.webank/wedatasphere/appjoint/QualitisNodeExecution.java b/qualitis-appjoint/appjoint/src/main/java/com.webank/wedatasphere/appjoint/QualitisNodeExecution.java index dbace5346..66196b7cf 100644 --- a/qualitis-appjoint/appjoint/src/main/java/com.webank/wedatasphere/appjoint/QualitisNodeExecution.java +++ b/qualitis-appjoint/appjoint/src/main/java/com.webank/wedatasphere/appjoint/QualitisNodeExecution.java @@ -44,10 +44,6 @@ public class QualitisNodeExecution extends LongTermNodeExecution { private String baseUrl; - public boolean canExecute(Node node, NodeContext nodeContext) { - return true; - } - @Override public void init(Map map) throws AppJointErrorException { appId = (String) map.get("qualitis_appId"); @@ -58,7 +54,7 @@ public class QualitisNodeExecution extends LongTermNodeExecution { @Override public boolean canExecute(AppJointNode appJointNode, NodeContext context, Session session) { - return false; + return appJointNode.getNodeType().toLowerCase().contains("qualitis"); } @Override @@ -321,4 +317,4 @@ public class QualitisNodeExecution extends LongTermNodeExecution { public void setBaseUrl(String s) { this.baseUrl = s; } -} \ No newline at end of file +} -- Gitee From 13b0c27c79578e4e7f4de51028dc2ecebdf92045 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Mon, 9 Dec 2019 15:14:57 +0800 Subject: [PATCH 012/238] Add SSH port configuration close #16 --- bin/install.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/install.sh b/bin/install.sh index 4efc7199c..825448a85 100644 --- a/bin/install.sh +++ b/bin/install.sh @@ -354,8 +354,8 @@ installPackage ###Update appjoint entrance linkis.properties echo "$SERVERNAME-step4:update linkis.properties" SERVER_CONF_PATH=$SERVER_HOME/$SERVERNAME/conf/linkis.properties -ssh $SERVER_IP "sed -i \"s#wds.linkis.entrance.config.logPath.*#wds.linkis.entrance.config.logPath=$WORKSPACE_USER_ROOT_PATH#g\" $SERVER_CONF_PATH" -ssh $SERVER_IP "sed -i \"s#wds.linkis.resultSet.store.path.*#wds.linkis.resultSet.store.path=$RESULT_SET_ROOT_PATH#g\" $SERVER_CONF_PATH" +ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.entrance.config.logPath.*#wds.linkis.entrance.config.logPath=$WORKSPACE_USER_ROOT_PATH#g\" $SERVER_CONF_PATH" +ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.resultSet.store.path.*#wds.linkis.resultSet.store.path=$RESULT_SET_ROOT_PATH#g\" $SERVER_CONF_PATH" isSuccess "subsitution linkis.properties of $SERVERNAME" echo "<----------------$SERVERNAME:end------------------->" echo "" @@ -441,6 +441,6 @@ APPJOINTPARENT=dss-appjoints APPJOINTNAME=schedulis #schedulis appjoint install installAppjoints -isSuccess "subsitution conf of qualitis" +isSuccess "subsitution conf of schedulis" echo "<----------------$APPJOINTNAME:end------------------->" fi \ No newline at end of file -- Gitee From e1df1a7d9ffc4f14f58928e6ed070e63e0587f4a Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Tue, 10 Dec 2019 15:30:50 +0800 Subject: [PATCH 013/238] update azkaban manual --- ...272\246\347\263\273\347\273\237Azkaban.md" | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 "docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" diff --git "a/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" "b/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" new file mode 100644 index 000000000..ef2fbd259 --- /dev/null +++ "b/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" @@ -0,0 +1,55 @@ +## 如何接入调度系统Azkaban: + Azkaban目前是作为一个SchedulerAppJoint在DSS-SERVER中使用,通过AzkabanSchedulerAppJoint实现了Azkaban的工程服务和安全认证服务, + 主要提供了工程的创建、更新、发布、删除,以及安全认证服务相关的代理登录,Cookie保存等。 + + **前提条件:用户已经安装部署好社区版本的Azkaban-3.69.X环境** + + (1) 安装DSS前配置Azkaban的环境信息 + + 在安装DSS之前,在工程的conf目录下配置Azkaban的IP地址和端口信息 +``` + #azkaban.address + AZKABAN_ADRESS_IP=127.0.0.1 + AZKABAN_ADRESS_PORT=99887 +``` + + 用户使用DSS一键安装,会自动配置以下两个参数内容: + +``` + wds.dss.appjoint.scheduler.azkaban.address= //Azkaban 的http地址 + wds.dss.appjoint.scheduler.project.store.dir= //Azkaban发布包临时存储目录 +``` + (2) 安装DSS后配置Azkaban用户信息 + + 在DSS-SERVER服务的conf目录下放置token.properties属性文件,配置用户名和密码信息,用于登录Azkaban.示例: + user01=1234 + 说明:由于每个公司都有各自的登录认证系统,这里只提供简单实现,用户可以实现SchedulerSecurityService定义自己的登录认证方法。 + 关联后DSS和Azkaban的用户必须是同一个。 + + (3) 在DSS数据库中配置Azkaban的appjoint信息(一键安装时默认已执行不需要重复执行,单独安装需要) + +``` + INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`) VALUES (NULL, 'azkaban', NULL, '0', '1', NULL, '0', NULL, NULL); +``` + 检查dss-appjoints目录下是否已经安装了schedulis的appjoint。 + + (4) 在Azkaban上安装Linkis任务执行插件 + + 由于现在DSS的任务基本都是提交给Linkis来执行的,所以需要在Azkaban上安装一个插件,用于DSS发布到Azkaban后的调度执行。 + 1、获取插件包 + +``` + /wedatasphere-dss-x.x.x-dist/share/plugins/azkaban/linkis-jobtype/linkis-jobtype-x.x.x-linkis-jobtype.zip +``` + 2、安装插件 + 把安装包解压到指定的目录下: +``` + /AzkabanInstall/wtss-exec/plugins/jobtypes/linkis +``` + + 3、配置插件 + private.properties(azkaban的jobtype配置)和 plugin.properties(额外的配置) + 请根据实际环境设置两个配置文件的内容 + + 4、刷新生效 + curl http://IP:PORT/executor?action=reloadJobTypePlugins \ No newline at end of file -- Gitee From 89ca518ad4d79147b0053658dc62ca13eb43e247 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Tue, 10 Dec 2019 16:35:21 +0800 Subject: [PATCH 014/238] DSS Quick Use Document FAQ Update close #20 --- ...77\347\224\250\346\226\207\346\241\243.md" | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index 54a3f1774..3cdbd36cc 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -47,7 +47,7 @@ Nginx,[如何安装Nginx](https://www.tecmint.com/install-nginx-on-centos-7/) sudo useradd hadoop ``` -##### 注意:用户需要有sudo权限,且可免密登陆本机。[如何配置SSH免密登陆](https://www.jianshu.com/p/0922095f69f3) +##### 注意:用户需要有sudo权限,且可免密登陆本机。[如何配置SSH免密登陆](https://linuxconfig.org/passwordless-ssh) ``` vi /etc/sudoers @@ -164,7 +164,7 @@ Azkaban [如何安装Azkaban](https://github.com/azkaban/azkaban) sudo useradd hadoop ``` -##### 注意:用户需要有sudo权限,且可免密登陆本机。[如何配置SSH免密登陆](https://www.jianshu.com/p/0922095f69f3) +##### 注意:用户需要有sudo权限,且可免密登陆本机。[如何配置SSH免密登陆](https://linuxconfig.org/passwordless-ssh) ``` vi /etc/sudoers @@ -420,8 +420,19 @@ Caused by: java.lang.Exception: /data/DSSInstall/visualis-server/bin/phantomjsis 下载 [driver驱动](https://phantomjs.org/download.html),把phantomjs二进制文件放入visualis-server的bin目录下即可。 +(3)简单版DSS创建工程失败 -(3)上传文件大小限制 + +删除数据库中表dss_application的schedulis和qualitis记录 + + +(4)多次重复安装后报错:TooManyResultsException:Expected on result + + +删除数据库中表dss_application的schedulis和qualitis记录 + + +(5)上传文件大小限制 ``` sudo vi /etc/nginx/nginx.conf @@ -433,7 +444,7 @@ sudo vi /etc/nginx/nginx.conf client_max_body_size 200m ``` - (4)接口超时 + (6)接口超时 ``` sudo vi /etc/nginx/conf.d/dss.conf -- Gitee From d1291673906bca9aa428254fdfc9022e82cae21f Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Tue, 10 Dec 2019 16:39:41 +0800 Subject: [PATCH 015/238] DSS Quick Use Document FAQ Update close #20 --- ...\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index 3cdbd36cc..c6b62101e 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -429,7 +429,7 @@ Caused by: java.lang.Exception: /data/DSSInstall/visualis-server/bin/phantomjsis (4)多次重复安装后报错:TooManyResultsException:Expected on result -删除数据库中表dss_application的schedulis和qualitis记录 +删除数据库中表linkis_user和dss_user中的重复记录 (5)上传文件大小限制 -- Gitee From e3bd069c2798d82b5619a48dc19f1697410e6708 Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Tue, 10 Dec 2019 19:56:33 +0800 Subject: [PATCH 016/238] update azkaban manual --- README-ZH.md | 2 ++ ...272\246\347\263\273\347\273\237Azkaban.md" | 26 +++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/README-ZH.md b/README-ZH.md index 89b69eb63..15c13c1e3 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -146,6 +146,8 @@ DSS主要特点: [外部系统快速接入DSS](docs/zh_CN/ch4/第三方系统接入DSS指南.md) +[如何接入调度系统Azkaban](docs/zh_CN/ch4/如何接入调度系统Azkaban.md) + 更多文档,敬请期待! ## 交流贡献 diff --git "a/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" "b/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" index ef2fbd259..3cc09b2a8 100644 --- "a/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" +++ "b/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" @@ -6,14 +6,15 @@ (1) 安装DSS前配置Azkaban的环境信息 - 在安装DSS之前,在工程的conf目录下配置Azkaban的IP地址和端口信息 + 在安装DSS之前,在工程的conf目录下配置Azkaban的IP地址和端口信息: + ``` #azkaban.address AZKABAN_ADRESS_IP=127.0.0.1 AZKABAN_ADRESS_PORT=99887 ``` - 用户使用DSS一键安装,会自动配置以下两个参数内容: + 用户使用DSS一键安装,会自动配置以下两个参数内容: ``` wds.dss.appjoint.scheduler.azkaban.address= //Azkaban 的http地址 @@ -29,27 +30,30 @@ (3) 在DSS数据库中配置Azkaban的appjoint信息(一键安装时默认已执行不需要重复执行,单独安装需要) ``` - INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`) VALUES (NULL, 'azkaban', NULL, '0', '1', NULL, '0', NULL, NULL); + INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`) VALUES (NULL, 'azkaban', NULL, '0', '1', NULL, '0', NULL, NULL); ``` 检查dss-appjoints目录下是否已经安装了schedulis的appjoint。 (4) 在Azkaban上安装Linkis任务执行插件 - 由于现在DSS的任务基本都是提交给Linkis来执行的,所以需要在Azkaban上安装一个插件,用于DSS发布到Azkaban后的调度执行。 - 1、获取插件包 + 由于现在DSS的任务基本都是提交给Linkis来执行的,所以需要在Azkaban上安装一个插件,用于DSS发布到Azkaban后的调度执行。 + 1、获取插件包 ``` - /wedatasphere-dss-x.x.x-dist/share/plugins/azkaban/linkis-jobtype/linkis-jobtype-x.x.x-linkis-jobtype.zip + /wedatasphere-dss-x.x.x-dist/share/plugins/azkaban/linkis-jobtype/linkis-jobtype-x.x.x-linkis-jobtype.zip ``` - 2、安装插件 - 把安装包解压到指定的目录下: + 2、安装插件 + + 把安装包解压到指定的目录下: ``` - /AzkabanInstall/wtss-exec/plugins/jobtypes/linkis + /AzkabanInstall/wtss-exec/plugins/jobtypes/linkis ``` - 3、配置插件 + 3、配置插件 + private.properties(azkaban的jobtype配置)和 plugin.properties(额外的配置) 请根据实际环境设置两个配置文件的内容 - 4、刷新生效 + 4、刷新生效 + curl http://IP:PORT/executor?action=reloadJobTypePlugins \ No newline at end of file -- Gitee From a4d03411afc4c9734236eec84c09c97bb9969f31 Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Tue, 10 Dec 2019 20:02:45 +0800 Subject: [PATCH 017/238] update azkaban manual --- ...5\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" "b/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" index 3cc09b2a8..96df77861 100644 --- "a/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" +++ "b/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" @@ -1,4 +1,4 @@ -## 如何接入调度系统Azkaban: +## 如何接入调度系统Azkaban Azkaban目前是作为一个SchedulerAppJoint在DSS-SERVER中使用,通过AzkabanSchedulerAppJoint实现了Azkaban的工程服务和安全认证服务, 主要提供了工程的创建、更新、发布、删除,以及安全认证服务相关的代理登录,Cookie保存等。 -- Gitee From 9a30c8254c08fc908ba6ccae483c420cae89bd2a Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Wed, 11 Dec 2019 19:38:29 +0800 Subject: [PATCH 018/238] new python node --- .../js/module/process/images/newIcon/python.svg | 1 + web/src/js/module/process/index.vue | 2 +- web/src/js/module/process/shape.js | 7 +++++++ web/src/js/service/mixin.js | 2 +- web/src/js/service/nodeType.js | 15 +++++++++++---- 5 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 web/src/js/module/process/images/newIcon/python.svg diff --git a/web/src/js/module/process/images/newIcon/python.svg b/web/src/js/module/process/images/newIcon/python.svg new file mode 100644 index 000000000..78a4e6e47 --- /dev/null +++ b/web/src/js/module/process/images/newIcon/python.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/js/module/process/index.vue b/web/src/js/module/process/index.vue index de0dfedfc..f6ca018da 100644 --- a/web/src/js/module/process/index.vue +++ b/web/src/js/module/process/index.vue @@ -208,7 +208,7 @@ export default { } } } - if ([NODETYPE.SPARKSQL, NODETYPE.HQL, NODETYPE.SPARKPY, NODETYPE.SHELL, NODETYPE.SCALA].indexOf(node.type) !== -1) { + if ([NODETYPE.SPARKSQL, NODETYPE.HQL, NODETYPE.SPARKPY, NODETYPE.SHELL, NODETYPE.SCALA, NODETYPE.PYTHON].indexOf(node.type) !== -1) { const len = node.resources ? node.resources.length : 0; if (len && node.jobContent && node.jobContent.script) { // 判断是否有保存过脚本 const resourceId = node.resources[0].resourceId; diff --git a/web/src/js/module/process/shape.js b/web/src/js/module/process/shape.js index 670cedd17..635b1d234 100644 --- a/web/src/js/module/process/shape.js +++ b/web/src/js/module/process/shape.js @@ -66,6 +66,13 @@ export default [ image: NODEICON[NODETYPE.SCALA].icon, editParam: false, editBaseInfo: false, + }, + { + type: NODETYPE.PYTHON, + title: 'python', + image: NODEICON[NODETYPE.PYTHON].icon, + editParam: false, + editBaseInfo: false, }], }, { diff --git a/web/src/js/service/mixin.js b/web/src/js/service/mixin.js index f128f8feb..31e933fcb 100644 --- a/web/src/js/service/mixin.js +++ b/web/src/js/service/mixin.js @@ -31,7 +31,7 @@ export default { { rule: /\.scala$/i, lang: 'java', executable: true, application: 'spark', runType: 'scala', ext: '.scala', scriptType: 'scala', abbr: 'scala', logo: 'fi-scala', isCanBeNew: true, label: 'Scala', isCanBeOpen: true, flowType: 'scala' }, { rule: /\.scala$/i, lang: 'java', executable: true, application: 'spark', runType: 'function.mdq', ext: '.scala', scriptType: 'scala', abbr: 'scala', logo: 'fi-scala', isCanBeNew: false, label: 'Scala', isCanBeOpen: true }, { rule: /\.jdbc$/i, lang: 'hql', executable: true, application: 'jdbc', runType: 'jdbc', ext: '.jdbc', scriptType: 'jdbc', abbr: 'jdbc', logo: 'fi-jdbc', isCanBeNew: true, label: 'JDBC', isCanBeOpen: true }, - { rule: /\.python$/i, lang: 'python', executable: true, application: 'python', runType: 'python', ext: '.python', scriptType: 'python', abbr: 'py', logo: 'fi-python', isCanBeNew: true, label: 'Python', isCanBeOpen: true }, + { rule: /\.python$/i, lang: 'python', executable: true, application: 'python', runType: 'python', ext: '.python', scriptType: 'python', abbr: 'py', logo: 'fi-python', isCanBeNew: true, label: 'Python', isCanBeOpen: true, flowType: 'python' }, { rule: /\.py$/i, lang: 'python', executable: true, application: 'spark', runType: 'python', ext: '.py', scriptType: 'pythonSpark', abbr: 'py', logo: 'fi-spark-python', isCanBeNew: true, label: 'PythonSpark', isCanBeOpen: true, flowType: 'pyspark' }, { rule: /\.r$/i, lang: 'r', executable: true, application: 'spark', runType: 'r', ext: '.r', scriptType: 'r', abbr: 'r', logo: 'fi-r', isCanBeNew: true, label: 'R', isCanBeOpen: true }, { rule: /\.sh$/i, lang: 'sh', executable: true, application: 'shell', runType: 'shell', ext: '.sh', scriptType: 'shell', abbr: 'shell', logo: 'fi-r', isCanBeNew: false, label: 'Shell', isCanBeOpen: true, flowType: 'shell' }, diff --git a/web/src/js/service/nodeType.js b/web/src/js/service/nodeType.js index 71c00e1e7..68ffedce5 100644 --- a/web/src/js/service/nodeType.js +++ b/web/src/js/service/nodeType.js @@ -18,7 +18,7 @@ import shell from '../module/process/images/shell.svg'; import flow from '../module/process/images/newIcon/flow.svg'; import eventchecker from '../module/process/images/newIcon/eventcheckerf.svg'; -import Python from '../module/process/images/pyspark.svg'; +import sparkPython from '../module/process/images/pyspark.svg'; import sql from '../module/process/images/newIcon/spark.svg'; import hivesql from '../module/process/images/newIcon/hive.svg'; import veceive from '../module/process/images/newIcon/eventcheckerw.svg'; @@ -31,12 +31,14 @@ import sendmail from '../module/process/images/newIcon/email.svg'; import scala from '../module/process/images/scala.svg'; import exchange from '../module/process/images/newIcon/exchange.svg'; import qualitis from '../module/process/images/newIcon/qualitis.svg'; +import python from '../module/process/images/newIcon/python.svg'; const NODETYPE = { SHELL: 'azkaban.shell', HQL: 'linkis.hive.hql', SPARKSQL: 'linkis.spark.sql', SPARKPY: 'linkis.spark.py', SCALA: 'linkis.spark.scala', + PYTHON: 'linkis.python.python', CONNECTOR: 'linkis.control.empty', DISPLAY: 'linkis.appjoint.visualis.display', DASHBOARD: 'linkis.appjoint.visualis.dashboard', @@ -54,7 +56,8 @@ const ext = { [NODETYPE.HQL]: 'hql', [NODETYPE.SPARKSQL]: 'sparksql', [NODETYPE.SPARKPY]: 'pyspark', - [NODETYPE.SCALA]: 'scala' + [NODETYPE.SCALA]: 'scala', + [NODETYPE.PYTHON]: 'python' } const NODEICON = { [NODETYPE.SHELL]: { @@ -70,13 +73,17 @@ const NODEICON = { class: {'sql': true} }, [NODETYPE.SPARKPY]: { - icon: Python, - class: {'Python': true} + icon: sparkPython, + class: {'sparkPython': true} }, [NODETYPE.SCALA]: { icon: scala, class: {'scala': true} }, + [NODETYPE.PYTHON]: { + icon: python, + class: {'python': true} + }, [NODETYPE.CONNECTOR]: { icon: connect, class: {'connect': true} -- Gitee From eed3301390dcb4fd9ba6e313162736e3af442601 Mon Sep 17 00:00:00 2001 From: jftang Date: Thu, 12 Dec 2019 11:17:31 +0800 Subject: [PATCH 019/238] sharenode bug fix --- .../appjoint/scheduler/tuning/AbstractShareNodeFlowTuning.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dss-scheduler-appjoint-core/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/tuning/AbstractShareNodeFlowTuning.java b/dss-scheduler-appjoint-core/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/tuning/AbstractShareNodeFlowTuning.java index 84493b510..de2e848e7 100644 --- a/dss-scheduler-appjoint-core/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/tuning/AbstractShareNodeFlowTuning.java +++ b/dss-scheduler-appjoint-core/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/tuning/AbstractShareNodeFlowTuning.java @@ -66,7 +66,7 @@ public abstract class AbstractShareNodeFlowTuning extends AbstractFlowTuning imp Map res = new HashMap<>(); //遍历readNodes,将NodeIds转为name的集合,过滤掉删除了节点但是还滞留在content里面的id Arrays.stream(readNodes).filter(rn ->rn.getShareNodeIds() != null).forEach(rn ->{ - List names = Arrays.stream(rn.getShareNodeIds()).filter(id->flow.getSchedulerNodes().stream().filter(sn -> !id.equals(sn.getId())).findFirst().isPresent()). + List names = Arrays.stream(rn.getShareNodeIds()).filter(id->flow.getSchedulerNodes().stream().filter(sn -> id.equals(sn.getId())).findFirst().isPresent()). map(id -> flow.getSchedulerNodes().stream().filter(sn -> id.equals(sn.getId())).findFirst().get().getName()).collect(Collectors.toList()); rn.setShareNodeIds(names.toArray(new String[0])); }); -- Gitee From ee1ddb526d37b2c96cbb1e2901f9c04d6b6c24b9 Mon Sep 17 00:00:00 2001 From: jftang Date: Thu, 12 Dec 2019 11:19:59 +0800 Subject: [PATCH 020/238] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scheduler/tuning/AbstractShareNodeFlowTuning.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dss-scheduler-appjoint-core/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/tuning/AbstractShareNodeFlowTuning.java b/dss-scheduler-appjoint-core/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/tuning/AbstractShareNodeFlowTuning.java index de2e848e7..7a1cb8bce 100644 --- a/dss-scheduler-appjoint-core/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/tuning/AbstractShareNodeFlowTuning.java +++ b/dss-scheduler-appjoint-core/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/tuning/AbstractShareNodeFlowTuning.java @@ -66,9 +66,8 @@ public abstract class AbstractShareNodeFlowTuning extends AbstractFlowTuning imp Map res = new HashMap<>(); //遍历readNodes,将NodeIds转为name的集合,过滤掉删除了节点但是还滞留在content里面的id Arrays.stream(readNodes).filter(rn ->rn.getShareNodeIds() != null).forEach(rn ->{ - List names = Arrays.stream(rn.getShareNodeIds()).filter(id->flow.getSchedulerNodes().stream().filter(sn -> id.equals(sn.getId())).findFirst().isPresent()). - map(id -> flow.getSchedulerNodes().stream().filter(sn -> id.equals(sn.getId())).findFirst().get().getName()).collect(Collectors.toList()); - rn.setShareNodeIds(names.toArray(new String[0])); + rn.setShareNodeIds(Arrays.stream(rn.getShareNodeIds()).filter(id -> flow.getSchedulerNodes().stream().anyMatch(sn -> id.equals(sn.getId()))). + map(id -> flow.getSchedulerNodes().stream().filter(sn -> id.equals(sn.getId())).findFirst().get().getName()).toArray(String[]::new)); }); Stream.of(readNodes).forEach(x -> { -- Gitee From 33b209392550b9d14952b52a5c5cc17c2f207484 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Fri, 13 Dec 2019 17:14:46 +0800 Subject: [PATCH 021/238] Automated Installation Enhance close #37 --- bin/checkEnv.sh | 42 +++++++++++ bin/install.sh | 70 ++++++++++++++----- bin/start-all.sh | 48 +++++++++++++ conf/config.sh | 8 +-- db/azkaban.sql | 3 + db/dss_dml.sql | 4 +- db/qualitis.sql | 3 + .../bin/start-dss-flow-execution-entrance.sh | 50 ++++++++----- dss-server/bin/start-dss-server.sh | 40 ++++++----- .../bin/start-linkis-appjoint-entrance.sh | 43 ++++++------ .../bin/stop-linkis-appjoint-entrance.sh | 2 +- 11 files changed, 233 insertions(+), 80 deletions(-) create mode 100644 bin/checkEnv.sh create mode 100644 db/azkaban.sql create mode 100644 db/qualitis.sql diff --git a/bin/checkEnv.sh b/bin/checkEnv.sh new file mode 100644 index 000000000..c377c05ea --- /dev/null +++ b/bin/checkEnv.sh @@ -0,0 +1,42 @@ +# +# Copyright 2019 WeBank +# +# 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. +# +#!/bin/sh +say() { + printf 'check command fail \n %s\n' "$1" +} + +err() { + say "$1" >&2 + exit 1 +} + +check_cmd() { + command -v "$1" > /dev/null 2>&1 +} + +need_cmd() { + if ! check_cmd "$1"; then + err "need '$1' (command not found)" + fi +} +echo "<-----start to check used cmd---->" +need_cmd yum +need_cmd java +need_cmd mysql +need_cmd unzip +need_cmd expect +need_cmd telnet +echo "<-----end to check used cmd------>" diff --git a/bin/install.sh b/bin/install.sh index 825448a85..70adc5a34 100644 --- a/bin/install.sh +++ b/bin/install.sh @@ -1,3 +1,18 @@ +# +# Copyright 2019 WeBank +# +# 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. +# #!/bin/sh #Actively load user env source ~/.bash_profile @@ -38,6 +53,11 @@ else fi } + +#check env +sh ${workDir}/bin/checkEnv.sh +isSuccess "check env" + function checkJava(){ java -version isSuccess "execute java --version" @@ -158,38 +178,55 @@ fi ##init db if [[ '2' = "$MYSQL_INSTALL_MODE" ]];then mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/dss_ddl.sql" - isSuccess "source linkis_ddl.sql" - LOCAL_IP="`ifconfig | grep 'inet' | grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $2}'`" + isSuccess "source dss_ddl.sql" + LOCAL_IP="`hostname -i`" if [ $GATEWAY_INSTALL_IP == "127.0.0.1" ];then echo "GATEWAY_INSTALL_IP is equals 127.0.0.1 ,we will change it to ip address" GATEWAY_INSTALL_IP_2=$LOCAL_IP else GATEWAY_INSTALL_IP_2=$GATEWAY_INSTALL_IP fi - echo $GATEWAY_INSTALL_IP_2 + #echo $GATEWAY_INSTALL_IP_2 sed -i "s/GATEWAY_INSTALL_IP_2/$GATEWAY_INSTALL_IP_2/g" ${workDir}/db/dss_dml.sql sed -i "s/GATEWAY_PORT/$GATEWAY_PORT/g" ${workDir}/db/dss_dml.sql - if [ $AZKABAN_ADRESS_IP == "127.0.0.1" ];then - echo "AZKABAN_ADRESS_IP is equals 127.0.0.1 ,we will change it to ip address" - AZKABAN_ADRESS_IP_2=$LOCAL_IP - else - AZKABAN_ADRESS_IP_2=$AZKABAN_ADRESS_IP - fi - echo $AZKABAN_ADRESS_IP_2 - sed -i "s/AZKABAN_ADRESS_IP_2/$AZKABAN_ADRESS_IP_2/g" ${workDir}/db/dss_dml.sql - sed -i "s/AZKABAN_ADRESS_PORT/$AZKABAN_ADRESS_PORT/g" ${workDir}/db/dss_dml.sql if [ $VISUALIS_NGINX_IP == "127.0.0.1" ]||[ $VISUALIS_NGINX_IP == "0.0.0.0" ];then echo "VISUALIS_NGINX_IP is equals $VISUALIS_NGINX_IP ,we will change it to ip address" VISUALIS_NGINX_IP_2=$LOCAL_IP else VISUALIS_NGINX_IP_2=$VISUALIS_NGINX_IP fi - echo $VISUALIS_NGINX_IP_2 + #echo $VISUALIS_NGINX_IP_2 sed -i "s/VISUALIS_NGINX_IP_2/$VISUALIS_NGINX_IP_2/g" ${workDir}/db/dss_dml.sql sed -i "s/VISUALIS_NGINX_PORT/$VISUALIS_NGINX_PORT/g" ${workDir}/db/dss_dml.sql mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/dss_dml.sql" - isSuccess "source linkis_dml.sql" - echo "Rebuild the table" + isSuccess "source dss_dml.sql" + if [[ '2' = "$INSTALL_MODE" ]];then + echo "start to update azkaban and qualitis table info " + #azkaban + if [ $AZKABAN_ADRESS_IP == "127.0.0.1" ];then + echo "AZKABAN_ADRESS_IP is equals 127.0.0.1 ,we will change it to ip address" + AZKABAN_ADRESS_IP_2=$LOCAL_IP + else + AZKABAN_ADRESS_IP_2=$AZKABAN_ADRESS_IP + fi + echo $AZKABAN_ADRESS_IP_2 + sed -i "s/AZKABAN_ADRESS_IP_2/$AZKABAN_ADRESS_IP_2/g" ${workDir}/db/azkaban.sql + sed -i "s/AZKABAN_ADRESS_PORT/$AZKABAN_ADRESS_PORT/g" ${workDir}/db/azkaban.sql + mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/azkaban.sql" + isSuccess "source azkaban.sql" + #qualitis + if [ $QUALITIS_ADRESS_IP == "127.0.0.1" ];then + echo "QUALITIS_ADRESS_IP is equals 127.0.0.1 ,we will change it to ip address" + QUALITIS_ADRESS_IP_2=$LOCAL_IP + else + QUALITIS_ADRESS_IP_2=$QUALITIS_ADRESS_IP + fi + echo $QUALITIS_ADRESS_IP_2 + sed -i "s/QUALITIS_ADRESS_IP_2/$QUALITIS_ADRESS_IP_2/g" ${workDir}/db/qualitis.sql + sed -i "s/QUALITIS_ADRESS_PORT/$QUALITIS_ADRESS_PORT/g" ${workDir}/db/qualitis.sql + mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/qualitis.sql" + isSuccess "source qualitis.sql" + fi fi ##env check @@ -304,8 +341,7 @@ isSuccess "install ${APPJOINTNAME}.zip" } ##function end -## -ver Install +##dss-Server install PACKAGE_DIR=dss/dss-server SERVERNAME=dss-server SERVER_IP=$DSS_SERVER_INSTALL_IP diff --git a/bin/start-all.sh b/bin/start-all.sh index abc0e64ed..df229abc8 100644 --- a/bin/start-all.sh +++ b/bin/start-all.sh @@ -76,6 +76,16 @@ sleep 15 #for Eureka register SERVER_NAME=dss-server SERVER_IP=$DSS_SERVER_INSTALL_IP startApp +#MICRO_SERVICE_NAME=dss-server +#MICRO_SERVICE_IP=$DSS_SERVER_INSTALL_IP +#MICRO_SERVICE_PORT=$DSS_SERVER_PORT +#sh $workDir/check.sh $MICRO_SERVICE_NAME $MICRO_SERVICE_IP $MICRO_SERVICE_PORT +#state=`echo -e "\n" | telnet $MICRO_SERVICE_IP $MICRO_SERVICE_PORT 2>/dev/null | grep Connected | wc -l` +#if [ $state -eq 0 ]; then +# echo "" +# echo "ERROR " $MICRO_SERVICE_NAME "is a critical service and must be guaranteed to be started !!!" +# exit 1 +#fi #dss-flow-execution-entrance SERVER_NAME=dss-flow-execution-entrance @@ -91,3 +101,41 @@ SERVER_NAME=visualis-server SERVER_IP=$VISUALIS_SERVER_INSTALL_IP startApp + +echo "Start to check all dss microservice" + +#check dss-server +MICRO_SERVICE_NAME=dss-server +MICRO_SERVICE_IP=$DSS_SERVER_INSTALL_IP +MICRO_SERVICE_PORT=$DSS_SERVER_PORT +sh $workDir/checkMicro.sh $MICRO_SERVICE_NAME $MICRO_SERVICE_IP $MICRO_SERVICE_PORT +state=`echo -e "\n" | telnet $MICRO_SERVICE_IP $MICRO_SERVICE_PORT 2>/dev/null | grep Connected | wc -l` +isSuccess "$MICRO_SERVICE_NAME start" + + +#check dss-flow-execution-entrance +MICRO_SERVICE_NAME=dss-flow-execution-entrance +MICRO_SERVICE_IP=$FLOW_EXECUTION_INSTALL_IP +MICRO_SERVICE_PORT=$FLOW_EXECUTION_PORT +sh $workDir/checkMicro.sh $MICRO_SERVICE_NAME $MICRO_SERVICE_IP $MICRO_SERVICE_PORT +state=`echo -e "\n" | telnet $MICRO_SERVICE_IP $MICRO_SERVICE_PORT 2>/dev/null | grep Connected | wc -l` +isSuccess "$MICRO_SERVICE_NAME start" + +#check linkis-appjoint-entrance +MICRO_SERVICE_NAME=linkis-appjoint-entrance +MICRO_SERVICE_IP=$APPJOINT_ENTRANCE_INSTALL_IP +MICRO_SERVICE_PORT=$APPJOINT_ENTRANCE_PORT +sh $workDir/checkMicro.sh $MICRO_SERVICE_NAME $MICRO_SERVICE_IP $MICRO_SERVICE_PORT +state=`echo -e "\n" | telnet $MICRO_SERVICE_IP $MICRO_SERVICE_PORT 2>/dev/null | grep Connected | wc -l` +isSuccess "$MICRO_SERVICE_NAME start" + + +#check visualis-server +sleep 10 #for visualis-server +MICRO_SERVICE_NAME=visualis-server +MICRO_SERVICE_IP=$VISUALIS_SERVER_INSTALL_IP +MICRO_SERVICE_PORT=$VISUALIS_SERVER_PORT +sh $workDir/checkMicro.sh $MICRO_SERVICE_NAME $MICRO_SERVICE_IP $MICRO_SERVICE_PORT +state=`echo -e "\n" | telnet $MICRO_SERVICE_IP $MICRO_SERVICE_PORT 2>/dev/null | grep Connected | wc -l` +isSuccess "$MICRO_SERVICE_NAME start" + diff --git a/conf/config.sh b/conf/config.sh index b5a00f706..895c2c02c 100644 --- a/conf/config.sh +++ b/conf/config.sh @@ -15,7 +15,7 @@ WORKSPACE_USER_ROOT_PATH=file:///tmp/linkis/ RESULT_SET_ROOT_PATH=hdfs:///tmp/linkis ### 1、DataCheck APPJOINT,This service is used to provide DataCheck capability. -HIVE_META_URL=jdbc:mysql://127.0.0.1:3306/linkis?characterEncoding=UTF-8 +HIVE_META_URL=jdbc:mysql://127.0.0.1:3306/hivemeta?characterEncoding=UTF-8 HIVE_META_USER=xxx HIVE_META_PASSWORD=xxx @@ -50,16 +50,16 @@ GATEWAY_PORT=9001 ### SSH Port SSH_PORT=22 -#for azkaban +#Used to store the azkaban project transformed by DSS WDS_SCHEDULER_PATH=file:///appcom/tmp/wds/scheduler ###The IP address and port are written into the database here, so be sure to plan ahead ## visualis-server VISUALIS_SERVER_INSTALL_IP=127.0.0.1 VISUALIS_SERVER_PORT=9007 -### visualis nginx acess ip +### visualis nginx acess ip,keep consistent with DSS front end VISUALIS_NGINX_IP=0.0.0.0 -VISUALIS_NGINX_PORT=9009 +VISUALIS_NGINX_PORT=8088 ### Eventchecker APPJOINT ### This service is used to provide Eventchecker capability. it's config in db.sh same as dss-server. diff --git a/db/azkaban.sql b/db/azkaban.sql new file mode 100644 index 000000000..489ded7bb --- /dev/null +++ b/db/azkaban.sql @@ -0,0 +1,3 @@ +INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'schedulis', NULL, '0', '1', NULL, '0', NULL, NULL, '1', NULL, NULL); +UPDATE `dss_application` SET url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT', project_url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT/manager?project=${projectName}',homepage_url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT/homepage' WHERE `name` in + ('schedulis'); diff --git a/db/dss_dml.sql b/db/dss_dml.sql index 3ee9fca20..27146dedc 100644 --- a/db/dss_dml.sql +++ b/db/dss_dml.sql @@ -1,6 +1,5 @@ INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'linkis', null, '0', '1', NULL, '0', '/home', NULL, '0', '/home', NULL); INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'visualis', null, '0', '1', NULL, '0', NULL, NULL, '1', NULL, NULL); -INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'schedulis', NULL, '0', '1', NULL, '0', NULL, NULL, '1', NULL, NULL); INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'workflow', null, '0', '1', NULL, '0', '/workflow', NULL, '0', '/project', NULL); INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'console', null, '0', '1', NULL, '0', '/console', NULL, '0', '/console', NULL); @@ -30,7 +29,6 @@ INSERT INTO `dss_flow_taxonomy` (`id`, `name`, `description`, `creator_id`, `cre UPDATE `dss_application` SET url = 'http://GATEWAY_INSTALL_IP_2:GATEWAY_PORT' WHERE `name` in('linkis','workflow'); UPDATE `dss_application` SET url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT' WHERE `name` in('visualis'); UPDATE `dss_application` SET project_url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT/dss/visualis/#/project/${projectId}',homepage_url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT/dss/visualis/#/projects' WHERE `name` in('visualis'); -UPDATE `dss_application` SET url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT', project_url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT/manager?project=${projectName}',homepage_url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT/homepage' WHERE `name` in('schedulis'); UPDATE `dss_workflow_node` SET jump_url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT/dss/visualis/#/project/${projectId}/display/${nodeId}' where node_type = 'linkis.appjoint.visualis.display'; UPDATE `dss_workflow_node` SET jump_url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT/dss/visualis/#/project/${projectId}/portal/${nodeId}/portalName/${nodeName}' where node_type = 'linkis.appjoint.visualis.dashboard'; @@ -59,4 +57,4 @@ insert into `linkis_config_key_tree` VALUES(NULL,@key_id2,@tree_id1); insert into `linkis_config_key_tree` VALUES(NULL,@key_id3,@tree_id1); insert into `linkis_config_key_tree` VALUES(NULL,@key_id4,@tree_id1); insert into `linkis_config_key_tree` VALUES(NULL,@key_id5,@tree_id1); -insert into `linkis_config_key_tree` VALUES(NULL,@key_id6,@tree_id2); \ No newline at end of file +insert into `linkis_config_key_tree` VALUES(NULL,@key_id6,@tree_id2); diff --git a/db/qualitis.sql b/db/qualitis.sql new file mode 100644 index 000000000..04fb15cfb --- /dev/null +++ b/db/qualitis.sql @@ -0,0 +1,3 @@ +INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'qualitis', 'http://QUALITIS_ADRESS_IP_2:QUALITIS_ADRESS_PORT', '0', '1', NULL, '1', 'http://QUALITIS_ADRESS_IP_2:QUALITIS_ADRESS_PORT/#/projects/list?id=${projectId}&flow=true', NULL, '1', 'http://QUALITIS_ADRESS_IP_2:QUALITIS_ADRESS_PORT/#/dashboard', 'http://QUALITIS_ADRESS_IP_2:QUALITIS_ADRESS_PORT/qualitis/api/v1/redirect'); +SELECT @qualitis_appid:=id from dss_application WHERE `name` = 'qualitis'; +INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.appjoint.qualitis', @qualitis_appid, NULL, '1', '0', '1', 'http://QUALITIS_ADRESS_IP_2:QUALITIS_ADRESS_PORT/#/addGroupTechniqueRule?tableType=1&id=${projectId}&ruleGroupId=${ruleGroupId}&nodeId=${nodeId}'); \ No newline at end of file diff --git a/dss-flow-execution-entrance/bin/start-dss-flow-execution-entrance.sh b/dss-flow-execution-entrance/bin/start-dss-flow-execution-entrance.sh index 5ce15dc90..9bd4a006c 100644 --- a/dss-flow-execution-entrance/bin/start-dss-flow-execution-entrance.sh +++ b/dss-flow-execution-entrance/bin/start-dss-flow-execution-entrance.sh @@ -1,33 +1,49 @@ #!/bin/bash - cd `dirname $0` cd .. HOME=`pwd` -export DWS_ENGINE_MANAGER_HOME=$HOME -export DWS_ENGINE_MANAGER_PID=$HOME/bin/linkis.pid +export SERVER_PID=$HOME/bin/linkis.pid +export SERVER_LOG_PATH=$HOME/logs +export SERVER_CLASS=com.webank.wedatasphere.linkis.DataWorkCloudApplication -if [[ -f "${DWS_ENGINE_MANAGER_PID}" ]]; then - pid=$(cat ${DWS_ENGINE_MANAGER_PID}) - if kill -0 ${pid} >/dev/null 2>&1; then - echo "FlowExecution Entrance is already running." - return 0; - fi +if test -z "$SERVER_HEAP_SIZE" +then + export SERVER_HEAP_SIZE="512M" fi -export DWS_ENGINE_MANAGER_LOG_PATH=$HOME/logs -export DWS_ENGINE_MANAGER_HEAP_SIZE="1G" -export DWS_ENGINE_MANAGER_JAVA_OPTS="-Xms$DWS_ENGINE_MANAGER_HEAP_SIZE -Xmx$DWS_ENGINE_MANAGER_HEAP_SIZE -XX:+UseG1GC -XX:MaxPermSize=500m -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=11730" +if test -z "$SERVER_JAVA_OPTS" +then + export SERVER_JAVA_OPTS=" -Xmx$SERVER_HEAP_SIZE -XX:+UseG1GC -Xloggc:$HOME/logs/linkis-gc.log" +fi -echo $HOME/lib/ +if [[ -f "${SERVER_PID}" ]]; then + pid=$(cat ${SERVER_PID}) + if kill -0 ${pid} >/dev/null 2>&1; then + echo "Server is already running." + exit 1 + fi +fi -nohup java $DWS_ENGINE_MANAGER_JAVA_OPTS -cp $HOME/conf:$HOME/lib/* com.webank.wedatasphere.linkis.DataWorkCloudApplication 2>&1 > $DWS_ENGINE_MANAGER_LOG_PATH/linkis.out & +nohup java $SERVER_JAVA_OPTS -cp $HOME/conf:$HOME/lib/* $SERVER_CLASS 2>&1 > $SERVER_LOG_PATH/linkis.out & pid=$! if [[ -z "${pid}" ]]; then - echo "FlowExecution Entrance start failed!" + echo "server $SERVER_NAME start failed!" exit 1 else - echo "FlowExecution Entrance start succeeded!" - echo $pid > $DWS_ENGINE_MANAGER_PID + echo "server $SERVER_NAME start succeeded!" + echo $pid > $SERVER_PID sleep 1 fi + + + + + + + + + + + + diff --git a/dss-server/bin/start-dss-server.sh b/dss-server/bin/start-dss-server.sh index e53e44a16..518cd8da1 100644 --- a/dss-server/bin/start-dss-server.sh +++ b/dss-server/bin/start-dss-server.sh @@ -1,33 +1,39 @@ #!/bin/bash - cd `dirname $0` cd .. HOME=`pwd` -export DWS_ENGINE_MANAGER_HOME=$HOME -export DWS_ENGINE_MANAGER_PID=$HOME/bin/linkis.pid +export SERVER_PID=$HOME/bin/linkis.pid +export SERVER_LOG_PATH=$HOME/logs +export SERVER_CLASS=com.webank.wedatasphere.dss.DSSSpringApplication + +if test -z "$SERVER_HEAP_SIZE" +then + export SERVER_HEAP_SIZE="512M" +fi + +if test -z "$SERVER_JAVA_OPTS" +then + export SERVER_JAVA_OPTS=" -Xmx$SERVER_HEAP_SIZE -XX:+UseG1GC -Xloggc:$HOME/logs/linkis-gc.log" +fi -if [[ -f "${DWS_ENGINE_MANAGER_PID}" ]]; then - pid=$(cat ${DWS_ENGINE_MANAGER_PID}) +if [[ -f "${SERVER_PID}" ]]; then + pid=$(cat ${SERVER_PID}) if kill -0 ${pid} >/dev/null 2>&1; then - echo "DSS SERVER is already running." - return 0; + echo "Server is already running." + exit 1 fi fi -export DWS_ENGINE_MANAGER_LOG_PATH=$HOME/logs -export DWS_ENGINE_MANAGER_HEAP_SIZE="1G" -export DWS_ENGINE_MANAGER_JAVA_OPTS="-Xms$DWS_ENGINE_MANAGER_HEAP_SIZE -Xmx$DWS_ENGINE_MANAGER_HEAP_SIZE -XX:+UseG1GC -XX:MaxPermSize=500m -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=11729" - -nohup java $DWS_ENGINE_MANAGER_JAVA_OPTS -cp $HOME/conf:$HOME/lib/* com.webank.wedatasphere.dss.DSSSpringApplication 2>&1 > $DWS_ENGINE_MANAGER_LOG_PATH/linkis.out & +nohup java $SERVER_JAVA_OPTS -cp $HOME/conf:$HOME/lib/* $SERVER_CLASS 2>&1 > $SERVER_LOG_PATH/linkis.out & pid=$! if [[ -z "${pid}" ]]; then - echo "DSS SERVER start failed!" - sleep 1 + echo "server $SERVER_NAME start failed!" exit 1 else - echo "DSS SERVER start succeeded!" - echo $pid > $DWS_ENGINE_MANAGER_PID + echo "server $SERVER_NAME start succeeded!" + echo $pid > $SERVER_PID sleep 1 fi -exit 1 + + diff --git a/plugins/linkis/linkis-appjoint-entrance/bin/start-linkis-appjoint-entrance.sh b/plugins/linkis/linkis-appjoint-entrance/bin/start-linkis-appjoint-entrance.sh index 0128a4d1c..4436def35 100644 --- a/plugins/linkis/linkis-appjoint-entrance/bin/start-linkis-appjoint-entrance.sh +++ b/plugins/linkis/linkis-appjoint-entrance/bin/start-linkis-appjoint-entrance.sh @@ -1,36 +1,37 @@ #!/bin/bash - cd `dirname $0` cd .. -HOE=`pwd` - export DWS_ENTRANCE_HOE=$HOE +HOME=`pwd` -export DWS_ENTRANCE_PID=$HOE/bin/linkis-appjoint-entrance.pid +export SERVER_PID=$HOME/bin/linkis.pid +export SERVER_LOG_PATH=$HOME/logs +export SERVER_CLASS=com.webank.wedatasphere.linkis.DataWorkCloudApplication -if [[ -f "${DWS_ENTRANCE_PID}" ]]; then - pid=$(cat ${DWS_ENTRANCE_PID}) - if kill -0 ${pid} >/dev/null 2>&1; then - echo "Entrance is already running." - return 0; - fi +if test -z "$SERVER_HEAP_SIZE" +then + export SERVER_HEAP_SIZE="512M" fi -export DWS_ENTRANCE_LOG_PATH=$HOE/logs -export DWS_ENTRANCE_DEBUG="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=19959" -export DWS_ENTRANCE_HEAP_SIZE="2G" -export DWS_ENTRANCE_JAVA_OPTS="-Xms$DWS_ENTRANCE_HEAP_SIZE -Xmx$DWS_ENTRANCE_HEAP_SIZE -XX:+UseG1GC -XX:MaxPermSize=500m $DWS_ENTRANCE_DEBUG" - -cmd="nohup java $DWS_ENTRANCE_JAVA_OPTS -cp $HOE/conf:$HOE/lib/* com.webank.wedatasphere.linkis.DataWorkCloudApplication 2>&1 > $DWS_ENTRANCE_LOG_PATH/linkis.out &" -#echo "CMD IS $cmd" +if test -z "$SERVER_JAVA_OPTS" +then + export SERVER_JAVA_OPTS=" -Xmx$SERVER_HEAP_SIZE -XX:+UseG1GC -Xloggc:$HOME/logs/linkis-gc.log" +fi +if [[ -f "${SERVER_PID}" ]]; then + pid=$(cat ${SERVER_PID}) + if kill -0 ${pid} >/dev/null 2>&1; then + echo "Server is already running." + exit 1 + fi +fi -nohup java $DWS_ENTRANCE_JAVA_OPTS -cp $HOE/conf:$HOE/lib/* com.webank.wedatasphere.linkis.DataWorkCloudApplication 2>&1 > $DWS_ENTRANCE_LOG_PATH/linkis.out & +nohup java $SERVER_JAVA_OPTS -cp $HOME/conf:$HOME/lib/* $SERVER_CLASS 2>&1 > $SERVER_LOG_PATH/linkis.out & pid=$! if [[ -z "${pid}" ]]; then - echo "AppJoint Entrance start failed!" + echo "server $SERVER_NAME start failed!" exit 1 else - echo "AppJoint Entrance start succeeded!" - echo $pid > $DWS_ENTRANCE_PID + echo "server $SERVER_NAME start succeeded!" + echo $pid > $SERVER_PID sleep 1 fi diff --git a/plugins/linkis/linkis-appjoint-entrance/bin/stop-linkis-appjoint-entrance.sh b/plugins/linkis/linkis-appjoint-entrance/bin/stop-linkis-appjoint-entrance.sh index f3aad1635..7d4703250 100644 --- a/plugins/linkis/linkis-appjoint-entrance/bin/stop-linkis-appjoint-entrance.sh +++ b/plugins/linkis/linkis-appjoint-entrance/bin/stop-linkis-appjoint-entrance.sh @@ -4,7 +4,7 @@ cd `dirname $0` cd .. HOE=`pwd` -export DWS_ENTRANCE_PID=$HOE/bin/linkis-appjoint-entrance.pid +export DWS_ENTRANCE_PID=$HOE/bin/linkis.pid function wait_for_DWS_ENGINE_MANAGER_to_die() { local pid -- Gitee From 94c3586c8488d46940b9323fc47fc5c49057604e Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Fri, 13 Dec 2019 17:33:17 +0800 Subject: [PATCH 022/238] Automated Installation Enhance close #37 --- bin/checkEnv.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bin/checkEnv.sh b/bin/checkEnv.sh index c377c05ea..dffcb7718 100644 --- a/bin/checkEnv.sh +++ b/bin/checkEnv.sh @@ -29,14 +29,18 @@ check_cmd() { need_cmd() { if ! check_cmd "$1"; then - err "need '$1' (command not found)" + err "need '$1' (your linux command not found)" fi } -echo "<-----start to check used cmd---->" +echo "<-----start to check linux cmd:yum java mysql unzip expect telnet sed tar---->" need_cmd yum need_cmd java need_cmd mysql need_cmd unzip need_cmd expect need_cmd telnet -echo "<-----end to check used cmd------>" +need_cmd sed +need_cmd tar +need_cmd source +need_cmd hostname +echo "<-----end to check linux cmd:yum java mysql unzip expect telnet sed tar------>" -- Gitee From e8484c30b36a3e0b871f7e7889bb03a0dfe07ca8 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Fri, 13 Dec 2019 18:04:51 +0800 Subject: [PATCH 023/238] Quick installation use documentation update close #39 --- ...05\344\275\277\347\224\250\346\226\207\346\241\243.md" | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index c6b62101e..4825b368c 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -85,7 +85,7 @@ Nginx,[如何安装Nginx](https://www.tecmint.com/install-nginx-on-centos-7/) RESULT_SET_ROOT_PATH=hdfs:///tmp/linkis # 结果集文件路径,用于存储Job的结果集文件 #用于DATACHECK校验 - HIVE_META_URL=jdbc:mysql://127.0.0.1:3306/linkis?characterEncoding=UTF-8 + HIVE_META_URL=jdbc:mysql://127.0.0.1:3306/hivemeta?characterEncoding=UTF-8 HIVE_META_USER=xxx HIVE_META_PASSWORD=xxx @@ -98,7 +98,7 @@ Nginx,[如何安装Nginx](https://www.tecmint.com/install-nginx-on-centos-7/) ``` ```properties - # 设置DSS-Server和Eventchecker AppJoint的数据库的连接信息。 + # 设置DSS-Server和Eventchecker AppJoint的数据库的连接信息,需要和linkis保持同库 MYSQL_HOST= MYSQL_PORT= MYSQL_DB= @@ -201,7 +201,7 @@ Azkaban [如何安装Azkaban](https://github.com/azkaban/azkaban) RESULT_SET_ROOT_PATH=hdfs:///tmp/linkis # 结果集文件路径,用于存储Job的结果集文件 - WDS_SCHEDULER_PATH=file:///appcom/tmp/wds/scheduler #Azkaban工程存储目录 + WDS_SCHEDULER_PATH=file:///appcom/tmp/wds/scheduler #DSS工程转换成Azkaban工程后zip包的存储路径 #1、用于DATACHECK HIVE_META_URL=jdbc:mysql://127.0.0.1:3306/linkis?characterEncoding=UTF-8 @@ -223,7 +223,7 @@ Azkaban [如何安装Azkaban](https://github.com/azkaban/azkaban) ``` ```properties - # 设置DSS-Server和Eventchecker AppJoint的数据库的连接信息。 + # 设置DSS-Server和Eventchecker AppJoint的数据库的连接信息,需要和linkis保持同库 MYSQL_HOST= MYSQL_PORT= MYSQL_DB= -- Gitee From e528596180fd8da1bc17293e62a7f1762f7fb61e Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Mon, 16 Dec 2019 15:48:06 +0800 Subject: [PATCH 024/238] Quick installation use documentation update close #39 --- ...3\205\344\275\277\347\224\250\346\226\207\346\241\243.md" | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index 4825b368c..f7e8d9bfb 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -395,12 +395,15 @@ server { ### 4.谷歌浏览器访问: ```http://nginx_ip:nginx_port``` -如何详细使用DSS, 点我进入 [DSS详细使用文档](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch3/DSS_User_Manual.md) +**试用用户和密码均为hadoop,更多用户配置,详见** [Linkis LDAP](https://github.com/WeBankFinTech/Linkis/wiki/%E9%83%A8%E7%BD%B2%E5%92%8C%E7%BC%96%E8%AF%91%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93) + +如何详细使用DSS, 点我进入 [DSS快速使用文档](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch3/DSS_User_Manual.md) ## 4.3、常见问题 (1)用户token为空 + ``` sudo vi dss-server/conf/token.properties ``` -- Gitee From 1ea2369a614bede7a06db50a4ee5e9c8de67d1a0 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Mon, 16 Dec 2019 16:10:01 +0800 Subject: [PATCH 025/238] Quick installation use documentation update close #39 --- ...\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index f7e8d9bfb..f9a2af2d7 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -395,7 +395,7 @@ server { ### 4.谷歌浏览器访问: ```http://nginx_ip:nginx_port``` -**试用用户和密码均为hadoop,更多用户配置,详见** [Linkis LDAP](https://github.com/WeBankFinTech/Linkis/wiki/%E9%83%A8%E7%BD%B2%E5%92%8C%E7%BC%96%E8%AF%91%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93) +**试用用户和密码均为部署用户,更多用户配置,详见** [Linkis LDAP](https://github.com/WeBankFinTech/Linkis/wiki/%E9%83%A8%E7%BD%B2%E5%92%8C%E7%BC%96%E8%AF%91%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93) 如何详细使用DSS, 点我进入 [DSS快速使用文档](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch3/DSS_User_Manual.md) -- Gitee From e90d127b25e73a3095badb718606e38323538a20 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Mon, 16 Dec 2019 16:30:16 +0800 Subject: [PATCH 026/238] update user manual documentation --- README-ZH.md | 2 ++ docs/zh_CN/ch3/DSS_User_Manual.md | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/README-ZH.md b/README-ZH.md index 15c13c1e3..20e5f78df 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -142,6 +142,8 @@ DSS主要特点: [DSS编译文档](docs/zh_CN/ch1/DSS编译文档.md) +[快速使用文档](docs/zh_CN/ch3/DataSphere_Studio_QuickStart.md) + [用户手册](docs/zh_CN/ch3/DSS_User_Manual.md) [外部系统快速接入DSS](docs/zh_CN/ch4/第三方系统接入DSS指南.md) diff --git a/docs/zh_CN/ch3/DSS_User_Manual.md b/docs/zh_CN/ch3/DSS_User_Manual.md index 470ae9c7c..f366e5de3 100644 --- a/docs/zh_CN/ch3/DSS_User_Manual.md +++ b/docs/zh_CN/ch3/DSS_User_Manual.md @@ -1,3 +1,9 @@ +## 快速登录 +      为了方便用户使用,系统默认通过使用Linkis的部署用户名进行登录,比如是hadoop部署的可以直接通过 用户:hadoop,密码:hadoop(密码就是用户名)来进行登录。 首先输入前端容器地址:192.168.xx.xx:8888 接着输入用户名密码:hadoop/hadoop +![quick_start00](/images/zh_CN/chapter3/quickstart/quick_start00.png) + +__注意:__ 如果要支持多用户登录,DSS的用户登录依赖Linkis,需要在linkis-GateWay的配置里面进行配置,Linkis-GateWay默认支持LDAP。 + ## 1 功能简介        DSS作为一站式数据应用开发门户,定位为闭环涵盖数据应用的全流程,满足从数据ETL、数据研发、可视化展现、数据治理、数据输出到工作流调度的数据应用全生命周期开发场景,现已经开源的组件包括如下图所示: -- Gitee From b6c68fbe725a8cf64c0f401cebaf3df783f63344 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Tue, 17 Dec 2019 12:12:01 +0800 Subject: [PATCH 027/238] DSS Quick Install Documentation Update --- ...43\205\344\275\277\347\224\250\346\226\207\346\241\243.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index f9a2af2d7..505eb6581 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -204,7 +204,7 @@ Azkaban [如何安装Azkaban](https://github.com/azkaban/azkaban) WDS_SCHEDULER_PATH=file:///appcom/tmp/wds/scheduler #DSS工程转换成Azkaban工程后zip包的存储路径 #1、用于DATACHECK - HIVE_META_URL=jdbc:mysql://127.0.0.1:3306/linkis?characterEncoding=UTF-8 + HIVE_META_URL=jdbc:mysql://127.0.0.1:3306/hivemeta?characterEncoding=UTF-8 HIVE_META_USER=xxx HIVE_META_PASSWORD=xxx #2、用于Qualitis @@ -341,7 +341,7 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/ 添加如下内容: ``` server { - listen 8080;# 访问端口 + listen 8088;# 访问端口 server_name localhost; #charset koi8-r; #access_log /var/log/nginx/host.access.log main; -- Gitee From 38cb775713afd7124905225b8bc14b94418a5c3a Mon Sep 17 00:00:00 2001 From: sargentti Date: Wed, 18 Dec 2019 11:24:35 +0800 Subject: [PATCH 028/238] add DSS install FAQ. --- ...56\351\242\230\345\210\227\350\241\250.md" | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 "docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" diff --git "a/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" "b/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" new file mode 100644 index 000000000..86ccf92b5 --- /dev/null +++ "b/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" @@ -0,0 +1,85 @@ +## DSS安装常见问题列表 + +**本文档汇总DSS安装过程中所有问题列表及解决方式,为社区用户安装DSS提供参考。** + + +#### (1) 创建工程提示用户token为空 + +``` +sudo vi dss-server/conf/token.properties +``` + +添加用户 + +``` +xxx=xxx +``` + +#### (2) visualis执行报错,找不到driver驱动 + +``` +Caused by: java.lang.Exception: /data/DSSInstall/visualis-server/bin/phantomjsis not executable! +``` + +下载 [driver驱动](https://phantomjs.org/download.html),把phantomjs二进制文件放入visualis-server的bin目录下即可。 + + +#### (3) dss-0.5.0简单版DSS创建工程失败 + + +删除数据库中表dss_application的schedulis和qualitis记录 + + +#### (4) DSS多次重复安装后报错:TooManyResultsException:Expected on result + + +删除数据库中表linkis_user、dss_user、linkis_application中的重复记录 + +#### (5) 访问前端出错 + +``` +Unexpected token { in JSON at position 4 +``` + +检查前端配置文件中linkis gateway的url配置 + +#### (6) DSS创建工程报表linkis.linkis_resources_task不存在 + +``` +Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'linkis.linkis_resources_task' doesn't exist +``` + +进入mysql,选择linkis的数据库,手动执行linkis安装目录中,db/moudle/linkis-bml.sql文件。 + + +#### (7)如何配置ladp登陆 + +修改linkis-gateway配置目录下的linkis.properties文件,增加LDAP登陆认证。 + +#### (8)上传文件大小限制 + +``` +sudo vi /etc/nginx/nginx.conf +``` + +更改上传大小 + +``` +client_max_body_size 200m +``` + +#### (9)接口超时 + +``` +sudo vi /etc/nginx/conf.d/dss.conf +``` + + +更改接口超时时间 + +``` +proxy_read_timeout 600s +``` + +**如果您在安装和使用DSS过程中遇到Linkis相关问题,请访问** +[linkis常见问题列表]([https://github.com/WeBankFinTech/Linkis/wiki/%E9%83%A8%E7%BD%B2%E5%92%8C%E7%BC%96%E8%AF%91%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93](https://github.com/WeBankFinTech/Linkis/wiki/%E9%83%A8%E7%BD%B2%E5%92%8C%E7%BC%96%E8%AF%91%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93)) \ No newline at end of file -- Gitee From b682eabee547351122f87de54abfb9550c7bc59c Mon Sep 17 00:00:00 2001 From: sargentti Date: Wed, 18 Dec 2019 11:28:55 +0800 Subject: [PATCH 029/238] add DSS publish to scheduling design doc. --- ...66\346\236\204\350\256\276\350\256\241.md" | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 "docs/zh_CN/ch4/DSS\345\267\245\347\250\213\345\217\221\345\270\203\350\260\203\345\272\246\347\263\273\347\273\237\346\236\266\346\236\204\350\256\276\350\256\241.md" diff --git "a/docs/zh_CN/ch4/DSS\345\267\245\347\250\213\345\217\221\345\270\203\350\260\203\345\272\246\347\263\273\347\273\237\346\236\266\346\236\204\350\256\276\350\256\241.md" "b/docs/zh_CN/ch4/DSS\345\267\245\347\250\213\345\217\221\345\270\203\350\260\203\345\272\246\347\263\273\347\273\237\346\236\266\346\236\204\350\256\276\350\256\241.md" new file mode 100644 index 000000000..14dbccac5 --- /dev/null +++ "b/docs/zh_CN/ch4/DSS\345\267\245\347\250\213\345\217\221\345\270\203\350\260\203\345\272\246\347\263\273\347\273\237\346\236\266\346\236\204\350\256\276\350\256\241.md" @@ -0,0 +1,30 @@ +# DataSphere Studio发布调度系统架构设计 + + + +## 一、背景 + + 目前在大数据领域存在许多种批量定时调度系统,如Azkaban、Airflow、EasyScheduler等,DSS支持将设计好的DAG工作流 +发布到不同的调度系统,系统默认支持了发布到Azkaban的实现。在DSS中主要完工作流的编排设计,节点的参数设置, +脚本代码编写,图表设计等需要交互式的操作,还可以在DSS中实时执行,并调试好所有节点的可执行代码。发布到调度系统后 +,由调度系统根据定时任务的配置,定时调度执行。 + +## 二、架构设计 + +![发布调度架构图](../../../images/zh_CN/charpter3/publish/publichtoscheduling.png) + +## 三、发布流程 + +(1)从数据库读取最新版本的工程、工作流信息,获取所有的保存在BML库工作流JSON文件。 + +(2)将上面的数据库内容,JSON文件内容分别转成DSS中的DWSProject,DWSFlow,如果存在子flow,则需要一并设置到flow中,保持原来的层级关系和依赖关系,构建好DWSProject,其中包含了工程下所有的DWSFlow。 + 一个工作流JSON包含了所有节点的定义,并存储了节点之间的依赖关系,以及工作流自身的属性信息。 + +(3)将DWSProject经过工程转换器转成SchedulerProject,转成SchedulerProject的过程中,同时完成了DWSJSONFlow到SchedulerFlow的转换,也完成了DWSNode到SchedulerNode的转换。 + +(4)使用ProjectTuning对整个SchedulerProject工程进行tuning操作,用于完成工程发布前的整体调整操作,在Azkaban的实现中主要完成了工程的路径设置和工作流的存储路径设置。 + +(5)ProjectPublishHook操作,hook可以根据不同的调度系统进行实现,且可分为发布前的hook和发布后的hook,这些都会被统一执行。 + 发布前的hook包含对工程的解析,工作流的解析,节点的解析,以及生成对应的资源文件,属性文件,节点描述文件等。这个需要根据不同的调度系统进行实现。 + +(6)发布工程,打包好经过转换、解析生成的工程目录文件,并上传到对应的调度系统。 -- Gitee From 58a11c86aa810191c4183c196e37afe1532b8db1 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 19 Dec 2019 14:56:38 +0800 Subject: [PATCH 030/238] DSS FAQ update DSS FAQ update --- ...56\351\242\230\345\210\227\350\241\250.md" | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git "a/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" "b/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" index 86ccf92b5..c62ee3edd 100644 --- "a/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" +++ "b/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" @@ -51,12 +51,41 @@ Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'linkis. 进入mysql,选择linkis的数据库,手动执行linkis安装目录中,db/moudle/linkis-bml.sql文件。 - #### (7)如何配置ladp登陆 修改linkis-gateway配置目录下的linkis.properties文件,增加LDAP登陆认证。 -#### (8)上传文件大小限制 + +#### (8) visualis可视化服务访问报错 + +a) 确保visualis-server已经启动。 + +b)检查visualis-server安装目录下的application.yml配置,确保以下配置准确无误 + +``` + url: http://0.0.0.0:0000/dws/visualis #frontend index page full path,此处保持与DSS前端Nginx访问IP地址和端口一致 + access: + address: 0.0.0.0 #frontend address,此处保持与DSS前端Nginx访问IP地址一致 + port: 0000#frontend port,此处保持与DSS前端Nginx访问端口一致 +``` + +c) 确保数据库表dss_application中 visualis记录行,访问地址与DSS前端Nginx访问IP地址和端口一致。 + +d) 访问visualis出现404错误,确保Nginx配置文件中关于visualis的访问路径配置正确。 + +``` + location /dss/visualis { + root /data/DSSFront; # 示例visualis前端静态文件目录 + autoindex on; + } + location / { + root /data/DSSFront/dist; # 示例DSS前端静态文件目录 + index index.html index.html; + } +``` + + +#### (9)上传文件大小限制 ``` sudo vi /etc/nginx/nginx.conf @@ -68,7 +97,7 @@ sudo vi /etc/nginx/nginx.conf client_max_body_size 200m ``` -#### (9)接口超时 +#### (10)接口超时 ``` sudo vi /etc/nginx/conf.d/dss.conf @@ -82,4 +111,4 @@ proxy_read_timeout 600s ``` **如果您在安装和使用DSS过程中遇到Linkis相关问题,请访问** -[linkis常见问题列表]([https://github.com/WeBankFinTech/Linkis/wiki/%E9%83%A8%E7%BD%B2%E5%92%8C%E7%BC%96%E8%AF%91%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93](https://github.com/WeBankFinTech/Linkis/wiki/%E9%83%A8%E7%BD%B2%E5%92%8C%E7%BC%96%E8%AF%91%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93)) \ No newline at end of file +[linkis常见问题列表]([https://github.com/WeBankFinTech/Linkis/wiki/%E9%83%A8%E7%BD%B2%E5%92%8C%E7%BC%96%E8%AF%91%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93]) -- Gitee From 21f69c1209f516f925b6834c2738cac75325760f Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 19 Dec 2019 14:58:08 +0800 Subject: [PATCH 031/238] DSS FAQ Update DSS FAQ Update --- ...\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" "b/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" index c62ee3edd..8df77b365 100644 --- "a/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" +++ "b/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" @@ -111,4 +111,4 @@ proxy_read_timeout 600s ``` **如果您在安装和使用DSS过程中遇到Linkis相关问题,请访问** -[linkis常见问题列表]([https://github.com/WeBankFinTech/Linkis/wiki/%E9%83%A8%E7%BD%B2%E5%92%8C%E7%BC%96%E8%AF%91%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93]) +[linkis常见问题列表](https://github.com/WeBankFinTech/Linkis/wiki/%E9%83%A8%E7%BD%B2%E5%92%8C%E7%BC%96%E8%AF%91%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93) -- Gitee From d94ae1604cfcb3f62a9f40aa8ae196deb31c25d7 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 19 Dec 2019 15:05:10 +0800 Subject: [PATCH 032/238] DSS FAQ Update DSS FAQ Update --- ...\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" "b/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" index 8df77b365..e321bc7f3 100644 --- "a/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" +++ "b/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" @@ -63,7 +63,7 @@ a) 确保visualis-server已经启动。 b)检查visualis-server安装目录下的application.yml配置,确保以下配置准确无误 ``` - url: http://0.0.0.0:0000/dws/visualis #frontend index page full path,此处保持与DSS前端Nginx访问IP地址和端口一致 + url: http://0.0.0.0:0000/dss/visualis 此出url中的IP和端口必须保持与DSS前端Nginx访问的IP地址和端口一致 access: address: 0.0.0.0 #frontend address,此处保持与DSS前端Nginx访问IP地址一致 port: 0000#frontend port,此处保持与DSS前端Nginx访问端口一致 -- Gitee From ec5439d644492f33fd8559aa2215ecbffef73998 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 19 Dec 2019 15:09:30 +0800 Subject: [PATCH 033/238] DSS FAQ Update DSS FAQ Update --- ...\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" "b/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" index e321bc7f3..0b9e77982 100644 --- "a/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" +++ "b/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" @@ -63,7 +63,7 @@ a) 确保visualis-server已经启动。 b)检查visualis-server安装目录下的application.yml配置,确保以下配置准确无误 ``` - url: http://0.0.0.0:0000/dss/visualis 此出url中的IP和端口必须保持与DSS前端Nginx访问的IP地址和端口一致 + url: http://0.0.0.0:0000/dss/visualis 此处url中的IP和端口必须保持与DSS前端Nginx访问的IP地址和端口一致 access: address: 0.0.0.0 #frontend address,此处保持与DSS前端Nginx访问IP地址一致 port: 0000#frontend port,此处保持与DSS前端Nginx访问端口一致 -- Gitee From 388100d5dfbeaba0edc563940d7983b179814206 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 19 Dec 2019 15:15:54 +0800 Subject: [PATCH 034/238] DSS Quick Install Documentation Update --- ...77\347\224\250\346\226\207\346\241\243.md" | 60 +------------------ 1 file changed, 1 insertion(+), 59 deletions(-) diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index 505eb6581..1f63fdfed 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -401,62 +401,4 @@ server { ## 4.3、常见问题 -(1)用户token为空 - - -``` -sudo vi dss-server/conf/token.properties -``` - -添加用户 - -``` -xxx=xxx -``` - -(2)visualis执行报错 - -``` -Caused by: java.lang.Exception: /data/DSSInstall/visualis-server/bin/phantomjsis not executable! -``` - -下载 [driver驱动](https://phantomjs.org/download.html),把phantomjs二进制文件放入visualis-server的bin目录下即可。 - - -(3)简单版DSS创建工程失败 - - -删除数据库中表dss_application的schedulis和qualitis记录 - - -(4)多次重复安装后报错:TooManyResultsException:Expected on result - - -删除数据库中表linkis_user和dss_user中的重复记录 - - -(5)上传文件大小限制 - -``` -sudo vi /etc/nginx/nginx.conf -``` - -更改上传大小 - -``` -client_max_body_size 200m -``` - - (6)接口超时 - -``` -sudo vi /etc/nginx/conf.d/dss.conf -``` - - -更改接口超时时间 - -``` -proxy_read_timeout 600s -``` - +[DSS安装常见问题](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch1/DSS%E5%AE%89%E8%A3%85%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%88%97%E8%A1%A8.md) \ No newline at end of file -- Gitee From 72e0c894bd11c2d8031f63193ce3662a86b0d6fc Mon Sep 17 00:00:00 2001 From: wushengyeyouya <690574002@qq.com> Date: Thu, 19 Dec 2019 12:04:21 +0800 Subject: [PATCH 035/238] update README-ZH.md --- README-ZH.md | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/README-ZH.md b/README-ZH.md index 20e5f78df..1b76faaa4 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -7,13 +7,15 @@ ## 引言 -DataSphere Studio(简称DSS)是微众银行大数据平台——WeDataSphere,自研的一站式数据应用开发管理门户。 +DataSphere Studio(简称DSS)是微众银行自研的一站式数据应用开发管理门户。 -基于 [**Linkis**](https://github.com/WeBankFinTech/Linkis) 计算中间件构建,可轻松整合上层各数据应用系统,让数据应用开发变得简洁又易用。 +基于插拔式的集成框架设计,及计算中间件 [**Linkis**](https://github.com/WeBankFinTech/Linkis) ,可轻松接入上层各种数据应用系统,让数据开发变得简洁又易用。 -DataSphere Studio定位为数据应用开发门户,闭环涵盖数据应用开发全流程。在统一的UI下,以工作流式的图形化拖拽开发体验,满足从数据导入、脱敏清洗、分析挖掘、质量检测、可视化展现、定时调度到数据输出应用等,数据应用开发全流程场景需求。 +在统一的UI下,DataSphere Studio以工作流式的图形化拖拽开发体验,将满足从数据交换、脱敏清洗、分析挖掘、质量检测、可视化展现、定时调度到数据输出应用等,数据应用开发全流程场景需求。 -借助于Linkis计算中间件的连接、复用与简化能力,DSS天生便具备了金融级高并发、高可用、多租户隔离和资源管控等执行与调度能力。 +**DSS通过插拔式的集成框架设计,让用户可以根据需要,简单快速替换DSS已集成的各种功能组件,或新增功能组件。** + +借助于 [**Linkis**](https://github.com/WeBankFinTech/Linkis) 计算中间件的连接、复用与简化能力,DSS天生便具备了金融级高并发、高可用、多租户隔离和资源管控等执行与调度能力。 ## 界面预览 @@ -37,10 +39,14 @@ DSS主要特点:        4、工作流调度工具——[Azkaban](https://azkaban.github.io/) +        **DSS插拔式的框架设计模式,允许用户快速替换DSS已集成的各个Web系统**。如:将Scriptis替换成Zeppelin,将Azkaban替换成DolphinScheduler。 + ![DSS一站式](images/zh_CN/readme/onestop.gif) ### 二、基于Linkis计算中间件,打造独有的AppJoint设计理念 +        AppJoint,是DSS可以简单快速集成各种上层Web系统的核心概念。 +        AppJoint——应用关节,定义了一套统一的前后台接入规范,可让外部数据应用系统快速简单地接入,成为DSS数据应用开发中的一环。        DSS通过串联多个AppJoint,编排成一条支持实时执行和定时调度的工作流,用户只需简单拖拽即可完成数据应用的全流程开发。 @@ -53,6 +59,10 @@ DSS主要特点: ### 四、已集成的数据应用组件 +        DSS通过实现多个AppJoint,已集成了丰富多样的各种上层数据应用系统,基本可满足用户的数据开发需求。 + +        **用户如果有需要,也可以轻松集成新的数据应用系统,以替换或丰富DSS的数据应用开发流程。** +        1、DSS的调度能力——Azkaban AppJoint            用户的很多数据应用,通常希望具备周期性的调度能力。 @@ -113,6 +123,10 @@ DSS主要特点:            空节点、子工作流节点。 +        8、**节点扩展** + +            **根据需要,用户可以简单快速替换DSS已集成的各种功能组件,或新增功能组件。** + ## 与类似系统对比 @@ -140,15 +154,35 @@ DSS主要特点: ## 文档列表 +#### 1. 安装编译文档 + +[快速安装使用文档](docs/zh_CN/ch2/DSS快速安装使用文档.md) + +[**DSS安装常见问题列表**](docs/zh_CN/ch1/DSS安装常见问题列表.md) + [DSS编译文档](docs/zh_CN/ch1/DSS编译文档.md) +#### 2. 使用文档 + [快速使用文档](docs/zh_CN/ch3/DataSphere_Studio_QuickStart.md) [用户手册](docs/zh_CN/ch3/DSS_User_Manual.md) -[外部系统快速接入DSS](docs/zh_CN/ch4/第三方系统接入DSS指南.md) +#### 3. AppJoint插件安装文档 + +**以下为手动安装相关插件的指南,DSS一键安装【标准版】已自动安装了以下插件,可忽略。** + +[DSS的Azkaban AppJoint插件安装指南](docs/zh_CN/ch4/如何接入调度系统Azkaban.md) + +[DSS的Qualitis AppJoint插件安装指南](https://github.com/WeBankFinTech/Qualitis/blob/master/docs/zh_CN/ch1/%E6%8E%A5%E5%85%A5%E5%B7%A5%E4%BD%9C%E6%B5%81%E6%8C%87%E5%8D%97.md) + +#### 4. 第三方系统如何接入文档 + +[DSS如何快速集成第三方系统](docs/zh_CN/ch4/第三方系统接入DSS指南.md) + +#### 5. 架构文档 -[如何接入调度系统Azkaban](docs/zh_CN/ch4/如何接入调度系统Azkaban.md) +[DSS工程发布到调度系统的架构设计](docs/zh_CN/ch4/DSS工程发布调度系统架构设计.md) 更多文档,敬请期待! -- Gitee From cd936c58a5ce671b3b75d5da2e6e254ef0fab5f0 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Fri, 20 Dec 2019 16:49:53 +0800 Subject: [PATCH 036/238] Quick access to azkaban system documentation update --- ...272\246\347\263\273\347\273\237Azkaban.md" | 85 +++++++------------ 1 file changed, 32 insertions(+), 53 deletions(-) diff --git "a/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" "b/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" index 96df77861..be30017a3 100644 --- "a/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" +++ "b/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" @@ -1,59 +1,38 @@ -## 如何接入调度系统Azkaban - Azkaban目前是作为一个SchedulerAppJoint在DSS-SERVER中使用,通过AzkabanSchedulerAppJoint实现了Azkaban的工程服务和安全认证服务, +## DSS如何手动安装接入调度系统Azkaban +           Azkaban目前是作为一个SchedulerAppJoint在DSS-SERVER中使用,通过AzkabanSchedulerAppJoint实现了Azkaban的工程服务和安全认证服务, 主要提供了工程的创建、更新、发布、删除,以及安全认证服务相关的代理登录,Cookie保存等。 - **前提条件:用户已经安装部署好社区版本的Azkaban-3.69.X环境** - - (1) 安装DSS前配置Azkaban的环境信息 - - 在安装DSS之前,在工程的conf目录下配置Azkaban的IP地址和端口信息: - -``` - #azkaban.address - AZKABAN_ADRESS_IP=127.0.0.1 - AZKABAN_ADRESS_PORT=99887 -``` - - 用户使用DSS一键安装,会自动配置以下两个参数内容: - -``` - wds.dss.appjoint.scheduler.azkaban.address= //Azkaban 的http地址 - wds.dss.appjoint.scheduler.project.store.dir= //Azkaban发布包临时存储目录 -``` - (2) 安装DSS后配置Azkaban用户信息 - - 在DSS-SERVER服务的conf目录下放置token.properties属性文件,配置用户名和密码信息,用于登录Azkaban.示例: - user01=1234 - 说明:由于每个公司都有各自的登录认证系统,这里只提供简单实现,用户可以实现SchedulerSecurityService定义自己的登录认证方法。 - 关联后DSS和Azkaban的用户必须是同一个。 - - (3) 在DSS数据库中配置Azkaban的appjoint信息(一键安装时默认已执行不需要重复执行,单独安装需要) + **前提条件:用户已经安装部署好社区版Azkaban-3.X以上版本。**[如何安装Azkaban](https://github.com/azkaban/azkaban) +#### **步骤:** +1、Azkaban APPJoint安装及配置 + 进入DSS安装包解压目录,复制share/appjoints/schedulis/dss-azkaban-appjoint.zip到DSS安装目录的dss-appjoints/schedulis文件夹下,解压即可。 + +2、修改dss-server配置目录中linkis.properties配置,增加如下参数: +``` +wds.dss.appjoint.scheduler.azkaban.address=http://IP地址:端口 #Azkaban的http地址 +wds.dss.appjoint.scheduler.project.store.dir=file:///appcom/tmp/wds/scheduler #Azkaban发布包临时存储目录 +``` + +3、数据库中dss_application表修改 + 修改DSS数据库dss_application表中schedulis记录行,修改url的连接IP地址和端口,保持与Azkaban Server实际地址一致。 + 示例SQL: + +``` +INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'schedulis', NULL, '0', '1', NULL, '0', NULL, NULL, '1', NULL, NULL); + +UPDATE `dss_application` SET url = 'http://IP地址:端口', project_url = 'http://IP地址:端口/manager?project=${projectName}',homepage_url = 'http://IP地址:端口/homepage' WHERE `name` in + ('schedulis'); +``` + +4、Azkaban JobType插件安装 +您还需为Azkaban安装一个JobType插件: linkis-jobtype,请点击[Linkis jobType安装文档](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/Azkaban_LinkisJobType_Deployment_Manual.md) + +5、用户token配置 + +##### 请在DSS-SERVER服务conf目录的token.properties文件中,配置用户名和密码信息,关联DSS和Azkaban用户,因为用户通过DSS创建工程后,要发布到azkaban,用户必须保持一致。示例: ``` - INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`) VALUES (NULL, 'azkaban', NULL, '0', '1', NULL, '0', NULL, NULL); + 用户名=密码 ``` - 检查dss-appjoints目录下是否已经安装了schedulis的appjoint。 - - (4) 在Azkaban上安装Linkis任务执行插件 - 由于现在DSS的任务基本都是提交给Linkis来执行的,所以需要在Azkaban上安装一个插件,用于DSS发布到Azkaban后的调度执行。 - 1、获取插件包 - -``` - /wedatasphere-dss-x.x.x-dist/share/plugins/azkaban/linkis-jobtype/linkis-jobtype-x.x.x-linkis-jobtype.zip -``` - 2、安装插件 - - 把安装包解压到指定的目录下: -``` - /AzkabanInstall/wtss-exec/plugins/jobtypes/linkis -``` - - 3、配置插件 - - private.properties(azkaban的jobtype配置)和 plugin.properties(额外的配置) - 请根据实际环境设置两个配置文件的内容 - - 4、刷新生效 - - curl http://IP:PORT/executor?action=reloadJobTypePlugins \ No newline at end of file +说明:由于每个公司都有各自的登录认证系统,这里只提供简单实现,用户可以实现SchedulerSecurityService定义自己的登录认证方法。azkaban用户管理可参考[Azkaban-3.x 用户管理](https://cloud.tencent.com/developer/article/1492734)及[官网](https://azkaban.readthedocs.io/en/latest/userManager.html) \ No newline at end of file -- Gitee From 9f814f9fc6eca76c5b3b72dc576d4b5b40fcf220 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Fri, 20 Dec 2019 16:54:08 +0800 Subject: [PATCH 037/238] Access to azkaban system documentation update Quick access to azkaban system documentation update --- ...45\272\246\347\263\273\347\273\237Azkaban.md" | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git "a/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" "b/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" index be30017a3..a6e307784 100644 --- "a/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" +++ "b/docs/zh_CN/ch4/\345\246\202\344\275\225\346\216\245\345\205\245\350\260\203\345\272\246\347\263\273\347\273\237Azkaban.md" @@ -4,16 +4,19 @@ **前提条件:用户已经安装部署好社区版Azkaban-3.X以上版本。**[如何安装Azkaban](https://github.com/azkaban/azkaban) #### **步骤:** -1、Azkaban APPJoint安装及配置 +**1、Azkaban APPJoint安装及配置** + 进入DSS安装包解压目录,复制share/appjoints/schedulis/dss-azkaban-appjoint.zip到DSS安装目录的dss-appjoints/schedulis文件夹下,解压即可。 -2、修改dss-server配置目录中linkis.properties配置,增加如下参数: +**2、修改dss-server配置目录中linkis.properties配置,增加如下参数:** + ``` wds.dss.appjoint.scheduler.azkaban.address=http://IP地址:端口 #Azkaban的http地址 wds.dss.appjoint.scheduler.project.store.dir=file:///appcom/tmp/wds/scheduler #Azkaban发布包临时存储目录 ``` -3、数据库中dss_application表修改 +**3、数据库中dss_application表修改** + 修改DSS数据库dss_application表中schedulis记录行,修改url的连接IP地址和端口,保持与Azkaban Server实际地址一致。 示例SQL: @@ -24,10 +27,11 @@ UPDATE `dss_application` SET url = 'http://IP地址:端口', project_url = 'http ('schedulis'); ``` -4、Azkaban JobType插件安装 +**4、Azkaban JobType插件安装** + 您还需为Azkaban安装一个JobType插件: linkis-jobtype,请点击[Linkis jobType安装文档](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/Azkaban_LinkisJobType_Deployment_Manual.md) -5、用户token配置 +**5、用户token配置** ##### 请在DSS-SERVER服务conf目录的token.properties文件中,配置用户名和密码信息,关联DSS和Azkaban用户,因为用户通过DSS创建工程后,要发布到azkaban,用户必须保持一致。示例: @@ -35,4 +39,4 @@ UPDATE `dss_application` SET url = 'http://IP地址:端口', project_url = 'http 用户名=密码 ``` -说明:由于每个公司都有各自的登录认证系统,这里只提供简单实现,用户可以实现SchedulerSecurityService定义自己的登录认证方法。azkaban用户管理可参考[Azkaban-3.x 用户管理](https://cloud.tencent.com/developer/article/1492734)及[官网](https://azkaban.readthedocs.io/en/latest/userManager.html) \ No newline at end of file +说明:由于每个公司都有各自的登录认证系统,这里只提供简单实现,用户可以实现SchedulerSecurityService定义自己的登录认证方法。azkaban用户管理可参考[Azkaban-3.x 用户管理](https://cloud.tencent.com/developer/article/1492734)及[官网](https://azkaban.readthedocs.io/en/latest/userManager.html) -- Gitee From 5d03317068904b5f7a95efab5154e672ade86e64 Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Tue, 24 Dec 2019 10:07:31 +0800 Subject: [PATCH 038/238] web compilation --- docs/en_US/ch4/Web Compilation.md | 102 ++++++++++++++++++ ...26\350\257\221\346\226\207\346\241\243.md" | 86 +++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 docs/en_US/ch4/Web Compilation.md create mode 100644 "docs/zh_CN/ch4/\345\211\215\347\253\257\347\274\226\350\257\221\346\226\207\346\241\243.md" diff --git a/docs/en_US/ch4/Web Compilation.md b/docs/en_US/ch4/Web Compilation.md new file mode 100644 index 000000000..1f22f0a29 --- /dev/null +++ b/docs/en_US/ch4/Web Compilation.md @@ -0,0 +1,102 @@ +# Compilation + +## Getting Started + +### Prerequisites + +Install Node.js on your computer. Download Link: [http://nodejs.cn/download/](http://nodejs.cn/download/). Recommend using the latest stable version. + +**Only do this step at the first time.** + +### Installation + +Run the following commands in terminal: + +``` +git clone https://github.com/WeBankFinTech/Scriptis.git +cd DataSphereStudio/web +npm install +``` + + Commands explanation: + +1. Pull remote repository to local: `git clone https://github.com/WeBankFinTech/Scriptis.git` + +2. Change to the root directory of the project: `cd DataSphereStudio/web` + +3. Install all dependencies required for the project: `npm install` + +**Only do this step at the first time.** + +### Configuration + +You need to make some configurations in your code, such as port address of backend server and socket address of backend server in .env.development file in root directory. + +``` +// Port address of backend server +VUE_APP_MN_CONFIG_PREFIX=http://yourIp:yourPort/yourPath +// Socket address +VUE_APP_MN_CONFIG_SOCKET=/yourSocketPath +``` + +You can refer to the official documentation of vue-cli for detailed explanation. [Modes and environment variables](https://cli.vuejs.org/guide/mode-and-env.html#modes) + +### Building project + +You can run the following command in terminal to build the project: + +``` +npm run build +``` + +A folder named "dist" would appear in your project's root directory if the command has run successfully and you can directly put "dist" to your static server. + +### How to run + +You would need to run the following command in terminal if you want to run project on your local browser and see corresponding effects after making changes to the code. + +``` +npm run serve +``` + +Access the application in browser (Chrome recommended) via link: [http://localhost:8080/](http://localhost:8080/) . + +Changes you make to the code would dynamically reflect on the +effects shown on browser when using the method described above to run project. + +**Notes: Since frontend and backend are developed separately, when running on local browser you need to allow cross domain access in order to access the port of backend server.** + +e.g. Chrome browser: + +Configuration in Windows: + +1. Close all browser windows. + +2. Create a shortcut of chrome, right-click to choose "properties" , then go to "Shortcut" tab find "Target" and add`--args --disable-web-security --user-data-dir=C:\MyChromeDevUserData` to it . +3. Use shortcut to open the browser. + +Configuration in MacOS: + +Run the following command. (You need to replace "yourname" in the path. If it's not working, check the path of MyChromeDevUserData on your machine and copy its path to the place right after "--user-data-dir=") + +``` +open -n /Applications/Google\ Chrome.app/ --args --disable-web-security --user-data-dir=/Users/yourname/MyChromeDevUserData/ +``` + +### FAQ + +#### Failed installation when running npm install + +Try to use Taobao npm mirror: + +``` +npm install -g cnpm --registry=https://registry.npm.taobao.org +``` + +Next, run the following command instead of npm install: + +``` +cnpm install +``` + +Note that you can still use `npm run serve` and `npm run build` to run and build project. \ No newline at end of file diff --git "a/docs/zh_CN/ch4/\345\211\215\347\253\257\347\274\226\350\257\221\346\226\207\346\241\243.md" "b/docs/zh_CN/ch4/\345\211\215\347\253\257\347\274\226\350\257\221\346\226\207\346\241\243.md" new file mode 100644 index 000000000..ee447703a --- /dev/null +++ "b/docs/zh_CN/ch4/\345\211\215\347\253\257\347\274\226\350\257\221\346\226\207\346\241\243.md" @@ -0,0 +1,86 @@ +# 编译文档中文版 + +## 启动流程 + +### 一、安装Node.js +将Node.js下载到电脑本地,安装即可。下载地址:[http://nodejs.cn/download/](http://nodejs.cn/download/) (建议使用最新的稳定版本) +**该步骤仅第一次使用时需要执行。** + +### 二、安装项目 +在终端命令行中执行以下指令: + +``` +git clone ${ipAddress} +cd DataSphereStudio/web +npm install +``` + +指令简介: +1. 将项目包从远程仓库拉取到电脑本地:git clone ${ipAddress} +2. 进入项目包根目录:cd DataSphereStudio/web +3. 安装项目所需依赖:npm install + +**该步骤仅第一次使用时需要执行。** + +### 三、配置 +您需要在代码中进行一些配置,如后端接口地址,后端socket地址等,如根目录下的.env.development文件: + +``` +// 后端接口地址 +VUE_APP_MN_CONFIG_PREFIX=http://yourIp:yourPort/yourPath +// 后端socket地址 +VUE_APP_MN_CONFIG_SOCKET=/yourSocketPath +``` + +配置的具体解释可参考vue-cli官方文档:[环境变量和模式](https://cli.vuejs.org/zh/guide/mode-and-env.html#%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E5%92%8C%E6%A8%A1%E5%BC%8F) + +### 打包项目 +您可以通过在终端命令行执行以下指令对项目进行打包,生成压缩后的代码: + +``` +npm run build +``` + +该指令成功执行后,项目根目录下会出现一个名叫 “dist” 的文件夹,该文件夹即为打包好的代码。您可以直接将该文件夹放进您的静态服务器中。 + +### 运行项目 +如果您想在本地浏览器上运行该项目并且改动代码查看效果,需要在终端命令行中执行以下指令: + +``` +npm run serve +``` + +在浏览器中(建议Chrome浏览器)通过链接访问应用:[http://localhost:8080/](http://localhost:8080/) . +当您使用该方式运行项目时,您对代码的改动产生的效果,会动态体现在浏览器上。 + +**注意:因为项目采用前后端分离开发,所以在本地浏览器上运行时,需要对浏览器进行设置跨域才能访问后端接口:** + +比如chrome浏览器: +windows系统下的配置方式: +1. 关闭所有的chrome浏览器。 +2. 新建一个chrome快捷方式,右键“属性”,“快捷方式”选项卡里选择“目标”,添加  --args --disable-web-security --user-data-dir=C:\MyChromeDevUserData +3. 通过快捷方式打开chrome浏览器 +mac系统下的配置方式: +在终端命令行执行以下命令(需要替换路径中的yourname,若还不生效请检查您机器上MyChromeDevUserData文件夹的位置并将路径复制到下面指令的“--user-data-dir=”后面) + +``` +open -n /Applications/Google\ Chrome.app/ --args --disable-web-security --user-data-dir=/Users/yourname/MyChromeDevUserData/ +``` + + +### 常见问题 + +#### npm install无法成功 +如果遇到该情况,可以使用国内的淘宝npm镜像: + +``` +npm install -g cnpm --registry=https://registry.npm.taobao.org +``` + +接着,通过执行以下指令代替npm install指令 + +``` +cnpm install +``` + +注意,项目启动和打包时,仍然可以使用npm run build和npm run serve指令 \ No newline at end of file -- Gitee From f19d68a7098acbecf45370d1697fabf26413510f Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Tue, 24 Dec 2019 15:03:32 +0800 Subject: [PATCH 039/238] Fix the bug for delete node of visualis that requestBody is null --- .../webank/wedatasphere/dss/server/function/FunctionPool.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dss-server/src/main/java/com/webank/wedatasphere/dss/server/function/FunctionPool.java b/dss-server/src/main/java/com/webank/wedatasphere/dss/server/function/FunctionPool.java index 3ace828c7..7efe477b2 100644 --- a/dss-server/src/main/java/com/webank/wedatasphere/dss/server/function/FunctionPool.java +++ b/dss-server/src/main/java/com/webank/wedatasphere/dss/server/function/FunctionPool.java @@ -26,6 +26,7 @@ import java.util.Map; public class FunctionPool { public static NodeServiceFunction deleteNode = (NodeService nodeService, Session session, AppJointNode node, Map requestBody)->{ + node.setJobContent(requestBody); nodeService.deleteNode(session,node); return null; }; -- Gitee From 13add27dccfb485403fa304af018cf85d7480b71 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Tue, 24 Dec 2019 22:44:19 +0800 Subject: [PATCH 040/238] Add Lite install script and documentation close #57 --- bin/checkEnv.sh | 5 +- bin/checkMicro.sh | 50 ++++++ bin/install.sh | 99 +++++------ bin/start-all.sh | 52 ++++-- bin/stop-all.sh | 7 +- conf/config.sh | 4 +- db/dss_dml.sql | 11 -- db/visualis.sql | 34 ++++ ...77\347\224\250\346\226\207\346\241\243.md" | 165 +++++++++++++++--- 9 files changed, 315 insertions(+), 112 deletions(-) create mode 100644 bin/checkMicro.sh create mode 100644 db/visualis.sql diff --git a/bin/checkEnv.sh b/bin/checkEnv.sh index dffcb7718..bdf48659a 100644 --- a/bin/checkEnv.sh +++ b/bin/checkEnv.sh @@ -39,8 +39,7 @@ need_cmd mysql need_cmd unzip need_cmd expect need_cmd telnet -need_cmd sed need_cmd tar -need_cmd source -need_cmd hostname +need_cmd sed +need_cmd dos2unix echo "<-----end to check linux cmd:yum java mysql unzip expect telnet sed tar------>" diff --git a/bin/checkMicro.sh b/bin/checkMicro.sh new file mode 100644 index 000000000..3f8ff95fa --- /dev/null +++ b/bin/checkMicro.sh @@ -0,0 +1,50 @@ +# +# Copyright 2019 WeBank +# +# 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. +# +#!/bin/sh +source ~/.bash_profile + +shellDir=`dirname $0` +workDir=`cd ${shellDir}/..;pwd` + +##load config +source ${workDir}/conf/config.sh +source ${workDir}/conf/db.sh + +MICRO_SERVICE_NAME=$1 +MICRO_SERVICE_IP=$2 +MICRO_SERVICE_PORT=$3 +echo "<--------------------------------------------------------------------------->" +echo "Start to Check if your microservice:$MICRO_SERVICE_NAME is normal via telnet" +echo "" +if [ ! -d $DSS_INSTALL_HOME/$MICRO_SERVICE_NAME ];then + echo "$MICRO_SERVICE_NAME is not installed,the check steps will be skipped" + exit 0 +fi + +result=`echo -e "\n" | telnet $MICRO_SERVICE_IP $MICRO_SERVICE_PORT 2>/dev/null | grep Connected | wc -l` +if [ $result -eq 1 ]; then + echo "$MICRO_SERVICE_NAME is ok." +else + echo "<--------------------------------------------------------------------------->" + echo "ERROR your $MICRO_SERVICE_NAME microservice is not start successful !!! ERROR logs as follows :" + echo "PLEAESE CHECK DETAIL LOG,LOCATION:$DSS_INSTALL_HOME/$MICRO_SERVICE_NAME/logs/linkis.out" + echo '<------------------------------------------------------------->' + tail -n 50 $DSS_INSTALL_HOME/$MICRO_SERVICE_NAME/logs/*.out + echo '<-------------------------------------------------------------->' + echo "PLEAESE CHECK DETAIL LOG,LOCATION:$DSS_INSTALL_HOME/$MICRO_SERVICE_NAME/logs/linkis.out" + exit 1 +fi + diff --git a/bin/install.sh b/bin/install.sh index 70adc5a34..5961dfdbd 100644 --- a/bin/install.sh +++ b/bin/install.sh @@ -37,7 +37,6 @@ elif [[ "$OSTYPE" == "win32" ]]; then echo "dss not support Windows operating system" exit 1 elif [[ "$OSTYPE" == "freebsd"* ]]; then - txt="" else echo "Operating system unknown, please tell us(submit issue) for better service" @@ -46,14 +45,13 @@ fi function isSuccess(){ if [ $? -ne 0 ]; then - echo "Failed to " + $1 + echo "ERROR to " + $1 exit 1 else - echo "Succeed to" + $1 + echo "SUCESS to" + $1 fi } - #check env sh ${workDir}/bin/checkEnv.sh isSuccess "check env" @@ -74,45 +72,19 @@ else fi } -function checkPythonAndJava(){ - python --version - isSuccess "execute python --version" - java -version - isSuccess "execute java --version" -} - -function checkHadoopAndHive(){ - hdfs version - isSuccess "execute hdfs version" - hive --help - #isSuccess "execute hive -h" -} - -function checkSpark(){ - spark-submit --version - isSuccess "execute spark-submit --version" -} - -##install env:expect, -sudo yum install -y expect -isSuccess "install expect" - -##install env:telnet, -sudo yum install -y telnet -isSuccess "install telnet" - ##load config echo "step1:load config" source ${workDir}/conf/config.sh source ${workDir}/conf/db.sh isSuccess "load config" -local_host="`hostname --fqdn`" +local_host="`hostname -i`" ##env check echo "Please enter the mode selection such as: 1" -echo " 1: Simple" -echo " 2: Standard" +echo " 1: lite" +echo " 2: sample" +echo " 3: Standard" echo "" INSTALL_MODE=1 @@ -120,7 +92,7 @@ INSTALL_MODE=1 read -p "Please input the choice:" idx if [[ '1' = "$idx" ]];then INSTALL_MODE=1 - echo "You chose Simple installation mode" + echo "You chose lite installation mode" #check for Java checkJava #check for mysql @@ -128,9 +100,18 @@ if [[ '1' = "$idx" ]];then EXTERNAL_SERVER_IP=$MYSQL_HOST EXTERNAL_SERVER_PORT=$MYSQL_PORT checkExternalServer - elif [[ '2' = "$idx" ]];then INSTALL_MODE=2 + echo "You chose sample installation mode" + #check for Java + checkJava + #check for mysql + SERVER_NAME=MYSQL + EXTERNAL_SERVER_IP=$MYSQL_HOST + EXTERNAL_SERVER_PORT=$MYSQL_PORT + +elif [[ '3' = "$idx" ]];then + INSTALL_MODE=3 echo "You chose Standard installation mode" #check for Java checkJava @@ -155,8 +136,8 @@ else exit 1 fi -##env check -echo "Do you want to clear Dss table information in the database?" +##init db +echo "Do you want to clear DSS table information in the database?" echo " 1: Do not execute table-building statements" echo " 2: Dangerous! Clear all data and rebuild the tables." echo "" @@ -189,18 +170,25 @@ if [[ '2' = "$MYSQL_INSTALL_MODE" ]];then #echo $GATEWAY_INSTALL_IP_2 sed -i "s/GATEWAY_INSTALL_IP_2/$GATEWAY_INSTALL_IP_2/g" ${workDir}/db/dss_dml.sql sed -i "s/GATEWAY_PORT/$GATEWAY_PORT/g" ${workDir}/db/dss_dml.sql - if [ $VISUALIS_NGINX_IP == "127.0.0.1" ]||[ $VISUALIS_NGINX_IP == "0.0.0.0" ];then + mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/dss_dml.sql" + isSuccess "source dss_dml.sql" + + if [ '2' = "$INSTALL_MODE" ]||[ '3' = "$INSTALL_MODE" ];then + echo "visualis support " + if [ $VISUALIS_NGINX_IP == "127.0.0.1" ]||[ $VISUALIS_NGINX_IP == "0.0.0.0" ];then echo "VISUALIS_NGINX_IP is equals $VISUALIS_NGINX_IP ,we will change it to ip address" VISUALIS_NGINX_IP_2=$LOCAL_IP - else + else VISUALIS_NGINX_IP_2=$VISUALIS_NGINX_IP + fi + #echo $VISUALIS_NGINX_IP_2 + sed -i "s/VISUALIS_NGINX_IP_2/$VISUALIS_NGINX_IP_2/g" ${workDir}/db/visualis.sql + sed -i "s/VISUALIS_NGINX_PORT/$VISUALIS_NGINX_PORT/g" ${workDir}/db/visualis.sql + mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/visualis.sql" + isSuccess "source visualis.sql" fi - #echo $VISUALIS_NGINX_IP_2 - sed -i "s/VISUALIS_NGINX_IP_2/$VISUALIS_NGINX_IP_2/g" ${workDir}/db/dss_dml.sql - sed -i "s/VISUALIS_NGINX_PORT/$VISUALIS_NGINX_PORT/g" ${workDir}/db/dss_dml.sql - mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/dss_dml.sql" - isSuccess "source dss_dml.sql" - if [[ '2' = "$INSTALL_MODE" ]];then + + if [[ '3' = "$INSTALL_MODE" ]];then echo "start to update azkaban and qualitis table info " #azkaban if [ $AZKABAN_ADRESS_IP == "127.0.0.1" ];then @@ -229,7 +217,7 @@ if [[ '2' = "$MYSQL_INSTALL_MODE" ]];then fi fi -##env check +## davinci db init echo "Do you want to clear davinci table information in the database ? If you have not installed davinci environment,you must input '2',if you have davinci installed,choice 1." echo " 1: Do not execute table-building statements" echo "WARN:" @@ -252,7 +240,6 @@ else exit 1 fi - ###linkis Eurkea info SERVER_IP=$EUREKA_INSTALL_IP SERVER_PORT=$EUREKA_PORT @@ -362,6 +349,8 @@ ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.dss.appjoint.scheduler.project.sto isSuccess "subsitution linkis.properties of $SERVERNAME" echo "<----------------$SERVERNAME:end------------------->" echo "" + +if [ '2' = "$INSTALL_MODE" ]||[ '3' = "$INSTALL_MODE" ];then ##Flow execution Install PACKAGE_DIR=dss/dss-flow-execution-entrance SERVERNAME=dss-flow-execution-entrance @@ -437,7 +426,7 @@ APPJOINTNAME_CONF_PATH_PATENT=$SERVER_HOME/$APPJOINTPARENT/$APPJOINTNAME/appjoin ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#job.datachecker.jdo.option.url.*#job.datachecker.jdo.option.url=$HIVE_META_URL#g\" $APPJOINTNAME_CONF_PATH_PATENT" ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#job.datachecker.jdo.option.username.*#job.datachecker.jdo.option.username=$HIVE_META_USER#g\" $APPJOINTNAME_CONF_PATH_PATENT" ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#job.datachecker.jdo.option.password.*#job.datachecker.jdo.option.password=$HIVE_META_PASSWORD#g\" $APPJOINTNAME_CONF_PATH_PATENT" -isSuccess "subsitution conf of $SERVERNAME" +isSuccess "subsitution conf of datachecker" echo "<----------------datachecker appjoint install end------------------->" echo "" echo "<----------------eventchecker appjoint install start------------------->" @@ -450,7 +439,7 @@ APPJOINTNAME_CONF_PATH_PATENT=$SERVER_HOME/$APPJOINTPARENT/$APPJOINTNAME/appjoin ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#msg.eventchecker.jdo.option.url.*#msg.eventchecker.jdo.option.url=jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DB}?characterEncoding=UTF-8#g\" $APPJOINTNAME_CONF_PATH_PATENT" ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#msg.eventchecker.jdo.option.username.*#msg.eventchecker.jdo.option.username=$MYSQL_USER#g\" $APPJOINTNAME_CONF_PATH_PATENT" ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#msg.eventchecker.jdo.option.password.*#msg.eventchecker.jdo.option.password=$MYSQL_PASSWORD#g\" $APPJOINTNAME_CONF_PATH_PATENT" -isSuccess "subsitution conf of $SERVERNAME" +isSuccess "subsitution conf of eventchecker" echo "<----------------$APPJOINTNAME:end------------------->" echo "" echo "<----------------visualis appjoint install start------------------->" @@ -459,8 +448,10 @@ APPJOINTNAME=visualis #visualis appjoint install installAppjoints echo "<----------------$APPJOINTNAME:end------------------->" -##sample version does not install qualitis APPJoint and scheduis APPJoint -if [[ '2' = "$INSTALL_MODE" ]];then +fi + +##lite and sample version does not install qualitis APPJoint and scheduis APPJoint +if [[ '3' = "$INSTALL_MODE" ]];then echo "" echo "<----------------qualitis appjoint install start------------------->" APPJOINTPARENT=dss-appjoints @@ -469,7 +460,7 @@ APPJOINTNAME=qualitis installAppjoints APPJOINTNAME_CONF_PATH_PATENT=$SERVER_HOME/$APPJOINTPARENT/$APPJOINTNAME/appjoint.properties ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#baseUrl=http://127.0.0.1:8090#baseUrl=http://$QUALITIS_ADRESS_IP:$QUALITIS_ADRESS_PORT#g\" $APPJOINTNAME_CONF_PATH_PATENT" -isSuccess "subsitution conf of $SERVERNAME" +isSuccess "subsitution conf of qualitis" echo "<----------------$APPJOINTNAME:end------------------->" echo "" echo "<----------------schedulis appjoint install start------------------->" @@ -479,4 +470,4 @@ APPJOINTNAME=schedulis installAppjoints isSuccess "subsitution conf of schedulis" echo "<----------------$APPJOINTNAME:end------------------->" -fi \ No newline at end of file +fi diff --git a/bin/start-all.sh b/bin/start-all.sh index df229abc8..8f5b04e2c 100644 --- a/bin/start-all.sh +++ b/bin/start-all.sh @@ -31,6 +31,31 @@ workDir=`cd "$workDir"; pwd` CONF_DIR="${workDir}"/../conf CONF_FILE=${CONF_DIR}/config.sh +function isLocal(){ + if [ "$1" == "127.0.0.1" ];then + return 0 + elif [ $1 == "localhost" ]; then + return 0 + elif [ $1 == $local_host ]; then + return 0 + elif [ $1 == $ipaddr ]; then + return 0 + fi + return 1 +} + +function executeCMD(){ + isLocal $1 + flag=$? + echo "Is local "$flag + if [ $flag == "0" ];then + eval $2 + else + ssh -p $SSH_PORT $1 $2 + fi + +} + function isSuccess(){ if [ $? -ne 0 ]; then echo "ERROR: " + $1 @@ -60,7 +85,14 @@ function startApp(){ echo "<-------------------------------->" echo "Begin to start $SERVER_NAME" SERVER_BIN=${DSS_INSTALL_HOME}/${SERVER_NAME}/bin -SERVER_START_CMD="source ~/.bash_profile;cd ${SERVER_BIN}; dos2unix ./* > /dev/null 2>&1; dos2unix ../conf/* > /dev/null 2>&1;sh start-${SERVER_NAME}.sh > /dev/null 2>&1 &" +SERVER_START_CMD="source /etc/profile;source ~/.bash_profile;cd ${SERVER_BIN}; dos2unix ./* > /dev/null 2>&1; dos2unix ../conf/* > /dev/null 2>&1;sh start-${SERVER_NAME}.sh > /dev/null 2>&1 &" + +if [ ! -d $SERVER_BIN ];then + echo "<-------------------------------->" + echo "$SERVER_NAME is not installed,the start steps will be skipped" + echo "<-------------------------------->" + return +fi if [ -n "${SERVER_IP}" ];then ssh ${SERVER_IP} "${SERVER_START_CMD}" @@ -76,16 +108,6 @@ sleep 15 #for Eureka register SERVER_NAME=dss-server SERVER_IP=$DSS_SERVER_INSTALL_IP startApp -#MICRO_SERVICE_NAME=dss-server -#MICRO_SERVICE_IP=$DSS_SERVER_INSTALL_IP -#MICRO_SERVICE_PORT=$DSS_SERVER_PORT -#sh $workDir/check.sh $MICRO_SERVICE_NAME $MICRO_SERVICE_IP $MICRO_SERVICE_PORT -#state=`echo -e "\n" | telnet $MICRO_SERVICE_IP $MICRO_SERVICE_PORT 2>/dev/null | grep Connected | wc -l` -#if [ $state -eq 0 ]; then -# echo "" -# echo "ERROR " $MICRO_SERVICE_NAME "is a critical service and must be guaranteed to be started !!!" -# exit 1 -#fi #dss-flow-execution-entrance SERVER_NAME=dss-flow-execution-entrance @@ -101,15 +123,14 @@ SERVER_NAME=visualis-server SERVER_IP=$VISUALIS_SERVER_INSTALL_IP startApp - +echo "" echo "Start to check all dss microservice" - +echo "" #check dss-server MICRO_SERVICE_NAME=dss-server MICRO_SERVICE_IP=$DSS_SERVER_INSTALL_IP MICRO_SERVICE_PORT=$DSS_SERVER_PORT sh $workDir/checkMicro.sh $MICRO_SERVICE_NAME $MICRO_SERVICE_IP $MICRO_SERVICE_PORT -state=`echo -e "\n" | telnet $MICRO_SERVICE_IP $MICRO_SERVICE_PORT 2>/dev/null | grep Connected | wc -l` isSuccess "$MICRO_SERVICE_NAME start" @@ -118,7 +139,6 @@ MICRO_SERVICE_NAME=dss-flow-execution-entrance MICRO_SERVICE_IP=$FLOW_EXECUTION_INSTALL_IP MICRO_SERVICE_PORT=$FLOW_EXECUTION_PORT sh $workDir/checkMicro.sh $MICRO_SERVICE_NAME $MICRO_SERVICE_IP $MICRO_SERVICE_PORT -state=`echo -e "\n" | telnet $MICRO_SERVICE_IP $MICRO_SERVICE_PORT 2>/dev/null | grep Connected | wc -l` isSuccess "$MICRO_SERVICE_NAME start" #check linkis-appjoint-entrance @@ -126,7 +146,6 @@ MICRO_SERVICE_NAME=linkis-appjoint-entrance MICRO_SERVICE_IP=$APPJOINT_ENTRANCE_INSTALL_IP MICRO_SERVICE_PORT=$APPJOINT_ENTRANCE_PORT sh $workDir/checkMicro.sh $MICRO_SERVICE_NAME $MICRO_SERVICE_IP $MICRO_SERVICE_PORT -state=`echo -e "\n" | telnet $MICRO_SERVICE_IP $MICRO_SERVICE_PORT 2>/dev/null | grep Connected | wc -l` isSuccess "$MICRO_SERVICE_NAME start" @@ -136,6 +155,5 @@ MICRO_SERVICE_NAME=visualis-server MICRO_SERVICE_IP=$VISUALIS_SERVER_INSTALL_IP MICRO_SERVICE_PORT=$VISUALIS_SERVER_PORT sh $workDir/checkMicro.sh $MICRO_SERVICE_NAME $MICRO_SERVICE_IP $MICRO_SERVICE_PORT -state=`echo -e "\n" | telnet $MICRO_SERVICE_IP $MICRO_SERVICE_PORT 2>/dev/null | grep Connected | wc -l` isSuccess "$MICRO_SERVICE_NAME start" diff --git a/bin/stop-all.sh b/bin/stop-all.sh index f1a2c3681..82252c7b5 100644 --- a/bin/stop-all.sh +++ b/bin/stop-all.sh @@ -60,6 +60,11 @@ echo "<-------------------------------->" echo "Begin to stop $SERVER_NAME" SERVER_BIN=${DSS_INSTALL_HOME}/${SERVER_NAME}/bin SERVER_STOP_CMD="source ~/.bash_profile;cd ${SERVER_BIN}; dos2unix ./* > /dev/null 2>&1; dos2unix ../conf/* > /dev/null 2>&1; sh stop-${SERVER_NAME}.sh" +if [ ! -d ${DSS_INSTALL_HOME}/${SERVER_NAME} ];then + echo "$SERVER_NAME is not installed,the stop steps will be skipped" + return +fi + if [ -n "${SERVER_IP}" ];then ssh -p $SSH_PORT ${SERVER_IP} "${SERVER_STOP_CMD}" else @@ -87,4 +92,4 @@ stopAPP #visualis-server SERVER_NAME=visualis-server SERVER_IP=$VISUALIS_SERVER_INSTALL_IP -stopAPP \ No newline at end of file +stopAPP diff --git a/conf/config.sh b/conf/config.sh index 895c2c02c..0b5a501e3 100644 --- a/conf/config.sh +++ b/conf/config.sh @@ -58,7 +58,7 @@ WDS_SCHEDULER_PATH=file:///appcom/tmp/wds/scheduler VISUALIS_SERVER_INSTALL_IP=127.0.0.1 VISUALIS_SERVER_PORT=9007 ### visualis nginx acess ip,keep consistent with DSS front end -VISUALIS_NGINX_IP=0.0.0.0 +VISUALIS_NGINX_IP=127.0.0.1 VISUALIS_NGINX_PORT=8088 ### Eventchecker APPJOINT @@ -72,4 +72,4 @@ AZKABAN_ADRESS_PORT=8091 QUALITIS_ADRESS_IP=127.0.0.1 QUALITIS_ADRESS_PORT=8090 -DSS_VERSION=0.6.0 \ No newline at end of file +DSS_VERSION=0.7.0 \ No newline at end of file diff --git a/db/dss_dml.sql b/db/dss_dml.sql index 27146dedc..f9c2b2a24 100644 --- a/db/dss_dml.sql +++ b/db/dss_dml.sql @@ -1,10 +1,8 @@ INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'linkis', null, '0', '1', NULL, '0', '/home', NULL, '0', '/home', NULL); -INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'visualis', null, '0', '1', NULL, '0', NULL, NULL, '1', NULL, NULL); INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'workflow', null, '0', '1', NULL, '0', '/workflow', NULL, '0', '/project', NULL); INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'console', null, '0', '1', NULL, '0', '/console', NULL, '0', '/console', NULL); SELECT @linkis_appid:=id from dss_application WHERE `name` = 'linkis'; -SELECT @visualis_appid:=id from dss_application WHERE `name` = 'visualis'; SELECT @workflow_appid:=id from dss_application WHERE `name` = 'workflow'; INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.python.python', @linkis_appid, '1', '1', '0', '1', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.spark.py', @linkis_appid, '1', '1', '0', '1', NULL); @@ -13,8 +11,6 @@ INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `s INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.hive.hql', @linkis_appid, '1', '1', '0', '1', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.control.empty', @linkis_appid, '1', '1', '0', '0', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.appjoint.sendemail', @linkis_appid, '1', '1', '0', '0', NULL); -INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.appjoint.visualis.display', @visualis_appid, '1', '1', '1', '1', NULL); -INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.appjoint.visualis.dashboard', @visualis_appid, '1', '1', '1', '1', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.appjoint.eventchecker.eventsender', @linkis_appid, '1', '1', '0', '0', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.appjoint.eventchecker.eventreceiver', @linkis_appid, '1', '1', '0', '0', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.appjoint.datachecker', @linkis_appid, '1', '1', '0', '0', NULL); @@ -27,14 +23,7 @@ INSERT INTO `dss_project_taxonomy` (`id`, `name`, `description`, `creator_id`, ` INSERT INTO `dss_flow_taxonomy` (`id`, `name`, `description`, `creator_id`, `create_time`, `update_time`, `project_id`) VALUES (NULL, 'My workflow', NULL, NULL, NULL,NULL, '-1'); UPDATE `dss_application` SET url = 'http://GATEWAY_INSTALL_IP_2:GATEWAY_PORT' WHERE `name` in('linkis','workflow'); -UPDATE `dss_application` SET url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT' WHERE `name` in('visualis'); -UPDATE `dss_application` SET project_url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT/dss/visualis/#/project/${projectId}',homepage_url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT/dss/visualis/#/projects' WHERE `name` in('visualis'); -UPDATE `dss_workflow_node` SET jump_url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT/dss/visualis/#/project/${projectId}/display/${nodeId}' where node_type = 'linkis.appjoint.visualis.display'; -UPDATE `dss_workflow_node` SET jump_url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT/dss/visualis/#/project/${projectId}/portal/${nodeId}/portalName/${nodeName}' where node_type = 'linkis.appjoint.visualis.dashboard'; - -INSERT INTO `linkis_application` (`id`, `name`, `chinese_name`, `description`) VALUES (NULL, 'visualis', NULL, NULL); -select @application_id:=id from `linkis_application` where `name` = 'visualis'; INSERT INTO `linkis_config_key` (`id`, `key`, `description`, `name`, `application_id`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`) VALUES (NULL, 'spark.executor.instances', '取值范围:1-40,单位:个', '执行器实例最大并发数', @application_id, '2', 'NumInterval', '[1,40]', '0', '0', '2'); INSERT INTO `linkis_config_key` (`id`, `key`, `description`, `name`, `application_id`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`) VALUES (NULL, 'spark.executor.cores', '取值范围:1-8,单位:个', '执行器核心个数', @application_id, '2', 'NumInterval', '[1,2]', '1', '0', '1'); INSERT INTO `linkis_config_key` (`id`, `key`, `description`, `name`, `application_id`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`) VALUES (NULL, 'spark.executor.memory', '取值范围:3-15,单位:G', '执行器内存大小', @application_id, '3', 'NumInterval', '[3,15]', '0', '0', '3'); diff --git a/db/visualis.sql b/db/visualis.sql new file mode 100644 index 000000000..71070c7bd --- /dev/null +++ b/db/visualis.sql @@ -0,0 +1,34 @@ +INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'visualis', null, '0', '1', NULL, '0', NULL, NULL, '1', NULL, NULL); +SELECT @visualis_appid:=id from dss_application WHERE `name` = 'visualis'; +INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.appjoint.visualis.display', @visualis_appid, '1', '1', '1', '1', NULL); +INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.appjoint.visualis.dashboard', @visualis_appid, '1', '1', '1', '1', NULL);UPDATE `dss_application` SET url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT' WHERE `name` in('visualis'); +UPDATE `dss_application` SET url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT' WHERE `name` in('visualis'); +UPDATE `dss_application` SET project_url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT/dss/visualis/#/project/${projectId}',homepage_url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT/dss/visualis/#/projects' WHERE `name` in('visualis'); +UPDATE `dss_workflow_node` SET jump_url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT/dss/visualis/#/project/${projectId}/display/${nodeId}' where node_type = 'linkis.appjoint.visualis.display'; +UPDATE `dss_workflow_node` SET jump_url = 'http://VISUALIS_NGINX_IP_2:VISUALIS_NGINX_PORT/dss/visualis/#/project/${projectId}/portal/${nodeId}/portalName/${nodeName}' where node_type = 'linkis.appjoint.visualis.dashboard'; +INSERT INTO `linkis_application` (`id`, `name`, `chinese_name`, `description`) VALUES (NULL, 'visualis', NULL, NULL); +select @application_id:=id from `linkis_application` where `name` = 'visualis'; + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index 1f63fdfed..d54550cd6 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -4,20 +4,24 @@ ### 一、确定您的安装环境 -####         DataSphereStudio根据组件丰富程度,安装环境略有差异,分为简单版和标准版,其区别如下: +####         DataSphereStudio根据组件丰富程度,安装环境略有差异,分为精简版、简单版和标准版,其区别如下: ---- +1. **精简版**: -1. **简单版**: - -      最少环境依赖,前后端基础环境部分仅需准备:[Linkis](https://github.com/WeBankFinTech/Linkis)、JAVA、MYSQL、[Nginx](https://www.nginx.com/) ,您即刻能享受到DSS已集成的数据开发Scriptis、工作流实时执行,可视化,邮件发送,DATACHECK和EVENTCHECK服务。 +      最少环境依赖,前后端基础环境部分仅需准备:[Linkis](https://github.com/WeBankFinTech/Linkis)、JAVA、MYSQL、[Nginx](https://www.nginx.com/) ,您即刻能享受到DSS已集成的数据开发Scriptis服务。         点我进入[简单版DSS环境配置准备](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E4%BA%8C%E7%AE%80%E5%8D%95%E7%89%88dss%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E5%87%86%E5%A4%87) ---- +2. **简单版**: + +      较少环境依赖,前后端基础环境部分仅需准备:[Linkis](https://github.com/WeBankFinTech/Linkis)、JAVA、MYSQL、[Nginx](https://www.nginx.com/) ,您即刻能享受到DSS已集成的数据开发Scriptis、工作流实时执行,可视化,邮件发送,DATACHECK和EVENTCHECK服务。 +        点我进入[简单版DSS环境配置准备](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E4%BA%8C%E7%AE%80%E5%8D%95%E7%89%88dss%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E5%87%86%E5%A4%87) -2. **标准版** +---- +3. **标准版**           DSS还实现了很多外部系统的集成,如[Qualitis](https://github.com/WeBankFinTech/Qualitis)和[Azkaban](https://github.com/azkaban/azkaban),如果您想使用这些外部系统,则需要在简单版的基础上,提前安装和启动好Qualitis和Azkaban服务,并确保其能够正常提供服务,并在配置中指定对应服务的IP和端口。 @@ -25,10 +29,10 @@ ---- -## 二、简单版DSS环境配置准备 +## 二、精简版DSS环境配置准备 DSS环境配置准备分为三部分,前后端基础软件安装、后端环境配置准备和前端环配置境准备,详细介绍如下: ### 2.1 前后端基础软件安装 -Linkis标准版(0.9.1及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) +Linkis简单版(0.9.1及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) @@ -58,6 +62,121 @@ Nginx,[如何安装Nginx](https://www.tecmint.com/install-nginx-on-centos-7/) 从DSS已发布的release中([点击这里进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/releases)),下载对应安装包。先解压安装包到安装目录,并对解压后的文件进行配置修改 +``` + tar -xvf wedatasphere-dss-x.x.x-dist.tar.gz +``` + + +### c. 修改基础配置 + +``` + vi conf/config.sh +``` + +```properties + + + deployUser=hadoop #指定部署用户 + + DSS_INSTALL_HOME=/appcom/Install/DSS #指定DSS的安装目录 + + EUREKA_INSTALL_IP=127.0.0.1 #Linkis的 EUREKA 服务主机IP地址 + + EUREKA_PORT=20303 #Linkis的 EUREKA 服务端口号 + + WORKSPACE_USER_ROOT_PATH=file:///tmp/Linkis #指定用户根目录,存储用户的脚本文件和日志文件等,是用户的工作空间。 + + RESULT_SET_ROOT_PATH=hdfs:///tmp/linkis # 结果集文件路径,用于存储Job的结果集文件 + +``` + +### d. 修改数据库配置 + +```bash + vi conf/db.sh +``` + +```properties + # 设置DSS-Server和Eventchecker AppJoint的数据库的连接信息,需要和linkis保持同库 + MYSQL_HOST= + MYSQL_PORT= + MYSQL_DB= + MYSQL_USER= + MYSQL_PASSWORD= +``` + +### 2.3 前端端环境配置准备 + +### a、下载安装包 + + 点击[release](https://github.com/WeBankFinTech/DataSphereStudio/releases) 下载对应安装包,并在安装目录进行解压: + +```bash + unzip wedatasphere-dss-web-x.x.x-dist.zip +``` + +##### 注意:如果DSS前端安装包是用户自行编译的,则需要把[visualis前端安装包](https://github.com/WeBankFinTech/Visualis/releases)复制到DSS前端安装目录的dss/visualis文件夹下,以供自动化安装使用 + +### b、配置修改 + +    进入前端工作目录,在该目录下编辑: + + +```bash + vi conf/config.sh +``` + +更改dss的前端端口和后端linkis的gateway的IP地址及端口 + +``` +# Configuring front-end ports +dss_port="8088" + +# URL of the backend linkis gateway +linkis_url="http://127.0.0.1:9001" + +# dss ip address +dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') +``` + + 环境准备完毕,点我进入 [五、安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E5%9B%9B%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) + + +---- + +## 三、简单版DSS环境配置准备 +DSS环境配置准备分为三部分,前后端基础软件安装、后端环境配置准备和前端环配置境准备,详细介绍如下: +### 3.1 前后端基础软件安装 +Linkis简单版(0.9.1及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) + +JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) + +MySQL (5.5+),[如何安装MySQL](https://www.runoob.com/mysql/mysql-install.html) + +Nginx,[如何安装Nginx](https://www.tecmint.com/install-nginx-on-centos-7/) + +### 3.2 后端环境配置准备 + +### a. 创建用户 + + 例如: **部署用户是hadoop账号** + +在部署机器上创建部署用户,使用该用户进行安装。 +``` + sudo useradd hadoop +``` + +##### 注意:用户需要有sudo权限,且可免密登陆本机。[如何配置SSH免密登陆](https://linuxconfig.org/passwordless-ssh) +``` + vi /etc/sudoers + + hadoop ALL=(ALL) NOPASSWD: NOPASSWD: ALL +``` + +### b. 安装包准备 + +从DSS已发布的release中([点击这里进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/releases)),下载对应安装包。先解压安装包到安装目录,并对解压后的文件进行配置修改 + ``` tar -xvf wedatasphere-dss-x.x.x-dist.tar.gz ``` @@ -106,7 +225,7 @@ Nginx,[如何安装Nginx](https://www.tecmint.com/install-nginx-on-centos-7/) MYSQL_PASSWORD= ``` -### 2.3 前端端环境配置准备 +### 3.3 前端端环境配置准备 ### a、下载安装包 @@ -135,12 +254,12 @@ linkis_url="http://127.0.0.1:9001" dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') ``` - 环境准备完毕,点我进入 [四、安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E5%9B%9B%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) + 环境准备完毕,点我进入 [五、安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E5%9B%9B%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) -## 三、标准版DSS环境配置准备 +## 四、标准版DSS环境配置准备 标准版DSS环境准备也分为三部分,前后端基础软件安装、后端环境准备和前端环境准备,详细介绍如下: -### 3.1 前后端基础软件安装 -Linkis标准版(0.9.1及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) +### 4.1 前后端基础软件安装 +Linkis简单版(0.9.1及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) @@ -153,7 +272,7 @@ Qualitis [如何安装Qualitis](https://github.com/WeBankFinTech/Qualitis/blob/m Azkaban [如何安装Azkaban](https://github.com/azkaban/azkaban) ##### 注意:支持Azkaban调度需要配套安装linkis-jobtype,请点击[Linkis jobType安装文档](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/Azkaban_LinkisJobType_Deployment_Manual.md) -### 3.2 后端环境配置准备 +### 4.2 后端环境配置准备 ### a. 创建用户 @@ -231,7 +350,7 @@ Azkaban [如何安装Azkaban](https://github.com/azkaban/azkaban) MYSQL_PASSWORD= ``` -### 3.3 前端环境配置准备 +### 4.3 前端环境配置准备 ### a、下载安装包 @@ -263,9 +382,9 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/ 环境准备完毕,点我进入 [四、安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E5%9B%9B%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) -# 四、安装和使用 +# 五、安装和使用 -## 4.1. DataSphereStudio 后台安装: +## 5.1. DataSphereStudio 后台安装: ### a. 执行安装脚本: @@ -277,7 +396,7 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/ - install.sh脚本会询问您安装模式。 -     安装模式就是简单模式或标准模式,请根据您准备的环境情况,选择合适的安装模式,简单模式和标准模式都会检查mysql服务,标准模式还会检测Qualitis服务和Azkaban服务,如果检测失败会直接退出安装。 +     安装模式就是简单模式或标准模式,请根据您准备的环境情况,选择合适的安装模式,精简版、简单模式和标准模式都会检查mysql服务,标准模式还会检测Qualitis服务和Azkaban外部server服务,如果检测失败会直接退出安装。 - install.sh脚本会询问您是否需要初始化数据库并导入元数据。      因为担心用户重复执行install.sh脚本,把数据库中的用户数据清空,所以在install.sh执行时,会询问用户是否需要初始化数据库并导入元数据。 @@ -292,9 +411,7 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/         通过查看控制台打印的日志信息查看是否安装成功。 -        如果有错误信息,可以查看具体报错原因。 - -        您也可以通过查看我们的[常见问题](https://github.com/WeBankFinTech/DataSphereStudio/wiki/FAQ),获取问题的解答。 +        您也可以通过查看我们的[常见问题]([https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch1/DSS%E5%AE%89%E8%A3%85%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%88%97%E8%A1%A8.md](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch1/DSS%E5%AE%89%E8%A3%85%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%88%97%E8%A1%A8.md)),获取问题的解答。 ### d. 启动DataSphereStudio后台服务 @@ -316,7 +433,7 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/ ![Eureka](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/images/zh_CN/chapter2/quickInstallUse/quickInstall.png) -## 4.2 DataSphereStudio前端安装 +## 5.2 DataSphereStudio前端安装 ### a、部署 @@ -387,7 +504,7 @@ server { ### 2.将前端包拷贝到对应的目录: ```/appcom/Install/DSS/FRONT; # 前端包安装目录 ``` -##### 注意: 手动安装DSS前端,则需要到DSS前端安装目录的dss/visualis文件夹下,解压visualis前端安装包。 +##### 注意: 手动安装DSS前端,则需要到DSS前端安装目录的dss/visualis文件夹下,解压visualis前端安装包,用于自动化安装visualis前端。 ### 3.启动服务 ```sudo systemctl restart nginx``` @@ -395,10 +512,10 @@ server { ### 4.谷歌浏览器访问: ```http://nginx_ip:nginx_port``` -**试用用户和密码均为部署用户,更多用户配置,详见** [Linkis LDAP](https://github.com/WeBankFinTech/Linkis/wiki/%E9%83%A8%E7%BD%B2%E5%92%8C%E7%BC%96%E8%AF%91%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93) +**DSS登录用户和登录密码都是部署DSS的Linux用户名,更多用户配置,详见** [Linkis LDAP](https://github.com/WeBankFinTech/Linkis/wiki/%E9%83%A8%E7%BD%B2%E5%92%8C%E7%BC%96%E8%AF%91%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93) 如何详细使用DSS, 点我进入 [DSS快速使用文档](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch3/DSS_User_Manual.md) -## 4.3、常见问题 +## 5.3、常见问题 [DSS安装常见问题](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch1/DSS%E5%AE%89%E8%A3%85%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%88%97%E8%A1%A8.md) \ No newline at end of file -- Gitee From f38ae08a0a39145de9da2a507fa0cd816aa8f347 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Tue, 24 Dec 2019 22:59:03 +0800 Subject: [PATCH 041/238] Version number modification close #57 --- assembly/pom.xml | 2 +- datachecker-appjoint/pom.xml | 2 +- docs/en_US/ch1/DataSphereStudio_Compile_Manual.md | 2 +- .../ch2/Azkaban_LinkisJobType_Deployment_Manual.md | 2 +- ...7\274\226\350\257\221\346\226\207\346\241\243.md" | 2 +- dss-appjoint-auth/pom.xml | 2 +- dss-appjoint-core/pom.xml | 2 +- dss-appjoint-loader/pom.xml | 4 ++-- dss-application/pom.xml | 2 +- dss-azkaban-scheduler-appjoint/pom.xml | 2 +- dss-common/pom.xml | 2 +- dss-flow-execution-entrance/pom.xml | 2 +- dss-linkis-node-execution/pom.xml | 2 +- dss-scheduler-appjoint-core/pom.xml | 2 +- dss-server/pom.xml | 4 ++-- eventchecker-appjoint/pom.xml | 2 +- plugins/azkaban/linkis-jobtype/pom.xml | 2 +- plugins/linkis/linkis-appjoint-entrance/pom.xml | 2 +- pom.xml | 4 ++-- qualitis-appjoint/appjoint/pom.xml | 2 +- .../wedatasphere/appjoint/QualitisNodeExecution.java | 12 +++++++++--- sendemail-appjoint/sendemail-core/pom.xml | 2 +- visualis-appjoint/appjoint/pom.xml | 2 +- 23 files changed, 34 insertions(+), 28 deletions(-) diff --git a/assembly/pom.xml b/assembly/pom.xml index 8ba8adfde..4ec1c8b64 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 4.0.0 diff --git a/datachecker-appjoint/pom.xml b/datachecker-appjoint/pom.xml index 5ef5b7806..c2d804486 100644 --- a/datachecker-appjoint/pom.xml +++ b/datachecker-appjoint/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 4.0.0 diff --git a/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md b/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md index 1225b0f99..d3dde44ae 100644 --- a/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md +++ b/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md @@ -6,7 +6,7 @@ ```xml - 0.6.0 + 0.7.0 0.9.1 2.11.8 1.8 diff --git a/docs/en_US/ch2/Azkaban_LinkisJobType_Deployment_Manual.md b/docs/en_US/ch2/Azkaban_LinkisJobType_Deployment_Manual.md index 098673adf..d70a87eed 100644 --- a/docs/en_US/ch2/Azkaban_LinkisJobType_Deployment_Manual.md +++ b/docs/en_US/ch2/Azkaban_LinkisJobType_Deployment_Manual.md @@ -2,7 +2,7 @@ ## 1. Ready work -1.Click [release](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.6.0/linkis-jobtype-0.6.0.zip) to select the corresponding installation package to download: +1.Click [release](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.7.0/linkis-jobtype-0.7.0.zip) to select the corresponding installation package to download: - linkis-jobtype-$version.zip diff --git "a/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" "b/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" index d68ec401b..26f89d3dc 100644 --- "a/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" @@ -6,7 +6,7 @@ ```xml - 0.6.0 + 0.7.0 0.9.1 2.11.8 1.8 diff --git a/dss-appjoint-auth/pom.xml b/dss-appjoint-auth/pom.xml index 4815bd70a..04144de5c 100644 --- a/dss-appjoint-auth/pom.xml +++ b/dss-appjoint-auth/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 4.0.0 diff --git a/dss-appjoint-core/pom.xml b/dss-appjoint-core/pom.xml index 1d70a3825..0c00f2cd7 100644 --- a/dss-appjoint-core/pom.xml +++ b/dss-appjoint-core/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 4.0.0 diff --git a/dss-appjoint-loader/pom.xml b/dss-appjoint-loader/pom.xml index 98acd9f6e..7dc9097f3 100644 --- a/dss-appjoint-loader/pom.xml +++ b/dss-appjoint-loader/pom.xml @@ -22,12 +22,12 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 4.0.0 dss-appjoint-loader - 0.6.0 + 0.7.0 diff --git a/dss-application/pom.xml b/dss-application/pom.xml index b12fbea75..1a55a8035 100644 --- a/dss-application/pom.xml +++ b/dss-application/pom.xml @@ -23,7 +23,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 dss-application diff --git a/dss-azkaban-scheduler-appjoint/pom.xml b/dss-azkaban-scheduler-appjoint/pom.xml index 2391dd429..a6d894534 100644 --- a/dss-azkaban-scheduler-appjoint/pom.xml +++ b/dss-azkaban-scheduler-appjoint/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 4.0.0 diff --git a/dss-common/pom.xml b/dss-common/pom.xml index 5fe13c32b..bbf896bfa 100644 --- a/dss-common/pom.xml +++ b/dss-common/pom.xml @@ -23,7 +23,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 dss-common diff --git a/dss-flow-execution-entrance/pom.xml b/dss-flow-execution-entrance/pom.xml index 7e03605ad..12218e310 100644 --- a/dss-flow-execution-entrance/pom.xml +++ b/dss-flow-execution-entrance/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 4.0.0 diff --git a/dss-linkis-node-execution/pom.xml b/dss-linkis-node-execution/pom.xml index dac6c0aa5..ecea3e8bf 100644 --- a/dss-linkis-node-execution/pom.xml +++ b/dss-linkis-node-execution/pom.xml @@ -24,7 +24,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 dss-linkis-node-execution diff --git a/dss-scheduler-appjoint-core/pom.xml b/dss-scheduler-appjoint-core/pom.xml index 95bf0e4c4..1eaba100f 100644 --- a/dss-scheduler-appjoint-core/pom.xml +++ b/dss-scheduler-appjoint-core/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 4.0.0 diff --git a/dss-server/pom.xml b/dss-server/pom.xml index e7470f350..f42dbb0a4 100644 --- a/dss-server/pom.xml +++ b/dss-server/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 4.0.0 @@ -145,7 +145,7 @@ com.webank.wedatasphere.dss dss-scheduler-appjoint-core - 0.6.0 + 0.7.0 diff --git a/eventchecker-appjoint/pom.xml b/eventchecker-appjoint/pom.xml index e7a5a7c21..8c38e4747 100644 --- a/eventchecker-appjoint/pom.xml +++ b/eventchecker-appjoint/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 4.0.0 diff --git a/plugins/azkaban/linkis-jobtype/pom.xml b/plugins/azkaban/linkis-jobtype/pom.xml index dfc73b728..56225d510 100644 --- a/plugins/azkaban/linkis-jobtype/pom.xml +++ b/plugins/azkaban/linkis-jobtype/pom.xml @@ -23,7 +23,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 com.webank.wedatasphere.dss linkis-jobtype diff --git a/plugins/linkis/linkis-appjoint-entrance/pom.xml b/plugins/linkis/linkis-appjoint-entrance/pom.xml index 5b721b862..26b80a750 100644 --- a/plugins/linkis/linkis-appjoint-entrance/pom.xml +++ b/plugins/linkis/linkis-appjoint-entrance/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 4.0.0 diff --git a/pom.xml b/pom.xml index 5f3078cc2..c93448dc7 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ pom com.webank.wedatasphere.dss dss - 0.6.0 + 0.7.0 dss-common @@ -47,7 +47,7 @@ - 0.6.0 + 0.7.0 0.9.1 2.11.8 1.8 diff --git a/qualitis-appjoint/appjoint/pom.xml b/qualitis-appjoint/appjoint/pom.xml index 226419bac..d32ad4bb8 100644 --- a/qualitis-appjoint/appjoint/pom.xml +++ b/qualitis-appjoint/appjoint/pom.xml @@ -5,7 +5,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 4.0.0 diff --git a/qualitis-appjoint/appjoint/src/main/java/com.webank/wedatasphere/appjoint/QualitisNodeExecution.java b/qualitis-appjoint/appjoint/src/main/java/com.webank/wedatasphere/appjoint/QualitisNodeExecution.java index 66196b7cf..f2b0bbc38 100644 --- a/qualitis-appjoint/appjoint/src/main/java/com.webank/wedatasphere/appjoint/QualitisNodeExecution.java +++ b/qualitis-appjoint/appjoint/src/main/java/com.webank/wedatasphere/appjoint/QualitisNodeExecution.java @@ -44,6 +44,10 @@ public class QualitisNodeExecution extends LongTermNodeExecution { private String baseUrl; + public boolean canExecute(Node node, NodeContext nodeContext) { + return true; + } + @Override public void init(Map map) throws AppJointErrorException { appId = (String) map.get("qualitis_appId"); @@ -64,8 +68,10 @@ public class QualitisNodeExecution extends LongTermNodeExecution { String filter = (String) map.get("filter"); String executionUser = (String) map.get("executeUser"); String createUser = (String) map.get("user"); - Long groupId = Long.valueOf((Integer) map.get("ruleGroupId")); - + Map map1 = ((AppJointNode)appJointNode).getJobContent(); + String id = map1.get("ruleGroupId").toString(); + float f = Float.valueOf(id); + Long groupId = (long)f; QualitisSubmitRequest submitRequest = new QualitisSubmitRequest(); submitRequest.setCreateUser(createUser); submitRequest.setExecutionUser(executionUser); @@ -317,4 +323,4 @@ public class QualitisNodeExecution extends LongTermNodeExecution { public void setBaseUrl(String s) { this.baseUrl = s; } -} +} \ No newline at end of file diff --git a/sendemail-appjoint/sendemail-core/pom.xml b/sendemail-appjoint/sendemail-core/pom.xml index 81e946f15..97c3c167d 100644 --- a/sendemail-appjoint/sendemail-core/pom.xml +++ b/sendemail-appjoint/sendemail-core/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 4.0.0 diff --git a/visualis-appjoint/appjoint/pom.xml b/visualis-appjoint/appjoint/pom.xml index 33e921f8d..9c6016de1 100644 --- a/visualis-appjoint/appjoint/pom.xml +++ b/visualis-appjoint/appjoint/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.6.0 + 0.7.0 4.0.0 -- Gitee From 815363e0e49e70999ff1ee4fc7a47a5b914f43ab Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 25 Dec 2019 09:53:47 +0800 Subject: [PATCH 042/238] =?UTF-8?q?Update=20DSS=E5=BF=AB=E9=80=9F=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E4=BD=BF=E7=94=A8=E6=96=87=E6=A1=A3.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...275\277\347\224\250\346\226\207\346\241\243.md" | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index d54550cd6..110b94374 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -11,21 +11,21 @@       最少环境依赖,前后端基础环境部分仅需准备:[Linkis](https://github.com/WeBankFinTech/Linkis)、JAVA、MYSQL、[Nginx](https://www.nginx.com/) ,您即刻能享受到DSS已集成的数据开发Scriptis服务。 -        点我进入[简单版DSS环境配置准备](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E4%BA%8C%E7%AE%80%E5%8D%95%E7%89%88dss%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E5%87%86%E5%A4%87) +        点我进入[精简版DSS环境配置准备](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E4%BA%8C%E7%B2%BE%E7%AE%80%E7%89%88dss%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E5%87%86%E5%A4%87) ---- 2. **简单版**:       较少环境依赖,前后端基础环境部分仅需准备:[Linkis](https://github.com/WeBankFinTech/Linkis)、JAVA、MYSQL、[Nginx](https://www.nginx.com/) ,您即刻能享受到DSS已集成的数据开发Scriptis、工作流实时执行,可视化,邮件发送,DATACHECK和EVENTCHECK服务。 -        点我进入[简单版DSS环境配置准备](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E4%BA%8C%E7%AE%80%E5%8D%95%E7%89%88dss%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E5%87%86%E5%A4%87) +        点我进入[简单版DSS环境配置准备](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E4%B8%89%E7%AE%80%E5%8D%95%E7%89%88dss%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E5%87%86%E5%A4%87) ---- 3. **标准版**           DSS还实现了很多外部系统的集成,如[Qualitis](https://github.com/WeBankFinTech/Qualitis)和[Azkaban](https://github.com/azkaban/azkaban),如果您想使用这些外部系统,则需要在简单版的基础上,提前安装和启动好Qualitis和Azkaban服务,并确保其能够正常提供服务,并在配置中指定对应服务的IP和端口。 -          点我进入[标准版DSS环境配置准备](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E4%B8%89%E6%A0%87%E5%87%86%E7%89%88dss%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E5%87%86%E5%A4%87) +          点我进入[标准版DSS环境配置准备](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E5%9B%9B%E6%A0%87%E5%87%86%E7%89%88dss%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E5%87%86%E5%A4%87) ---- @@ -139,7 +139,7 @@ linkis_url="http://127.0.0.1:9001" dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') ``` - 环境准备完毕,点我进入 [五、安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E5%9B%9B%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) + 环境准备完毕,点我进入 [五、安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E4%BA%94%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) ---- @@ -254,7 +254,7 @@ linkis_url="http://127.0.0.1:9001" dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') ``` - 环境准备完毕,点我进入 [五、安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E5%9B%9B%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) + 环境准备完毕,点我进入 [五、安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E4%BA%94%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) ## 四、标准版DSS环境配置准备 标准版DSS环境准备也分为三部分,前后端基础软件安装、后端环境准备和前端环境准备,详细介绍如下: @@ -380,7 +380,7 @@ linkis_url="http://127.0.0.1:9001" dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') ``` - 环境准备完毕,点我进入 [四、安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E5%9B%9B%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) + 环境准备完毕,点我进入 [五、安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E4%BA%94%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) # 五、安装和使用 @@ -518,4 +518,4 @@ server { ## 5.3、常见问题 -[DSS安装常见问题](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch1/DSS%E5%AE%89%E8%A3%85%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%88%97%E8%A1%A8.md) \ No newline at end of file +[DSS安装常见问题](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch1/DSS%E5%AE%89%E8%A3%85%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%88%97%E8%A1%A8.md) -- Gitee From 48d6b1b10257ea3642525ea9d6adb977969e0775 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 25 Dec 2019 10:01:28 +0800 Subject: [PATCH 043/238] =?UTF-8?q?Update=20DSS=E5=BF=AB=E9=80=9F=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E4=BD=BF=E7=94=A8=E6=96=87=E6=A1=A3.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...4\275\277\347\224\250\346\226\207\346\241\243.md" | 12 ------------ 1 file changed, 12 deletions(-) diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index 110b94374..83ff91152 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -79,10 +79,6 @@ Nginx,[如何安装Nginx](https://www.tecmint.com/install-nginx-on-centos-7/) deployUser=hadoop #指定部署用户 DSS_INSTALL_HOME=/appcom/Install/DSS #指定DSS的安装目录 - - EUREKA_INSTALL_IP=127.0.0.1 #Linkis的 EUREKA 服务主机IP地址 - - EUREKA_PORT=20303 #Linkis的 EUREKA 服务端口号 WORKSPACE_USER_ROOT_PATH=file:///tmp/Linkis #指定用户根目录,存储用户的脚本文件和日志文件等,是用户的工作空间。 @@ -194,10 +190,6 @@ Nginx,[如何安装Nginx](https://www.tecmint.com/install-nginx-on-centos-7/) deployUser=hadoop #指定部署用户 DSS_INSTALL_HOME=/appcom/Install/DSS #指定DSS的安装目录 - - EUREKA_INSTALL_IP=127.0.0.1 #Linkis的 EUREKA 服务主机IP地址 - - EUREKA_PORT=20303 #Linkis的 EUREKA 服务端口号 WORKSPACE_USER_ROOT_PATH=file:///tmp/Linkis #指定用户根目录,存储用户的脚本文件和日志文件等,是用户的工作空间。 @@ -311,10 +303,6 @@ Azkaban [如何安装Azkaban](https://github.com/azkaban/azkaban) deployUser=hadoop #指定部署用户 DSS_INSTALL_HOME=/appcom/Install/DSS #指定DSS的安装目录 - - EUREKA_INSTALL_IP=127.0.0.1 #Linkis的 EUREKA 服务主机IP地址 - - EUREKA_PORT=20303 #Linkis的 EUREKA 服务端口号 WORKSPACE_USER_ROOT_PATH=file:///tmp/Linkis #指定用户根目录,存储用户的脚本文件和日志文件等,是用户的工作空间。 -- Gitee From 9ba71b00496a9b3f8aacb49d69b39b5c8fd1f140 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 25 Dec 2019 10:04:22 +0800 Subject: [PATCH 044/238] Add Lite install script and documentation close #58 --- conf/config.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/conf/config.sh b/conf/config.sh index 0b5a501e3..2d0172d23 100644 --- a/conf/config.sh +++ b/conf/config.sh @@ -4,21 +4,12 @@ deployUser=hadoop ### The install home path of DSS,Must provided DSS_INSTALL_HOME=/appcom/Install/DSS -### Linkis EUREKA information. -EUREKA_INSTALL_IP=127.0.0.1 # Microservices Service Registration Discovery Center -EUREKA_PORT=20303 - ### Specifies the user workspace, which is used to store the user's script files and log files. ### Generally local directory WORKSPACE_USER_ROOT_PATH=file:///tmp/linkis/ ### Path to store job ResultSet:file or hdfs path RESULT_SET_ROOT_PATH=hdfs:///tmp/linkis -### 1、DataCheck APPJOINT,This service is used to provide DataCheck capability. -HIVE_META_URL=jdbc:mysql://127.0.0.1:3306/hivemeta?characterEncoding=UTF-8 -HIVE_META_USER=xxx -HIVE_META_PASSWORD=xxx - ################### The install Configuration of all Micro-Services ##################### # # NOTICE: @@ -43,6 +34,10 @@ APPJOINT_ENTRANCE_PORT=9005 FLOW_EXECUTION_INSTALL_IP=127.0.0.1 FLOW_EXECUTION_PORT=9006 +### Linkis EUREKA information. +EUREKA_INSTALL_IP=127.0.0.1 # Microservices Service Registration Discovery Center +EUREKA_PORT=20303 + ### Linkis Gateway information GATEWAY_INSTALL_IP=127.0.0.1 GATEWAY_PORT=9001 @@ -50,6 +45,11 @@ GATEWAY_PORT=9001 ### SSH Port SSH_PORT=22 +### 1、DataCheck APPJOINT,This service is used to provide DataCheck capability. +HIVE_META_URL=jdbc:mysql://127.0.0.1:3306/hivemeta?characterEncoding=UTF-8 +HIVE_META_USER=xxx +HIVE_META_PASSWORD=xxx + #Used to store the azkaban project transformed by DSS WDS_SCHEDULER_PATH=file:///appcom/tmp/wds/scheduler -- Gitee From db3c63e00ede6fc9661beeac9285775ec5ba7167 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 25 Dec 2019 10:08:02 +0800 Subject: [PATCH 045/238] =?UTF-8?q?Update=20DSS=E5=BF=AB=E9=80=9F=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E4=BD=BF=E7=94=A8=E6=96=87=E6=A1=A3.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index 83ff91152..d27f338b6 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -370,7 +370,7 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/ 环境准备完毕,点我进入 [五、安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E4%BA%94%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) -# 五、安装和使用 +## 五、安装和使用 ## 5.1. DataSphereStudio 后台安装: -- Gitee From 3a5b2b9ad3bfa4176f5545097086eaeebcf0af26 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 25 Dec 2019 10:09:34 +0800 Subject: [PATCH 046/238] =?UTF-8?q?Update=20DSS=E5=BF=AB=E9=80=9F=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E4=BD=BF=E7=94=A8=E6=96=87=E6=A1=A3.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...05\344\275\277\347\224\250\346\226\207\346\241\243.md" | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index d27f338b6..d3d96b212 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -1,4 +1,4 @@ -# # 如何快速安装使用DataSphereStudio +## 如何快速安装使用DataSphereStudio ### DataSphereStudio安装分为前端部分和后台部分,安装之前首先需要确定前、后端安装环境。 @@ -372,7 +372,7 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/ ## 五、安装和使用 -## 5.1. DataSphereStudio 后台安装: +### 5.1. DataSphereStudio 后台安装: ### a. 执行安装脚本: @@ -421,7 +421,7 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/ ![Eureka](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/images/zh_CN/chapter2/quickInstallUse/quickInstall.png) -## 5.2 DataSphereStudio前端安装 +### 5.2 DataSphereStudio前端安装 ### a、部署 @@ -504,6 +504,6 @@ server { 如何详细使用DSS, 点我进入 [DSS快速使用文档](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch3/DSS_User_Manual.md) -## 5.3、常见问题 +### 5.3、常见问题 [DSS安装常见问题](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch1/DSS%E5%AE%89%E8%A3%85%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%88%97%E8%A1%A8.md) -- Gitee From 53c810a6dcc512a812eb9f5041a56ddf2bf478c0 Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Tue, 24 Dec 2019 10:07:31 +0800 Subject: [PATCH 047/238] web compilation --- docs/en_US/ch4/Web Compilation.md | 102 ++++++++++++++++++ ...26\350\257\221\346\226\207\346\241\243.md" | 86 +++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 docs/en_US/ch4/Web Compilation.md create mode 100644 "docs/zh_CN/ch4/\345\211\215\347\253\257\347\274\226\350\257\221\346\226\207\346\241\243.md" diff --git a/docs/en_US/ch4/Web Compilation.md b/docs/en_US/ch4/Web Compilation.md new file mode 100644 index 000000000..1f22f0a29 --- /dev/null +++ b/docs/en_US/ch4/Web Compilation.md @@ -0,0 +1,102 @@ +# Compilation + +## Getting Started + +### Prerequisites + +Install Node.js on your computer. Download Link: [http://nodejs.cn/download/](http://nodejs.cn/download/). Recommend using the latest stable version. + +**Only do this step at the first time.** + +### Installation + +Run the following commands in terminal: + +``` +git clone https://github.com/WeBankFinTech/Scriptis.git +cd DataSphereStudio/web +npm install +``` + + Commands explanation: + +1. Pull remote repository to local: `git clone https://github.com/WeBankFinTech/Scriptis.git` + +2. Change to the root directory of the project: `cd DataSphereStudio/web` + +3. Install all dependencies required for the project: `npm install` + +**Only do this step at the first time.** + +### Configuration + +You need to make some configurations in your code, such as port address of backend server and socket address of backend server in .env.development file in root directory. + +``` +// Port address of backend server +VUE_APP_MN_CONFIG_PREFIX=http://yourIp:yourPort/yourPath +// Socket address +VUE_APP_MN_CONFIG_SOCKET=/yourSocketPath +``` + +You can refer to the official documentation of vue-cli for detailed explanation. [Modes and environment variables](https://cli.vuejs.org/guide/mode-and-env.html#modes) + +### Building project + +You can run the following command in terminal to build the project: + +``` +npm run build +``` + +A folder named "dist" would appear in your project's root directory if the command has run successfully and you can directly put "dist" to your static server. + +### How to run + +You would need to run the following command in terminal if you want to run project on your local browser and see corresponding effects after making changes to the code. + +``` +npm run serve +``` + +Access the application in browser (Chrome recommended) via link: [http://localhost:8080/](http://localhost:8080/) . + +Changes you make to the code would dynamically reflect on the +effects shown on browser when using the method described above to run project. + +**Notes: Since frontend and backend are developed separately, when running on local browser you need to allow cross domain access in order to access the port of backend server.** + +e.g. Chrome browser: + +Configuration in Windows: + +1. Close all browser windows. + +2. Create a shortcut of chrome, right-click to choose "properties" , then go to "Shortcut" tab find "Target" and add`--args --disable-web-security --user-data-dir=C:\MyChromeDevUserData` to it . +3. Use shortcut to open the browser. + +Configuration in MacOS: + +Run the following command. (You need to replace "yourname" in the path. If it's not working, check the path of MyChromeDevUserData on your machine and copy its path to the place right after "--user-data-dir=") + +``` +open -n /Applications/Google\ Chrome.app/ --args --disable-web-security --user-data-dir=/Users/yourname/MyChromeDevUserData/ +``` + +### FAQ + +#### Failed installation when running npm install + +Try to use Taobao npm mirror: + +``` +npm install -g cnpm --registry=https://registry.npm.taobao.org +``` + +Next, run the following command instead of npm install: + +``` +cnpm install +``` + +Note that you can still use `npm run serve` and `npm run build` to run and build project. \ No newline at end of file diff --git "a/docs/zh_CN/ch4/\345\211\215\347\253\257\347\274\226\350\257\221\346\226\207\346\241\243.md" "b/docs/zh_CN/ch4/\345\211\215\347\253\257\347\274\226\350\257\221\346\226\207\346\241\243.md" new file mode 100644 index 000000000..ee447703a --- /dev/null +++ "b/docs/zh_CN/ch4/\345\211\215\347\253\257\347\274\226\350\257\221\346\226\207\346\241\243.md" @@ -0,0 +1,86 @@ +# 编译文档中文版 + +## 启动流程 + +### 一、安装Node.js +将Node.js下载到电脑本地,安装即可。下载地址:[http://nodejs.cn/download/](http://nodejs.cn/download/) (建议使用最新的稳定版本) +**该步骤仅第一次使用时需要执行。** + +### 二、安装项目 +在终端命令行中执行以下指令: + +``` +git clone ${ipAddress} +cd DataSphereStudio/web +npm install +``` + +指令简介: +1. 将项目包从远程仓库拉取到电脑本地:git clone ${ipAddress} +2. 进入项目包根目录:cd DataSphereStudio/web +3. 安装项目所需依赖:npm install + +**该步骤仅第一次使用时需要执行。** + +### 三、配置 +您需要在代码中进行一些配置,如后端接口地址,后端socket地址等,如根目录下的.env.development文件: + +``` +// 后端接口地址 +VUE_APP_MN_CONFIG_PREFIX=http://yourIp:yourPort/yourPath +// 后端socket地址 +VUE_APP_MN_CONFIG_SOCKET=/yourSocketPath +``` + +配置的具体解释可参考vue-cli官方文档:[环境变量和模式](https://cli.vuejs.org/zh/guide/mode-and-env.html#%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E5%92%8C%E6%A8%A1%E5%BC%8F) + +### 打包项目 +您可以通过在终端命令行执行以下指令对项目进行打包,生成压缩后的代码: + +``` +npm run build +``` + +该指令成功执行后,项目根目录下会出现一个名叫 “dist” 的文件夹,该文件夹即为打包好的代码。您可以直接将该文件夹放进您的静态服务器中。 + +### 运行项目 +如果您想在本地浏览器上运行该项目并且改动代码查看效果,需要在终端命令行中执行以下指令: + +``` +npm run serve +``` + +在浏览器中(建议Chrome浏览器)通过链接访问应用:[http://localhost:8080/](http://localhost:8080/) . +当您使用该方式运行项目时,您对代码的改动产生的效果,会动态体现在浏览器上。 + +**注意:因为项目采用前后端分离开发,所以在本地浏览器上运行时,需要对浏览器进行设置跨域才能访问后端接口:** + +比如chrome浏览器: +windows系统下的配置方式: +1. 关闭所有的chrome浏览器。 +2. 新建一个chrome快捷方式,右键“属性”,“快捷方式”选项卡里选择“目标”,添加  --args --disable-web-security --user-data-dir=C:\MyChromeDevUserData +3. 通过快捷方式打开chrome浏览器 +mac系统下的配置方式: +在终端命令行执行以下命令(需要替换路径中的yourname,若还不生效请检查您机器上MyChromeDevUserData文件夹的位置并将路径复制到下面指令的“--user-data-dir=”后面) + +``` +open -n /Applications/Google\ Chrome.app/ --args --disable-web-security --user-data-dir=/Users/yourname/MyChromeDevUserData/ +``` + + +### 常见问题 + +#### npm install无法成功 +如果遇到该情况,可以使用国内的淘宝npm镜像: + +``` +npm install -g cnpm --registry=https://registry.npm.taobao.org +``` + +接着,通过执行以下指令代替npm install指令 + +``` +cnpm install +``` + +注意,项目启动和打包时,仍然可以使用npm run build和npm run serve指令 \ No newline at end of file -- Gitee From 4d8e7d0b53c875faf5e8abe8d085fbf30681c0ac Mon Sep 17 00:00:00 2001 From: wushengyeyouya <690574002@qq.com> Date: Sat, 28 Dec 2019 17:41:29 +0800 Subject: [PATCH 048/238] update README-ZH.md --- README-ZH.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README-ZH.md b/README-ZH.md index 1b76faaa4..d03ba039d 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -127,6 +127,17 @@ DSS主要特点:            **根据需要,用户可以简单快速替换DSS已集成的各种功能组件,或新增功能组件。** +## Demo试用环境 + +由于DataSphereStudio支持执行脚本风险较高,WeDataSphere Demo环境的隔离没有做完,考虑到大家都在咨询Demo环境,决定向社区先定向发放邀请码,接受企业和组织的试用申请。 + +如果您想试用Demo环境,请加入DataSphere Studio社区用户群(**加群方式请翻到本文档末尾处**),联系团队成员获取邀请码。 + +WeDataSphere Demo环境用户注册页面:https://sandbox.webank.com/wds/dss/#/register + +WeDataSphere Demo环境登录页面:https://sandbox.webank.com/wds/dss/ + +我们会尽快解决环境隔离问题,争取早日向社区完全开放WeDataSphere Demo环境。 ## 与类似系统对比 -- Gitee From 88a0948fb9d51db4039fba1283d5358d82805e26 Mon Sep 17 00:00:00 2001 From: wushengyeyouya <690574002@qq.com> Date: Sat, 28 Dec 2019 17:46:37 +0800 Subject: [PATCH 049/238] update README-ZH.md --- README-ZH.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README-ZH.md b/README-ZH.md index d03ba039d..216b6af86 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -129,15 +129,15 @@ DSS主要特点: ## Demo试用环境 -由于DataSphereStudio支持执行脚本风险较高,WeDataSphere Demo环境的隔离没有做完,考虑到大家都在咨询Demo环境,决定向社区先定向发放邀请码,接受企业和组织的试用申请。 +       由于DataSphereStudio支持执行脚本风险较高,WeDataSphere Demo环境的隔离没有做完,考虑到大家都在咨询Demo环境,决定向社区先定向发放邀请码,接受企业和组织的试用申请。 -如果您想试用Demo环境,请加入DataSphere Studio社区用户群(**加群方式请翻到本文档末尾处**),联系团队成员获取邀请码。 +       如果您想试用Demo环境,请加入DataSphere Studio社区用户群(**加群方式请翻到本文档末尾处**),联系团队成员获取邀请码。 -WeDataSphere Demo环境用户注册页面:https://sandbox.webank.com/wds/dss/#/register +       WeDataSphere Demo环境用户注册页面:https://sandbox.webank.com/wds/dss/#/register -WeDataSphere Demo环境登录页面:https://sandbox.webank.com/wds/dss/ +       WeDataSphere Demo环境登录页面:https://sandbox.webank.com/wds/dss/ -我们会尽快解决环境隔离问题,争取早日向社区完全开放WeDataSphere Demo环境。 +       我们会尽快解决环境隔离问题,争取早日向社区完全开放WeDataSphere Demo环境。 ## 与类似系统对比 -- Gitee From 0b759d8468ddf65825a3e9a62f0646de29e12cc7 Mon Sep 17 00:00:00 2001 From: muicoder Date: Fri, 3 Jan 2020 12:15:57 +0800 Subject: [PATCH 050/238] fix #69 --- .../wedatasphere/dss/appjoint/auth/impl/AppJointAuthImpl.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dss-appjoint-auth/src/main/scala/com/webank/wedatasphere/dss/appjoint/auth/impl/AppJointAuthImpl.scala b/dss-appjoint-auth/src/main/scala/com/webank/wedatasphere/dss/appjoint/auth/impl/AppJointAuthImpl.scala index 841461514..7413baf5f 100644 --- a/dss-appjoint-auth/src/main/scala/com/webank/wedatasphere/dss/appjoint/auth/impl/AppJointAuthImpl.scala +++ b/dss-appjoint-auth/src/main/scala/com/webank/wedatasphere/dss/appjoint/auth/impl/AppJointAuthImpl.scala @@ -38,7 +38,8 @@ class AppJointAuthImpl private() extends AppJointAuth with Logging { private def getBaseUrl(dssUrl: String): String = { val uri = new URI(dssUrl) - uri.getScheme + "://" + uri.getHost + ":" + uri.getPort + val dssPort = if(uri.getPort != -1) uri.getPort else 80 + uri.getScheme + "://" + uri.getHost + ":" + dssPort } protected def getDWSClient(dssUrl: String): DWSHttpClient = { -- Gitee From a6b036dcf1da853b1b154063bbd02255e6c4f861 Mon Sep 17 00:00:00 2001 From: peacewong Date: Mon, 6 Jan 2020 11:09:49 +0800 Subject: [PATCH 051/238] update linkis-jobtype install docs --- docs/zh_CN/ch2/Azkaban_LinkisJobType_Deployment_Manual.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/zh_CN/ch2/Azkaban_LinkisJobType_Deployment_Manual.md b/docs/zh_CN/ch2/Azkaban_LinkisJobType_Deployment_Manual.md index 846dc7aed..adc075174 100644 --- a/docs/zh_CN/ch2/Azkaban_LinkisJobType_Deployment_Manual.md +++ b/docs/zh_CN/ch2/Azkaban_LinkisJobType_Deployment_Manual.md @@ -22,19 +22,19 @@ cd linkis/bin/ LINKIS_GATEWAY_URL=http://127.0.0.1:9001 ## linkis的GateWay地址 ##Linkis gateway token defaultWS-AUTH -LINKIS_GATEWAY_TOKEN=WS-AUTH ## Linkis的代理Token,该参数可以用默认的 +LINKIS_GATEWAY_TOKEN=WS-AUTH ## Linkis的代理Token,该参数可以用默认值 ##Azkaban executor host -AZKABAN_EXECUTOR_HOST=127.0.0.1 ## AZKABAN执行器机器IP +AZKABAN_EXECUTOR_HOST=127.0.0.1 ## 如果Azkaban是单机安装则该IP就是机器IP,如果是分布式安装为Azkaban执行器机器IP, ### SSH Port SSH_PORT=22 ## SSH端口 ##Azkaban executor dir -AZKABAN_EXECUTOR_DIR=/tmp/Install/AzkabanInstall/executor ## 执行器的安装目录,最后不需要带上/ +AZKABAN_EXECUTOR_DIR=/tmp/Install/AzkabanInstall/executor ## 如果Azkaban是单机安装则该目录是Azkaban的安装目录,如果是分布式安装为执行器的安装目录,注意:最后不需要带上/ ##Azkaban executor plugin reload url -AZKABAN_EXECUTOR_URL=http://127.0.0.1:12321/executor?action=reloadJobTypePlugins ##这里只需要修改IP和端口即可 +AZKABAN_EXECUTOR_URL=http://$AZKABAN_EXECUTOR_HOST:12321/executor?action=reloadJobTypePlugins ##这里只需要修改IP和端口即可,该地址为Azkaban重载插件的地址。 ``` ## 3. 执行安装脚本 ``` -- Gitee From a26b914df24d2c2adb714057bae241e16a59895d Mon Sep 17 00:00:00 2001 From: tangjianfeng Date: Tue, 7 Jan 2020 19:24:51 +0800 Subject: [PATCH 052/238] add jdbc node --- db/dss_dml.sql | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/db/dss_dml.sql b/db/dss_dml.sql index f9c2b2a24..1d48c18b2 100644 --- a/db/dss_dml.sql +++ b/db/dss_dml.sql @@ -9,6 +9,7 @@ INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `s INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.spark.sql', @linkis_appid, '1', '1', '0', '1', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.spark.scala', @linkis_appid, '1', '1', '0', '1', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.hive.hql', @linkis_appid, '1', '1', '0', '1', NULL); +INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.jdbc', @linkis_appid, '1', '1', '0', '1', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.control.empty', @linkis_appid, '1', '1', '0', '0', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.appjoint.sendemail', @linkis_appid, '1', '1', '0', '0', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.appjoint.eventchecker.eventsender', @linkis_appid, '1', '1', '0', '0', NULL); @@ -47,3 +48,23 @@ insert into `linkis_config_key_tree` VALUES(NULL,@key_id3,@tree_id1); insert into `linkis_config_key_tree` VALUES(NULL,@key_id4,@tree_id1); insert into `linkis_config_key_tree` VALUES(NULL,@key_id5,@tree_id1); insert into `linkis_config_key_tree` VALUES(NULL,@key_id6,@tree_id2); + +#-----------------------jdbc------------------- + +select @application_id:=id from `linkis_application` where `name` = 'nodeexecution'; +INSERT INTO `linkis_application` (`id`, `name`, `chinese_name`, `description`) SELECT NULL,'nodeexecution',`chinese_name`,`description` FROM linkis_application WHERE @application_id IS NULL LIMIT 1 ; +select @jdbc_id:=id from `linkis_application` where `name` = 'jdbc'; + +INSERT INTO `linkis_config_key` (`id`, `key`, `description`, `name`, `application_id`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`) VALUES (NULL, 'jdbc.url', '格式:', 'jdbc连接地址', @application_id, NULL , 'None', NULL , '0', '0', '1'); +INSERT INTO `linkis_config_key` (`id`, `key`, `description`, `name`, `application_id`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`) VALUES (NULL, 'jdbc.username', NULL , 'jdbc连接用户名', @application_id, NULL, 'None', NULL , '0', '0', '1'); +INSERT INTO `linkis_config_key` (`id`, `key`, `description`, `name`, `application_id`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`) VALUES (NULL, 'jdbc.password', NULL , 'jdbc连接密码', @application_id, NULL , 'None', NULL , '0', '0', '1'); + +select @key_id1:=id from `linkis_config_key` where `application_id` = @application_id and `key` = 'jdbc.url'; +select @key_id2:=id from `linkis_config_key` where `application_id` = @application_id and `key` = 'jdbc.username'; +select @key_id3:=id from `linkis_config_key` where `application_id` = @application_id and `key` = 'jdbc.password'; + +SELECT @tree_id1:=t.id from linkis_config_tree t LEFT JOIN linkis_application a on t.application_id = a.id WHERE t.`name` = 'jdbc连接设置' and a.`name` = 'jdbc'; + +insert into `linkis_config_key_tree` VALUES(NULL,@key_id1,@tree_id1); +insert into `linkis_config_key_tree` VALUES(NULL,@key_id2,@tree_id1); +insert into `linkis_config_key_tree` VALUES(NULL,@key_id3,@tree_id1); -- Gitee From 137f7b46aae4d6ae1b159a77ed2ceeda1b9d079f Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Fri, 10 Jan 2020 14:37:04 +0800 Subject: [PATCH 053/238] add JDBC Node --- .../process/component/nodeparameter.vue | 14 +++++++++- .../js/module/process/images/newIcon/JDBC.svg | 1 + .../module/process/images/newIcon/JDBC2.svg | 1 + web/src/js/module/process/index.vue | 2 +- web/src/js/module/process/module.vue | 18 +++++++++++- web/src/js/module/process/shape.js | 7 +++++ web/src/js/module/setting/setting.vue | 28 +++++++++++++++++++ web/src/js/service/mixin.js | 2 +- web/src/js/service/nodeType.js | 9 +++++- 9 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 web/src/js/module/process/images/newIcon/JDBC.svg create mode 100644 web/src/js/module/process/images/newIcon/JDBC2.svg diff --git a/web/src/js/module/process/component/nodeparameter.vue b/web/src/js/module/process/component/nodeparameter.vue index 0d2bfd615..171ea38c6 100644 --- a/web/src/js/module/process/component/nodeparameter.vue +++ b/web/src/js/module/process/component/nodeparameter.vue @@ -298,6 +298,18 @@ export default { } }; return { + 'jdbcUrl': [ + { required: true, message: 'joburl为必填项', trigger: 'blur' }, + { type: 'string', pattern: /(jdbc)[a-zA-Z0-9_:./]/, message: '必须以jdbc开头,且只支持数字、字母、(_:./)', trigger: 'blur' }, + ], + 'jdbcUsername': [ + { required: true, message: 'username为必填项', trigger: 'blur' }, + { type: 'string', pattern: /^[^\u4e00-\u9fa5]+$/, message: '此值不支持中文', trigger: 'blur' }, + ], + 'jdbcPassword': [ + { required: true, message: 'password为必填项', trigger: 'blur' }, + { type: 'string', pattern: /^[^\u4e00-\u9fa5]+$/, message: '此值不支持中文', trigger: 'blur' }, + ], 'sourceType': [ { required: true, message: this.$t('message.process.nodeParameter.XZSJLY'), trigger: 'blur' }, { type: 'string', pattern: /^[^\u4e00-\u9fa5]+$/, message: this.$t('message.process.nodeParameter.CZBNSRZW'), trigger: 'change' }, @@ -612,7 +624,7 @@ export default { if (this.currentNode.jobContent && this.currentNode.jobContent.jobParams) { this.currentNode.params.configuration.runtime = JSON.parse(JSON.stringify(this.currentNode.jobContent.jobParams)); } - if ([NODETYPE.EVENTCHECKERF, NODETYPE.EVENTCHECKERW, NODETYPE.DATACHECKER].includes(this.currentNode.type)) { + if ([NODETYPE.EVENTCHECKERF, NODETYPE.EVENTCHECKERW, NODETYPE.DATACHECKER, NODETYPE.JDBC].includes(this.currentNode.type)) { Object.keys(this.currentNode.params.configuration.runtime).map((key) => { this.currentNode.params.configuration.runtime[this.transtionKey(key)] = String(this.currentNode.params.configuration.runtime[key]); delete this.currentNode.params.configuration.runtime[key]; diff --git a/web/src/js/module/process/images/newIcon/JDBC.svg b/web/src/js/module/process/images/newIcon/JDBC.svg new file mode 100644 index 000000000..4d366412a --- /dev/null +++ b/web/src/js/module/process/images/newIcon/JDBC.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/js/module/process/images/newIcon/JDBC2.svg b/web/src/js/module/process/images/newIcon/JDBC2.svg new file mode 100644 index 000000000..31270ec8b --- /dev/null +++ b/web/src/js/module/process/images/newIcon/JDBC2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/js/module/process/index.vue b/web/src/js/module/process/index.vue index f6ca018da..95c04db7b 100644 --- a/web/src/js/module/process/index.vue +++ b/web/src/js/module/process/index.vue @@ -208,7 +208,7 @@ export default { } } } - if ([NODETYPE.SPARKSQL, NODETYPE.HQL, NODETYPE.SPARKPY, NODETYPE.SHELL, NODETYPE.SCALA, NODETYPE.PYTHON].indexOf(node.type) !== -1) { + if ([NODETYPE.SPARKSQL, NODETYPE.HQL, NODETYPE.SPARKPY, NODETYPE.SHELL, NODETYPE.SCALA, NODETYPE.PYTHON, NODETYPE.JDBC].indexOf(node.type) !== -1) { const len = node.resources ? node.resources.length : 0; if (len && node.jobContent && node.jobContent.script) { // 判断是否有保存过脚本 const resourceId = node.resources[0].resourceId; diff --git a/web/src/js/module/process/module.vue b/web/src/js/module/process/module.vue index cd07b49d9..5b734c3bb 100644 --- a/web/src/js/module/process/module.vue +++ b/web/src/js/module/process/module.vue @@ -596,7 +596,7 @@ export default { } if (!this.workflowIsExecutor) { if (type === 'node') { - if ([NODETYPE.SPARKSQL, NODETYPE.HQL, NODETYPE.SPARKPY, NODETYPE.SCALA].includes(node.type)) { + if ([NODETYPE.SPARKSQL, NODETYPE.HQL, NODETYPE.SPARKPY, NODETYPE.SCALA, NODETYPE.JDBC].includes(node.type)) { arr.push({ text: this.$t('message.process.associate'), value: 'associate', @@ -908,6 +908,22 @@ export default { 'executeUser': '' }, }); + } else if (this.clickCurrentNode.type === NODETYPE.JDBC) { + if (this.clickCurrentNode.jobContent) { + this.$set(this.clickCurrentNode.jobContent, 'jobParams', { + 'jdbcUrl': '', + 'jdbcUsername': '', + 'jdbcPassword': '' + }); + } else { + this.$set(this.clickCurrentNode, 'jobContent', { + jobParams: { + 'jdbcUrl': '', + 'jdbcUsername': '', + 'jdbcPassword': '' + }, + }); + } } } // 节点参数位置发生改变,先定义一个新的configuration用来存储数据,后面把jobparams干掉 diff --git a/web/src/js/module/process/shape.js b/web/src/js/module/process/shape.js index 635b1d234..f0c2cf568 100644 --- a/web/src/js/module/process/shape.js +++ b/web/src/js/module/process/shape.js @@ -73,6 +73,13 @@ export default [ image: NODEICON[NODETYPE.PYTHON].icon, editParam: false, editBaseInfo: false, + }, + { + type: NODETYPE.JDBC, + title: 'jdbc', + image: NODEICON[NODETYPE.JDBC].icon, + editParam: false, + editBaseInfo: false, }], }, { diff --git a/web/src/js/module/setting/setting.vue b/web/src/js/module/setting/setting.vue index 79adf33ae..82c089516 100644 --- a/web/src/js/module/setting/setting.vue +++ b/web/src/js/module/setting/setting.vue @@ -80,6 +80,10 @@ export default { }, { name: 'IDE-pipeline', title: 'PipeLine', + }, + { + name: 'IDE-jdbc', + title: 'Jdbc', }], }, { name: '3', @@ -89,6 +93,26 @@ export default { name: 'visualis-spark', title: 'Spark', }], + }, + { + name: '4', + title: '工作流', + icon: 'md-analytics', + children: [{ + name: 'nodeexecution-spark', + title: 'Spark', + }, { + name: 'nodeexecution-hive', + title: 'Hive', + }, + { + name: 'nodeexecution-python', + title: 'Python', + }, + { + name: 'nodeexecution-jdbc', + title: 'Jdbc', + }], }], activeMenu: '', fullTree: [], @@ -110,6 +134,7 @@ export default { this.activeMenu = type; const IDE = 'IDE'; const VSBI = 'visualis'; + const NODEECECUTION = 'nodeexecution'; let appName = '通用设置'; let creator = '通用设置'; if (type.match(IDE)) { @@ -118,6 +143,9 @@ export default { } else if (type.match(VSBI)) { creator = VSBI; appName = type.slice(VSBI.length + 1, type.length); + } else if (type.match(NODEECECUTION)) { + creator = NODEECECUTION; + appName = type.slice(NODEECECUTION.length + 1, type.length); } api.fetch('/configuration/getFullTreesByAppName', { appName, diff --git a/web/src/js/service/mixin.js b/web/src/js/service/mixin.js index 31e933fcb..90341c5dd 100644 --- a/web/src/js/service/mixin.js +++ b/web/src/js/service/mixin.js @@ -30,7 +30,7 @@ export default { { rule: /\.(out)$/i, lang: 'hql', executable: true, application: 'pipeline', runType: 'pipeline', ext: '.out', scriptType: 'storage', abbr: 'stor', logo: 'fi-storage', isCanBeNew: true, label: 'Storage', isCanBeOpen: true }, { rule: /\.scala$/i, lang: 'java', executable: true, application: 'spark', runType: 'scala', ext: '.scala', scriptType: 'scala', abbr: 'scala', logo: 'fi-scala', isCanBeNew: true, label: 'Scala', isCanBeOpen: true, flowType: 'scala' }, { rule: /\.scala$/i, lang: 'java', executable: true, application: 'spark', runType: 'function.mdq', ext: '.scala', scriptType: 'scala', abbr: 'scala', logo: 'fi-scala', isCanBeNew: false, label: 'Scala', isCanBeOpen: true }, - { rule: /\.jdbc$/i, lang: 'hql', executable: true, application: 'jdbc', runType: 'jdbc', ext: '.jdbc', scriptType: 'jdbc', abbr: 'jdbc', logo: 'fi-jdbc', isCanBeNew: true, label: 'JDBC', isCanBeOpen: true }, + { rule: /\.jdbc$/i, lang: 'hql', executable: true, application: 'jdbc', runType: 'jdbc', ext: '.jdbc', scriptType: 'jdbc', abbr: 'jdbc', logo: 'fi-jdbc', isCanBeNew: true, label: 'JDBC', isCanBeOpen: true, flowType: 'jdbc' }, { rule: /\.python$/i, lang: 'python', executable: true, application: 'python', runType: 'python', ext: '.python', scriptType: 'python', abbr: 'py', logo: 'fi-python', isCanBeNew: true, label: 'Python', isCanBeOpen: true, flowType: 'python' }, { rule: /\.py$/i, lang: 'python', executable: true, application: 'spark', runType: 'python', ext: '.py', scriptType: 'pythonSpark', abbr: 'py', logo: 'fi-spark-python', isCanBeNew: true, label: 'PythonSpark', isCanBeOpen: true, flowType: 'pyspark' }, { rule: /\.r$/i, lang: 'r', executable: true, application: 'spark', runType: 'r', ext: '.r', scriptType: 'r', abbr: 'r', logo: 'fi-r', isCanBeNew: true, label: 'R', isCanBeOpen: true }, diff --git a/web/src/js/service/nodeType.js b/web/src/js/service/nodeType.js index 68ffedce5..bf0a65498 100644 --- a/web/src/js/service/nodeType.js +++ b/web/src/js/service/nodeType.js @@ -32,12 +32,14 @@ import scala from '../module/process/images/scala.svg'; import exchange from '../module/process/images/newIcon/exchange.svg'; import qualitis from '../module/process/images/newIcon/qualitis.svg'; import python from '../module/process/images/newIcon/python.svg'; +import jdbc from '../module/process/images/newIcon/JDBC2.svg'; const NODETYPE = { SHELL: 'azkaban.shell', HQL: 'linkis.hive.hql', SPARKSQL: 'linkis.spark.sql', SPARKPY: 'linkis.spark.py', SCALA: 'linkis.spark.scala', + JDBC: 'linkis.jdbc.jdbc', PYTHON: 'linkis.python.python', CONNECTOR: 'linkis.control.empty', DISPLAY: 'linkis.appjoint.visualis.display', @@ -57,9 +59,14 @@ const ext = { [NODETYPE.SPARKSQL]: 'sparksql', [NODETYPE.SPARKPY]: 'pyspark', [NODETYPE.SCALA]: 'scala', - [NODETYPE.PYTHON]: 'python' + [NODETYPE.PYTHON]: 'python', + [NODETYPE.JDBC]: 'jdbc' } const NODEICON = { + [NODETYPE.JDBC]: { + icon: jdbc, + class: {'jdbc': true} + }, [NODETYPE.SHELL]: { icon: shell, class: {'shell': true} -- Gitee From 4e35305acbdae6ffe1aa494d055f5f783da76728 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Fri, 10 Jan 2020 19:51:39 +0800 Subject: [PATCH 054/238] 1.Automated installation enhancements. 2.Adapt to linkis changes. 3.Add jdbc node type. 4.Resolving module dependency conflicts close #79 #80 #81 #82 --- assembly/pom.xml | 45 +++ bin/checkEnv.sh | 6 +- bin/{checkMicro.sh => checkServices.sh} | 59 ++- bin/install.sh | 351 ++++++++++++------ bin/start-all.sh | 120 +++--- bin/stop-all.sh | 58 ++- conf/config.sh | 9 +- db/dss_dml.sql | 2 +- .../ch1/DataSphereStudio_Compile_Manual.md | 2 +- .../en_US/ch2/DSS Quick Installation Guide.md | 4 +- ...26\350\257\221\346\226\207\346\241\243.md" | 2 +- ...77\347\224\250\346\226\207\346\241\243.md" | 6 +- dss-appjoint-auth/pom.xml | 5 + dss-flow-execution-entrance/pom.xml | 18 +- .../src/main/assembly/distribution.xml | 36 -- .../FlowExecutionAppJointSignalSharedJob.java | 16 +- .../job/FlowExecutionJobSignalKeyCreator.java | 39 ++ .../FlowExecutionEntranceConfiguration.scala | 3 +- .../execution/DefaultFlowExecution.scala | 9 +- .../job/parser/FlowJobNodeParser.scala | 7 +- .../entrance/node/AppJointJobBuilder.scala | 22 +- .../entrance/node/DefaultNodeRunner.scala | 26 +- dss-linkis-node-execution/pom.xml | 4 +- .../node/execution/WorkflowContextImpl.java | 5 +- .../conf/LinkisJobExecutionConfiguration.java | 2 +- .../impl/LinkisNodeExecutionImpl.java | 12 +- .../job/AbstractAppJointLinkisJob.java | 2 +- .../job/AbstractCommonLinkisJob.java | 2 +- .../dss/linkis/node/execution/job/Job.java | 2 +- .../execution/job/JobSignalKeyCreator.java | 25 ++ .../node/execution/job/SignalSharedJob.java | 6 +- .../execution/parser/JobParamsParser.java | 24 +- dss-scheduler-appjoint-core/pom.xml | 5 + dss-server/pom.xml | 2 +- dss-server/src/main/assembly/distribution.xml | 4 + .../job/AzkabanAppJointSignalSharedJob.java | 17 +- .../job/AzkabanJobSignalKeyCreator.java | 39 ++ .../linkis/jobtype/job/AzkanbanBuilder.java | 18 +- .../linkis/linkis-appjoint-entrance/pom.xml | 17 +- .../src/main/assembly/distribution.xml | 41 +- pom.xml | 2 +- visualis-appjoint/appjoint/pom.xml | 8 + .../execution/VisualisNodeExecution.scala | 32 +- 43 files changed, 801 insertions(+), 313 deletions(-) rename bin/{checkMicro.sh => checkServices.sh} (50%) create mode 100644 dss-flow-execution-entrance/src/main/java/com/webank/wedatasphere/dss/flow/execution/entrance/job/FlowExecutionJobSignalKeyCreator.java create mode 100644 dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/JobSignalKeyCreator.java create mode 100644 plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanJobSignalKeyCreator.java diff --git a/assembly/pom.xml b/assembly/pom.xml index 4ec1c8b64..29934071c 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -105,6 +105,51 @@ jackson-core 2.9.6 + + net.databinder.dispatch + dispatch-core_2.11 + 0.11.2 + + + net.databinder.dispatch + dispatch-json4s-jackson_2.11 + 0.11.2 + + + org.apache.htrace + htrace-core + 3.1.0-incubating + + + org.apache.commons + commons-math3 + 3.1.1 + + + org.apache.httpcomponents + httpclient + 4.5.4 + + + org.apache.httpcomponents + httpcore + 4.4.7 + + + com.ning + async-http-client + 1.8.10 + + + commons-beanutils + commons-beanutils + 1.7.0 + + + commons-beanutils + commons-beanutils-core + 1.8.0 + dss-assembly diff --git a/bin/checkEnv.sh b/bin/checkEnv.sh index bdf48659a..d51bd5ca2 100644 --- a/bin/checkEnv.sh +++ b/bin/checkEnv.sh @@ -1,3 +1,4 @@ +#!/bin/sh # # Copyright 2019 WeBank # @@ -13,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # -#!/bin/sh say() { printf 'check command fail \n %s\n' "$1" } @@ -32,7 +32,7 @@ need_cmd() { err "need '$1' (your linux command not found)" fi } -echo "<-----start to check linux cmd:yum java mysql unzip expect telnet sed tar---->" +echo "<-----start to check used cmd---->" need_cmd yum need_cmd java need_cmd mysql @@ -42,4 +42,4 @@ need_cmd telnet need_cmd tar need_cmd sed need_cmd dos2unix -echo "<-----end to check linux cmd:yum java mysql unzip expect telnet sed tar------>" +echo "<-----end to check used cmd---->" diff --git a/bin/checkMicro.sh b/bin/checkServices.sh similarity index 50% rename from bin/checkMicro.sh rename to bin/checkServices.sh index 3f8ff95fa..a540d525f 100644 --- a/bin/checkMicro.sh +++ b/bin/checkServices.sh @@ -20,18 +20,59 @@ shellDir=`dirname $0` workDir=`cd ${shellDir}/..;pwd` ##load config -source ${workDir}/conf/config.sh -source ${workDir}/conf/db.sh +export LINKIS_DSS_CONF_FILE=${LINKIS_DSS_CONF_FILE:-"${workDir}/conf/config.sh"} +export DISTRIBUTION=${DISTRIBUTION:-"${workDir}/conf/config.sh"} +source ${LINKIS_DSS_CONF_FILE} +source ${DISTRIBUTION} MICRO_SERVICE_NAME=$1 MICRO_SERVICE_IP=$2 MICRO_SERVICE_PORT=$3 -echo "<--------------------------------------------------------------------------->" -echo "Start to Check if your microservice:$MICRO_SERVICE_NAME is normal via telnet" -echo "" -if [ ! -d $DSS_INSTALL_HOME/$MICRO_SERVICE_NAME ];then - echo "$MICRO_SERVICE_NAME is not installed,the check steps will be skipped" - exit 0 + +local_host="`hostname --fqdn`" + +ipaddr="`hostname -i`" + +function isLocal(){ + if [ "$1" == "127.0.0.1" ];then + return 0 + elif [ $1 == "localhost" ]; then + return 0 + elif [ $1 == $local_host ]; then + return 0 + elif [ $1 == $ipaddr ]; then + return 0 + fi + return 1 +} + +function executeCMD(){ + isLocal $1 + flag=$? + echo "Is local "$flag + if [ $flag == "0" ];then + eval $2 + else + ssh -p $SSH_PORT $1 $2 + fi + +} + +#echo "<--------------------------------------------------------------------------->" +#echo "Start to Check if your microservice:$MICRO_SERVICE_NAME is normal via telnet" +#echo "" +#if ! executeCMD $SERVER_IP "test -e $DSS_INSTALL_HOME/$MICRO_SERVICE_NAME"; then +# echo "$MICRO_SERVICE_NAME is not installed,the check steps will be skipped" +# exit 0 +#fi +echo "===========================================================" +echo $MICRO_SERVICE_NAME +echo $MICRO_SERVICE_IP +echo $MICRO_SERVICE_PORT +echo "===========================================================" + +if [ $MICRO_SERVICE_NAME == "visualis-server" ]||[ $MICRO_SERVICE_IP == "127.0.0.1" ]; then + MICRO_SERVICE_IP="`hostname -i`" fi result=`echo -e "\n" | telnet $MICRO_SERVICE_IP $MICRO_SERVICE_PORT 2>/dev/null | grep Connected | wc -l` @@ -42,7 +83,7 @@ else echo "ERROR your $MICRO_SERVICE_NAME microservice is not start successful !!! ERROR logs as follows :" echo "PLEAESE CHECK DETAIL LOG,LOCATION:$DSS_INSTALL_HOME/$MICRO_SERVICE_NAME/logs/linkis.out" echo '<------------------------------------------------------------->' - tail -n 50 $DSS_INSTALL_HOME/$MICRO_SERVICE_NAME/logs/*.out + executeCMD $MICRO_SERVICE_IP "tail -n 50 $DSS_INSTALL_HOME/$MICRO_SERVICE_NAME/logs/*.out" echo '<-------------------------------------------------------------->' echo "PLEAESE CHECK DETAIL LOG,LOCATION:$DSS_INSTALL_HOME/$MICRO_SERVICE_NAME/logs/linkis.out" exit 1 diff --git a/bin/install.sh b/bin/install.sh index 5961dfdbd..01b8c3a04 100644 --- a/bin/install.sh +++ b/bin/install.sh @@ -15,6 +15,7 @@ # #!/bin/sh #Actively load user env + source ~/.bash_profile shellDir=`dirname $0` @@ -45,17 +46,13 @@ fi function isSuccess(){ if [ $? -ne 0 ]; then - echo "ERROR to " + $1 + echo "Failed to " + $1 exit 1 else - echo "SUCESS to" + $1 + echo "Succeed to" + $1 fi } -#check env -sh ${workDir}/bin/checkEnv.sh -isSuccess "check env" - function checkJava(){ java -version isSuccess "execute java --version" @@ -72,46 +69,108 @@ else fi } + +say() { + printf 'check command fail \n %s\n' "$1" +} + +err() { + say "$1" >&2 + exit 1 +} + +check_cmd() { + command -v "$1" > /dev/null 2>&1 +} + +need_cmd() { + if ! check_cmd "$1"; then + err "need '$1' (command not found)" + fi +} + +#check env +sh ${workDir}/bin/checkEnv.sh +isSuccess "check env" + ##load config echo "step1:load config" -source ${workDir}/conf/config.sh -source ${workDir}/conf/db.sh +export DSS_CONFIG_PATH=${DSS_CONFIG_PATH:-"${workDir}/conf/config.sh"} +export DSS_DB_CONFIG_PATH=${DSS_DB_CONFIG_PATH:-"${workDir}/conf/db.sh"} +export DISTRIBUTION=${DISTRIBUTION:-"${workDir}/conf/config.sh"} +source ${DSS_CONFIG_PATH} +source ${DSS_DB_CONFIG_PATH} +source ${DISTRIBUTION} isSuccess "load config" -local_host="`hostname -i`" +local_host="`hostname --fqdn`" +ipaddr="`hostname -i`" + +function isLocal(){ + if [ "$1" == "127.0.0.1" ];then + return 0 + elif [ $1 == "localhost" ]; then + return 0 + elif [ $1 == $local_host ]; then + return 0 + elif [ $1 == $ipaddr ]; then + return 0 + fi + return 1 +} + +function executeCMD(){ + isLocal $1 + flag=$? + if [ $flag == "0" ];then + echo "Is local execution:$2" + eval $2 + else + echo "Is remote execution:$2" + ssh -p $SSH_PORT $1 $2 + fi +} -##env check -echo "Please enter the mode selection such as: 1" -echo " 1: lite" -echo " 2: sample" -echo " 3: Standard" -echo "" +function copyFile(){ + isLocal $1 + flag=$? + src=$2 + dest=$3 + if [ $flag == "0" ];then + echo "Is local cp " + eval "cp -r $src $dest" + else + echo "Is remote cp " + scp -r -P $SSH_PORT $src $1:$dest + fi +} -INSTALL_MODE=1 +##install mode choice +if [ "$INSTALL_MODE" == "" ];then + echo "Please enter the mode selection such as: 1" + echo " 1: Lite" + echo " 2: Simple" + echo " 3: Standard" + echo "" + read -p "Please input the choice:" idx + INSTALL_MODE=$idx +fi -read -p "Please input the choice:" idx -if [[ '1' = "$idx" ]];then - INSTALL_MODE=1 +if [[ '1' = "$INSTALL_MODE" ]];then echo "You chose lite installation mode" - #check for Java checkJava - #check for mysql SERVER_NAME=MYSQL EXTERNAL_SERVER_IP=$MYSQL_HOST EXTERNAL_SERVER_PORT=$MYSQL_PORT checkExternalServer -elif [[ '2' = "$idx" ]];then - INSTALL_MODE=2 +elif [[ '2' = "$INSTALL_MODE" ]];then echo "You chose sample installation mode" - #check for Java checkJava - #check for mysql SERVER_NAME=MYSQL EXTERNAL_SERVER_IP=$MYSQL_HOST EXTERNAL_SERVER_PORT=$MYSQL_PORT - -elif [[ '3' = "$idx" ]];then - INSTALL_MODE=3 + checkExternalServer +elif [[ '3' = "$INSTALL_MODE" ]];then echo "You chose Standard installation mode" #check for Java checkJava @@ -124,13 +183,16 @@ elif [[ '3' = "$idx" ]];then SERVER_NAME=Qualitis EXTERNAL_SERVER_IP=$QUALITIS_ADRESS_IP EXTERNAL_SERVER_PORT=$QUALITIS_ADRESS_PORT + if [[ $IGNORECHECK = "" ]];then checkExternalServer + fi #check azkaban serivice SERVER_NAME=AZKABAN EXTERNAL_SERVER_IP=$AZKABAN_ADRESS_IP EXTERNAL_SERVER_PORT=$AZKABAN_ADRESS_PORT + if [[ $IGNORECHECK = "" ]];then checkExternalServer - + fi else echo "no choice,exit!" exit 1 @@ -156,40 +218,97 @@ else exit 1 fi +echo "create hdfs directory and local directory" +if [ "$WORKSPACE_USER_ROOT_PATH" != "" ] +then + localRootDir=$WORKSPACE_USER_ROOT_PATH + if [[ $WORKSPACE_USER_ROOT_PATH == file://* ]];then + localRootDir=${WORKSPACE_USER_ROOT_PATH#file://} + mkdir -p $localRootDir/$deployUser + sudo chmod -R 775 $localRootDir/$deployUser + elif [[ $WORKSPACE_USER_ROOT_PATH == hdfs://* ]];then + localRootDir=${WORKSPACE_USER_ROOT_PATH#hdfs://} + hdfs dfs -mkdir -p $localRootDir/$deployUser + hdfs dfs -chmod -R 775 $localRootDir/$deployUser + else + echo "does not support $WORKSPACE_USER_ROOT_PATH filesystem types" + fi +isSuccess "create $WORKSPACE_USER_ROOT_PATH directory" +fi + + +if [ "$RESULT_SET_ROOT_PATH" != "" ] +then + localRootDir=$RESULT_SET_ROOT_PATH + if [[ $RESULT_SET_ROOT_PATH == file://* ]];then + localRootDir=${RESULT_SET_ROOT_PATH#file://} + mkdir -p $localRootDir/$deployUser + sudo chmod -R 775 $localRootDir/$deployUser + elif [[ $RESULT_SET_ROOT_PATH == hdfs://* ]];then + localRootDir=${RESULT_SET_ROOT_PATH#hdfs://} + hdfs dfs -mkdir -p $localRootDir/$deployUser + hdfs dfs -chmod -R 775 $localRootDir/$deployUser + else + echo "does not support $RESULT_SET_ROOT_PATH filesystem types" + fi +isSuccess "create $RESULT_SET_ROOT_PATH directory" +fi + + +if [ "$WDS_SCHEDULER_PATH" != "" ] +then + localRootDir=$WDS_SCHEDULER_PATH + if [[ $WDS_SCHEDULER_PATH == file://* ]];then + localRootDir=${WDS_SCHEDULER_PATH#file://} + mkdir -p $localRootDir + sudo chmod -R 775 $localRootDir + elif [[ $WDS_SCHEDULER_PATH == hdfs://* ]];then + localRootDir=${WDS_SCHEDULER_PATH#hdfs://} + hdfs dfs -mkdir -p $localRootDir + hdfs dfs -chmod -R 775 $localRootDir + else + echo "does not support $WDS_SCHEDULER_PATH filesystem types" + fi +isSuccess "create $WDS_SCHEDULER_PATH directory" +fi + + ##init db if [[ '2' = "$MYSQL_INSTALL_MODE" ]];then - mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/dss_ddl.sql" - isSuccess "source dss_ddl.sql" - LOCAL_IP="`hostname -i`" - if [ $GATEWAY_INSTALL_IP == "127.0.0.1" ];then - echo "GATEWAY_INSTALL_IP is equals 127.0.0.1 ,we will change it to ip address" - GATEWAY_INSTALL_IP_2=$LOCAL_IP + mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/dss_ddl.sql" + isSuccess "source dss_ddl.sql" + LOCAL_IP="`hostname -i`" + if [ $GATEWAY_INSTALL_IP == "127.0.0.1" ];then + echo "GATEWAY_INSTALL_IP is equals 127.0.0.1 ,we will change it to ip address" + GATEWAY_INSTALL_IP_2=$LOCAL_IP else - GATEWAY_INSTALL_IP_2=$GATEWAY_INSTALL_IP + GATEWAY_INSTALL_IP_2=$GATEWAY_INSTALL_IP fi #echo $GATEWAY_INSTALL_IP_2 sed -i "s/GATEWAY_INSTALL_IP_2/$GATEWAY_INSTALL_IP_2/g" ${workDir}/db/dss_dml.sql sed -i "s/GATEWAY_PORT/$GATEWAY_PORT/g" ${workDir}/db/dss_dml.sql mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/dss_dml.sql" - isSuccess "source dss_dml.sql" + isSuccess "source dss_dml.sql" - if [ '2' = "$INSTALL_MODE" ]||[ '3' = "$INSTALL_MODE" ];then - echo "visualis support " - if [ $VISUALIS_NGINX_IP == "127.0.0.1" ]||[ $VISUALIS_NGINX_IP == "0.0.0.0" ];then - echo "VISUALIS_NGINX_IP is equals $VISUALIS_NGINX_IP ,we will change it to ip address" - VISUALIS_NGINX_IP_2=$LOCAL_IP + if [[ '2' = "$INSTALL_MODE" ]] || [[ '3' = "$INSTALL_MODE" ]];then + echo "visualis support,visualis database will be initialized !" + if [ $VISUALIS_NGINX_IP == "127.0.0.1" ]||[ $VISUALIS_NGINX_IP == "0.0.0.0" ];then + echo "VISUALIS_NGINX_IP is equals $VISUALIS_NGINX_IP ,we will change it to ip address" + VISUALIS_NGINX_IP_2=$LOCAL_IP else - VISUALIS_NGINX_IP_2=$VISUALIS_NGINX_IP + VISUALIS_NGINX_IP_2=$VISUALIS_NGINX_IP fi #echo $VISUALIS_NGINX_IP_2 sed -i "s/VISUALIS_NGINX_IP_2/$VISUALIS_NGINX_IP_2/g" ${workDir}/db/visualis.sql sed -i "s/VISUALIS_NGINX_PORT/$VISUALIS_NGINX_PORT/g" ${workDir}/db/visualis.sql - mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/visualis.sql" - isSuccess "source visualis.sql" + mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/visualis.sql" + isSuccess "source visualis.sql" + mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/davinci.sql" + isSuccess "source davinci.sql" fi - if [[ '3' = "$INSTALL_MODE" ]];then - echo "start to update azkaban and qualitis table info " + if [[ '3' = "$INSTALL_MODE" ]];then + echo "azkaban and qualitis support, azkaban and qualitis database will be initialized !" #azkaban if [ $AZKABAN_ADRESS_IP == "127.0.0.1" ];then echo "AZKABAN_ADRESS_IP is equals 127.0.0.1 ,we will change it to ip address" @@ -217,28 +336,9 @@ if [[ '2' = "$MYSQL_INSTALL_MODE" ]];then fi fi -## davinci db init -echo "Do you want to clear davinci table information in the database ? If you have not installed davinci environment,you must input '2',if you have davinci installed,choice 1." -echo " 1: Do not execute table-building statements" -echo "WARN:" -echo " 2: Dangerous! Clear all data and rebuild the tables." -echo "" -DAVINCI_INSTALL_MODE=1 -read -p "Please input the choice:" idx -if [[ '2' = "$idx" ]];then - DAVINCI_INSTALL_MODE=2 - echo "You chose rebuild davinci's table !!! start rebuild all tables" - mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/davinci.sql" - isSuccess "source davinci.sql" - echo "" -elif [[ '1' = "$idx" ]];then - DAVINCI_INSTALL_MODE=1 - echo "You chose not execute table-building statements" - echo "" -else - echo "no choice,exit!" - exit 1 -fi +##Deal special symbol '#' +HIVE_META_PASSWORD=$(echo ${HIVE_META_PASSWORD//'#'/'\#'}) +MYSQL_PASSWORD=$(echo ${MYSQL_PASSWORD//'#'/'\#'}) ###linkis Eurkea info SERVER_IP=$EUREKA_INSTALL_IP @@ -260,24 +360,30 @@ then SERVER_IP=$local_host fi -if ! ssh -p $SSH_PORT $SERVER_IP test -e $SERVER_HOME; then - ssh -p $SSH_PORT $SERVER_IP "sudo mkdir -p $SERVER_HOME;sudo chown -R $deployUser:$deployUser $SERVER_HOME" +if ! executeCMD $SERVER_IP "test -e $SERVER_HOME"; then + executeCMD $SERVER_IP "sudo mkdir -p $SERVER_HOME;sudo chown -R $deployUser:$deployUser $SERVER_HOME" isSuccess "create the dir of $SERVERNAME" fi echo "$SERVERNAME-step2:copy install package" -scp -P $SSH_PORT ${workDir}/share/$PACKAGE_DIR/$SERVERNAME.zip $SERVER_IP:$SERVER_HOME +copyFile $SERVER_IP ${workDir}/share/$PACKAGE_DIR/$SERVERNAME.zip $SERVER_HOME + +if ! executeCMD $SERVER_IP "test -e $SERVER_HOME/lib"; then + copyFile $SERVER_IP ${workDir}/lib $SERVER_HOME +fi + +#copyFile $SERVER_IP ${workDir}/lib $SERVER_HOME isSuccess "copy ${SERVERNAME}.zip" -ssh -p $SSH_PORT $SERVER_IP "cd $SERVER_HOME/;rm -rf $SERVERNAME-bak; mv -f $SERVERNAME $SERVERNAME-bak" -ssh -p $SSH_PORT $SERVER_IP "cd $SERVER_HOME/;unzip $SERVERNAME.zip > /dev/null" -ssh -p $SSH_PORT $SERVER_IP "cd $workDir/;scp -r lib/* $SERVER_HOME/$SERVERNAME/lib" +executeCMD $SERVER_IP "cd $SERVER_HOME/;rm -rf $SERVERNAME-bak; mv -f $SERVERNAME $SERVERNAME-bak" +executeCMD $SERVER_IP "cd $SERVER_HOME/;unzip $SERVERNAME.zip > /dev/null" +executeCMD $SERVER_IP "cd $SERVER_HOME/;scp -r lib/* $SERVER_HOME/$SERVERNAME/lib" isSuccess "unzip ${SERVERNAME}.zip" echo "$SERVERNAME-step3:subsitution conf" SERVER_CONF_PATH=$SERVER_HOME/$SERVERNAME/conf/application.yml -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#port:.*#port: $SERVER_PORT#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#defaultZone:.*#defaultZone: $EUREKA_URL#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#hostname:.*#hostname: $SERVER_IP#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#port:.*#port: $SERVER_PORT#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#defaultZone:.*#defaultZone: $EUREKA_URL#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#hostname:.*#hostname: $SERVER_IP#g\" $SERVER_CONF_PATH" isSuccess "subsitution conf of $SERVERNAME" } ##function end @@ -291,16 +397,16 @@ then SERVER_IP=$local_host fi -if ! ssh -p $SSH_PORT $SERVER_IP test -e $SERVER_HOME; then - ssh -p $SSH_PORT $SERVER_IP "sudo mkdir -p $SERVER_HOME;sudo chown -R $deployUser:$deployUser $SERVER_HOME" +if ! executeCMD $SERVER_IP "test -e $SERVER_HOME"; then + executeCMD $SERVER_IP "sudo mkdir -p $SERVER_HOME;sudo chown -R $deployUser:$deployUser $SERVER_HOME" isSuccess "create the dir of $SERVERNAME" fi echo "$SERVERNAME-step2:copy install package" -scp -P $SSH_PORT ${workDir}/share/$PACKAGE_DIR/$SERVERNAME.zip $SERVER_IP:$SERVER_HOME +copyFile $SERVER_IP ${workDir}/share/$PACKAGE_DIR/$SERVERNAME.zip $SERVER_HOME isSuccess "copy ${SERVERNAME}.zip" -ssh -p $SSH_PORT $SERVER_IP "cd $SERVER_HOME/;rm -rf $SERVERNAME-bak; mv -f $SERVERNAME $SERVERNAME-bak" -ssh -p $SSH_PORT $SERVER_IP "cd $SERVER_HOME/;unzip $SERVERNAME.zip > /dev/null" +executeCMD $SERVER_IP "cd $SERVER_HOME/;rm -rf $SERVERNAME-bak; mv -f $SERVERNAME $SERVERNAME-bak" +executeCMD $SERVER_IP "cd $SERVER_HOME/;unzip $SERVERNAME.zip > /dev/null" isSuccess "unzip ${SERVERNAME}.zip" } ##function end @@ -315,15 +421,15 @@ then SERVER_IP=$local_host fi -if ! ssh -p $SSH_PORT $SERVER_IP test -e $SERVER_HOME/$APPJOINTPARENT; then - ssh -p $SSH_PORT $SERVER_IP "sudo mkdir -p $SERVER_HOME/$APPJOINTPARENT;sudo chown -R $deployUser:$deployUser $SERVER_HOME/$APPJOINTPARENT" +if ! executeCMD $SERVER_IP "test -e $SERVER_HOME/$APPJOINTPARENT"; then + executeCMD $SERVER_IP "sudo mkdir -p $SERVER_HOME/$APPJOINTPARENT;sudo chown -R $deployUser:$deployUser $SERVER_HOME/$APPJOINTPARENT" isSuccess "create the dir of $SERVER_HOME/$APPJOINTPARENT;" fi echo "$APPJOINTNAME-step2:copy install package" -scp -P $SSH_PORT $workDir/share/appjoints/$APPJOINTNAME/*.zip $SERVER_IP:$SERVER_HOME/$APPJOINTPARENT +copyFile $SERVER_IP $workDir/share/appjoints/$APPJOINTNAME/*.zip $SERVER_HOME/$APPJOINTPARENT isSuccess "copy ${APPJOINTNAME}.zip" -ssh -p $SSH_PORT $SERVER_IP "cd $SERVER_HOME/$APPJOINTPARENT/;unzip -o dss-*-appjoint.zip > /dev/null;rm -rf dss-*-appjoint.zip" +executeCMD $SERVER_IP "cd $SERVER_HOME/$APPJOINTPARENT/;unzip -o dss-*-appjoint.zip > /dev/null;rm -rf dss-*-appjoint.zip" isSuccess "install ${APPJOINTNAME}.zip" } ##function end @@ -339,18 +445,18 @@ installPackage ###update Dss-Server linkis.properties echo "$SERVERNAME-step4:update linkis.properties" SERVER_CONF_PATH=$SERVER_HOME/$SERVERNAME/conf/linkis.properties -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.server.mybatis.datasource.url.*#wds.linkis.server.mybatis.datasource.url=jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DB}?characterEncoding=UTF-8#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.server.mybatis.datasource.username.*#wds.linkis.server.mybatis.datasource.username=$MYSQL_USER#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.server.mybatis.datasource.password.*#wds.linkis.server.mybatis.datasource.password=$MYSQL_PASSWORD#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.dss.appjoint.scheduler.azkaban.address.*#wds.dss.appjoint.scheduler.azkaban.address=http://${AZKABAN_ADRESS_IP}:${AZKABAN_ADRESS_PORT}#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.gateway.ip.*#wds.linkis.gateway.ip=$GATEWAY_INSTALL_IP#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.gateway.port.*#wds.linkis.gateway.port=$GATEWAY_PORT#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.dss.appjoint.scheduler.project.store.dir.*#wds.dss.appjoint.scheduler.project.store.dir=$WDS_SCHEDULER_PATH#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.linkis.server.mybatis.datasource.url.*#wds.linkis.server.mybatis.datasource.url=jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DB}?characterEncoding=UTF-8#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.linkis.server.mybatis.datasource.username.*#wds.linkis.server.mybatis.datasource.username=$MYSQL_USER#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.linkis.server.mybatis.datasource.password.*#wds.linkis.server.mybatis.datasource.password=$MYSQL_PASSWORD#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.dss.appjoint.scheduler.azkaban.address.*#wds.dss.appjoint.scheduler.azkaban.address=http://${AZKABAN_ADRESS_IP}:${AZKABAN_ADRESS_PORT}#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.linkis.gateway.ip.*#wds.linkis.gateway.ip=$GATEWAY_INSTALL_IP#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.linkis.gateway.port.*#wds.linkis.gateway.port=$GATEWAY_PORT#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.dss.appjoint.scheduler.project.store.dir.*#wds.dss.appjoint.scheduler.project.store.dir=$WDS_SCHEDULER_PATH#g\" $SERVER_CONF_PATH" isSuccess "subsitution linkis.properties of $SERVERNAME" echo "<----------------$SERVERNAME:end------------------->" echo "" -if [ '2' = "$INSTALL_MODE" ]||[ '3' = "$INSTALL_MODE" ];then +if [[ '2' = "$INSTALL_MODE" ]]||[[ '3' = "$INSTALL_MODE" ]];then ##Flow execution Install PACKAGE_DIR=dss/dss-flow-execution-entrance SERVERNAME=dss-flow-execution-entrance @@ -362,9 +468,9 @@ installPackage ###Update flow execution linkis.properties echo "$SERVERNAME-step4:update linkis.properties" SERVER_CONF_PATH=$SERVER_HOME/$SERVERNAME/conf/linkis.properties -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.entrance.config.logPath.*#wds.linkis.entrance.config.logPath=$WORKSPACE_USER_ROOT_PATH#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.resultSet.store.path.*#wds.linkis.resultSet.store.path=$RESULT_SET_ROOT_PATH#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.gateway.url.*#wds.linkis.gateway.url=http://${GATEWAY_INSTALL_IP}:${GATEWAY_PORT}#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.linkis.entrance.config.logPath.*#wds.linkis.entrance.config.logPath=$WORKSPACE_USER_ROOT_PATH#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.linkis.resultSet.store.path.*#wds.linkis.resultSet.store.path=$RESULT_SET_ROOT_PATH#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.linkis.gateway.url.*#wds.linkis.gateway.url=http://${GATEWAY_INSTALL_IP}:${GATEWAY_PORT}#g\" $SERVER_CONF_PATH" isSuccess "subsitution linkis.properties of $SERVERNAME" echo "<----------------$SERVERNAME:end------------------->" echo "" @@ -379,8 +485,8 @@ installPackage ###Update appjoint entrance linkis.properties echo "$SERVERNAME-step4:update linkis.properties" SERVER_CONF_PATH=$SERVER_HOME/$SERVERNAME/conf/linkis.properties -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.entrance.config.logPath.*#wds.linkis.entrance.config.logPath=$WORKSPACE_USER_ROOT_PATH#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.resultSet.store.path.*#wds.linkis.resultSet.store.path=$RESULT_SET_ROOT_PATH#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.linkis.entrance.config.logPath.*#wds.linkis.entrance.config.logPath=$WORKSPACE_USER_ROOT_PATH#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.linkis.resultSet.store.path.*#wds.linkis.resultSet.store.path=$RESULT_SET_ROOT_PATH#g\" $SERVER_CONF_PATH" isSuccess "subsitution linkis.properties of $SERVERNAME" echo "<----------------$SERVERNAME:end------------------->" echo "" @@ -396,22 +502,25 @@ installVisualis echo "$SERVERNAME-step4:update linkis.properties" SERVER_CONF_PATH=$SERVER_HOME/$SERVERNAME/conf/linkis.properties if [ $VISUALIS_NGINX_IP == "127.0.0.1" ]||[ $VISUALIS_NGINX_IP == "0.0.0.0" ]; then - VISUALIS_NGINX_IP=$local_host + VISUALIS_NGINX_IP=$ipaddr +fi +if [ $VISUALIS_SERVER_INSTALL_IP == "127.0.0.1" ]||[ $VISUALIS_SERVER_INSTALL_IP == "0.0.0.0" ]; then + VISUALIS_SERVER_INSTALL_IP=$ipaddr fi -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.entrance.config.logPath.*#wds.linkis.entrance.config.logPath=$WORKSPACE_USER_ROOT_PATH#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.linkis.resultSet.store.path.*#wds.linkis.resultSet.store.path=$RESULT_SET_ROOT_PATH#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.dss.visualis.gateway.ip.*#wds.dss.visualis.gateway.ip=$GATEWAY_INSTALL_IP#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#wds.dss.visualis.gateway.port.*#wds.dss.visualis.gateway.port=$GATEWAY_PORT#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.linkis.entrance.config.logPath.*#wds.linkis.entrance.config.logPath=$WORKSPACE_USER_ROOT_PATH#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.linkis.resultSet.store.path.*#wds.linkis.resultSet.store.path=$RESULT_SET_ROOT_PATH#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.dss.visualis.gateway.ip.*#wds.dss.visualis.gateway.ip=$GATEWAY_INSTALL_IP#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#wds.dss.visualis.gateway.port.*#wds.dss.visualis.gateway.port=$GATEWAY_PORT#g\" $SERVER_CONF_PATH" SERVER_CONF_PATH=$SERVER_HOME/$SERVERNAME/conf/application.yml -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#address: 127.0.0.1#address: $VISUALIS_SERVER_INSTALL_IP#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#port: 9007#port: $VISUALIS_SERVER_PORT#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#url: http://0.0.0.0:0000/dss/visualis#url: http://$VISUALIS_NGINX_IP:$VISUALIS_NGINX_PORT/dss/visualis#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#address: 0.0.0.0#address: $VISUALIS_NGINX_IP#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#port: 0000#port: $VISUALIS_NGINX_PORT#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#defaultZone: http://127.0.0.1:20303/eureka/#defaultZone: http://$EUREKA_INSTALL_IP:$EUREKA_PORT/eureka/#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#url: jdbc:mysql://127.0.0.1:3306/xxx?characterEncoding=UTF-8#url: jdbc:mysql://$MYSQL_HOST:$MYSQL_PORT/$MYSQL_DB?characterEncoding=UTF-8#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#username: xxx#username: $MYSQL_USER#g\" $SERVER_CONF_PATH" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#password: xxx#password: $MYSQL_PASSWORD#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#address: 127.0.0.1#address: $VISUALIS_SERVER_INSTALL_IP#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#port: 9007#port: $VISUALIS_SERVER_PORT#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#url: http://0.0.0.0:0000/dss/visualis#url: http://$VISUALIS_NGINX_IP:$VISUALIS_NGINX_PORT/dss/visualis#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#address: 0.0.0.0#address: $VISUALIS_NGINX_IP#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#port: 0000#port: $VISUALIS_NGINX_PORT#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#defaultZone: http://127.0.0.1:20303/eureka/#defaultZone: http://$EUREKA_INSTALL_IP:$EUREKA_PORT/eureka/#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#url: jdbc:mysql://127.0.0.1:3306/xxx?characterEncoding=UTF-8#url: jdbc:mysql://$MYSQL_HOST:$MYSQL_PORT/$MYSQL_DB?characterEncoding=UTF-8#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#username: xxx#username: $MYSQL_USER#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "sed -i \"s#password: xxx#password: $MYSQL_PASSWORD#g\" $SERVER_CONF_PATH" isSuccess "subsitution linkis.properties of $SERVERNAME" echo "<----------------$SERVERNAME:end------------------->" echo "" @@ -423,9 +532,9 @@ APPJOINTNAME=datachecker installAppjoints echo "$APPJOINTNAME:subsitution conf" APPJOINTNAME_CONF_PATH_PATENT=$SERVER_HOME/$APPJOINTPARENT/$APPJOINTNAME/appjoint.properties -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#job.datachecker.jdo.option.url.*#job.datachecker.jdo.option.url=$HIVE_META_URL#g\" $APPJOINTNAME_CONF_PATH_PATENT" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#job.datachecker.jdo.option.username.*#job.datachecker.jdo.option.username=$HIVE_META_USER#g\" $APPJOINTNAME_CONF_PATH_PATENT" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#job.datachecker.jdo.option.password.*#job.datachecker.jdo.option.password=$HIVE_META_PASSWORD#g\" $APPJOINTNAME_CONF_PATH_PATENT" +executeCMD $SERVER_IP "sed -i \"s#job.datachecker.jdo.option.url.*#job.datachecker.jdo.option.url=$HIVE_META_URL#g\" $APPJOINTNAME_CONF_PATH_PATENT" +executeCMD $SERVER_IP "sed -i \"s#job.datachecker.jdo.option.username.*#job.datachecker.jdo.option.username=$HIVE_META_USER#g\" $APPJOINTNAME_CONF_PATH_PATENT" +executeCMD $SERVER_IP "sed -i \"s#job.datachecker.jdo.option.password.*#job.datachecker.jdo.option.password=$HIVE_META_PASSWORD#g\" $APPJOINTNAME_CONF_PATH_PATENT" isSuccess "subsitution conf of datachecker" echo "<----------------datachecker appjoint install end------------------->" echo "" @@ -436,9 +545,9 @@ APPJOINTNAME=eventchecker installAppjoints echo "$APPJOINTNAME:subsitution conf" APPJOINTNAME_CONF_PATH_PATENT=$SERVER_HOME/$APPJOINTPARENT/$APPJOINTNAME/appjoint.properties -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#msg.eventchecker.jdo.option.url.*#msg.eventchecker.jdo.option.url=jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DB}?characterEncoding=UTF-8#g\" $APPJOINTNAME_CONF_PATH_PATENT" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#msg.eventchecker.jdo.option.username.*#msg.eventchecker.jdo.option.username=$MYSQL_USER#g\" $APPJOINTNAME_CONF_PATH_PATENT" -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#msg.eventchecker.jdo.option.password.*#msg.eventchecker.jdo.option.password=$MYSQL_PASSWORD#g\" $APPJOINTNAME_CONF_PATH_PATENT" +executeCMD $SERVER_IP "sed -i \"s#msg.eventchecker.jdo.option.url.*#msg.eventchecker.jdo.option.url=jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DB}?characterEncoding=UTF-8#g\" $APPJOINTNAME_CONF_PATH_PATENT" +executeCMD $SERVER_IP "sed -i \"s#msg.eventchecker.jdo.option.username.*#msg.eventchecker.jdo.option.username=$MYSQL_USER#g\" $APPJOINTNAME_CONF_PATH_PATENT" +executeCMD $SERVER_IP "sed -i \"s#msg.eventchecker.jdo.option.password.*#msg.eventchecker.jdo.option.password=$MYSQL_PASSWORD#g\" $APPJOINTNAME_CONF_PATH_PATENT" isSuccess "subsitution conf of eventchecker" echo "<----------------$APPJOINTNAME:end------------------->" echo "" @@ -459,7 +568,7 @@ APPJOINTNAME=qualitis #qualitis appjoint install installAppjoints APPJOINTNAME_CONF_PATH_PATENT=$SERVER_HOME/$APPJOINTPARENT/$APPJOINTNAME/appjoint.properties -ssh -p $SSH_PORT $SERVER_IP "sed -i \"s#baseUrl=http://127.0.0.1:8090#baseUrl=http://$QUALITIS_ADRESS_IP:$QUALITIS_ADRESS_PORT#g\" $APPJOINTNAME_CONF_PATH_PATENT" +executeCMD $SERVER_IP "sed -i \"s#baseUrl=http://127.0.0.1:8090#baseUrl=http://$QUALITIS_ADRESS_IP:$QUALITIS_ADRESS_PORT#g\" $APPJOINTNAME_CONF_PATH_PATENT" isSuccess "subsitution conf of qualitis" echo "<----------------$APPJOINTNAME:end------------------->" echo "" diff --git a/bin/start-all.sh b/bin/start-all.sh index 8f5b04e2c..14016d020 100644 --- a/bin/start-all.sh +++ b/bin/start-all.sh @@ -15,21 +15,33 @@ # limitations under the License. # - - # Start all dss applications info="We will start all dss applications, it will take some time, please wait" echo ${info} #Actively load user env +source /etc/profile source ~/.bash_profile workDir=`dirname "${BASH_SOURCE-$0}"` workDir=`cd "$workDir"; pwd` - CONF_DIR="${workDir}"/../conf -CONF_FILE=${CONF_DIR}/config.sh +export LINKIS_DSS_CONF_FILE=${LINKIS_DSS_CONF_FILE:-"${CONF_DIR}/config.sh"} +export DISTRIBUTION=${DISTRIBUTION:-"${CONF_DIR}/config.sh"} +source $LINKIS_DSS_CONF_FILE +source ${DISTRIBUTION} +function isSuccess(){ +if [ $? -ne 0 ]; then + echo "ERROR: " + $1 + exit 1 +else + echo "INFO:" + $1 +fi +} +local_host="`hostname --fqdn`" + +ipaddr="`hostname -i`" function isLocal(){ if [ "$1" == "127.0.0.1" ];then @@ -56,28 +68,14 @@ function executeCMD(){ } -function isSuccess(){ -if [ $? -ne 0 ]; then - echo "ERROR: " + $1 - exit 1 -else - echo "INFO:" + $1 -fi -} - -sudo yum -y install dos2unix - - -local_host="`hostname --fqdn`" - #if there is no LINKIS_INSTALL_HOME,we need to source config again if [ -z ${DSS_INSTALL_HOME} ];then echo "Warning: DSS_INSTALL_HOME does not exist, we will source config" - if [ ! -f "${CONF_FILE}" ];then + if [ ! -f "${LINKIS_DSS_CONF_FILE}" ];then echo "Error: can not find config file, start applications failed" exit 1 else - source ${CONF_FILE} + source ${LINKIS_DSS_CONF_FILE} fi fi @@ -85,19 +83,29 @@ function startApp(){ echo "<-------------------------------->" echo "Begin to start $SERVER_NAME" SERVER_BIN=${DSS_INSTALL_HOME}/${SERVER_NAME}/bin -SERVER_START_CMD="source /etc/profile;source ~/.bash_profile;cd ${SERVER_BIN}; dos2unix ./* > /dev/null 2>&1; dos2unix ../conf/* > /dev/null 2>&1;sh start-${SERVER_NAME}.sh > /dev/null 2>&1 &" +#echo $SERVER_BIN +SERVER_LOCAL_START_CMD="dos2unix ${SERVER_BIN}/* > /dev/null 2>&1; dos2unix ${SERVER_BIN}/../conf/* > /dev/null 2>&1;sh ${SERVER_BIN}/start-${SERVER_NAME}.sh > /dev/null 2>&1 &" +SERVER_REMOTE_START_CMD="source /etc/profile;source ~/.bash_profile;cd ${SERVER_BIN}; dos2unix ./* > /dev/null 2>&1; dos2unix ../conf/* > /dev/null 2>&1; sh start-${SERVER_NAME}.sh > /dev/null 2>&1" + +if test -z "$SERVER_IP" +then + SERVER_IP=$local_host +fi -if [ ! -d $SERVER_BIN ];then +if ! executeCMD $SERVER_IP "test -e $SERVER_BIN"; then echo "<-------------------------------->" echo "$SERVER_NAME is not installed,the start steps will be skipped" echo "<-------------------------------->" return fi -if [ -n "${SERVER_IP}" ];then - ssh ${SERVER_IP} "${SERVER_START_CMD}" +isLocal $SERVER_IP +flag=$? +echo "Is local "$flag +if [ $flag == "0" ];then + eval $SERVER_LOCAL_START_CMD else - ssh ${local_host} "${SERVER_START_CMD}" + ssh -p $SSH_PORT $SERVER_IP $SERVER_REMOTE_START_CMD fi isSuccess "End to start $SERVER_NAME" echo "<-------------------------------->" @@ -119,6 +127,7 @@ SERVER_NAME=linkis-appjoint-entrance SERVER_IP=$APPJOINT_ENTRANCE_INSTALL_IP startApp +#visualis-server SERVER_NAME=visualis-server SERVER_IP=$VISUALIS_SERVER_INSTALL_IP startApp @@ -126,34 +135,53 @@ startApp echo "" echo "Start to check all dss microservice" echo "" + +function checkServer(){ +echo "<-------------------------------->" +echo "Begin to check $SERVER_NAME" +if test -z "$SERVER_IP" +then + SERVER_IP=$local_host +fi + +SERVER_BIN=${SERVER_HOME}/${SERVER_NAME}/bin + +if ! executeCMD $SERVER_IP "test -e ${DSS_INSTALL_HOME}/${SERVER_NAME}"; then + echo "$SERVER_NAME is not installed,the checkServer steps will be skipped" + return +fi + +sh $workDir/checkServices.sh $SERVER_NAME $SERVER_IP $SERVER_PORT +isSuccess "start $SERVER_NAME " +sleep 3 +echo "<-------------------------------->" +} + #check dss-server -MICRO_SERVICE_NAME=dss-server -MICRO_SERVICE_IP=$DSS_SERVER_INSTALL_IP -MICRO_SERVICE_PORT=$DSS_SERVER_PORT -sh $workDir/checkMicro.sh $MICRO_SERVICE_NAME $MICRO_SERVICE_IP $MICRO_SERVICE_PORT -isSuccess "$MICRO_SERVICE_NAME start" +SERVER_NAME=dss-server +SERVER_IP=$DSS_SERVER_INSTALL_IP +SERVER_PORT=$DSS_SERVER_PORT +checkServer #check dss-flow-execution-entrance -MICRO_SERVICE_NAME=dss-flow-execution-entrance -MICRO_SERVICE_IP=$FLOW_EXECUTION_INSTALL_IP -MICRO_SERVICE_PORT=$FLOW_EXECUTION_PORT -sh $workDir/checkMicro.sh $MICRO_SERVICE_NAME $MICRO_SERVICE_IP $MICRO_SERVICE_PORT -isSuccess "$MICRO_SERVICE_NAME start" +SERVER_NAME=dss-flow-execution-entrance +SERVER_IP=$FLOW_EXECUTION_INSTALL_IP +SERVER_PORT=$FLOW_EXECUTION_PORT +checkServer #check linkis-appjoint-entrance -MICRO_SERVICE_NAME=linkis-appjoint-entrance -MICRO_SERVICE_IP=$APPJOINT_ENTRANCE_INSTALL_IP -MICRO_SERVICE_PORT=$APPJOINT_ENTRANCE_PORT -sh $workDir/checkMicro.sh $MICRO_SERVICE_NAME $MICRO_SERVICE_IP $MICRO_SERVICE_PORT -isSuccess "$MICRO_SERVICE_NAME start" +SERVER_NAME=linkis-appjoint-entrance +SERVER_IP=$APPJOINT_ENTRANCE_INSTALL_IP +SERVER_PORT=$APPJOINT_ENTRANCE_PORT +checkServer #check visualis-server -sleep 10 #for visualis-server -MICRO_SERVICE_NAME=visualis-server -MICRO_SERVICE_IP=$VISUALIS_SERVER_INSTALL_IP -MICRO_SERVICE_PORT=$VISUALIS_SERVER_PORT -sh $workDir/checkMicro.sh $MICRO_SERVICE_NAME $MICRO_SERVICE_IP $MICRO_SERVICE_PORT -isSuccess "$MICRO_SERVICE_NAME start" +sleep 10 #visualis service need more time to register +SERVER_NAME=visualis-server +SERVER_IP=$VISUALIS_SERVER_INSTALL_IP +SERVER_PORT=$VISUALIS_SERVER_PORT +checkServer +echo "DSS started successfully" diff --git a/bin/stop-all.sh b/bin/stop-all.sh index 82252c7b5..af158c9b7 100644 --- a/bin/stop-all.sh +++ b/bin/stop-all.sh @@ -29,7 +29,12 @@ workDir=`cd "$workDir"; pwd` CONF_DIR="${workDir}"/../conf -CONF_FILE=${CONF_DIR}/config.sh +export LINKIS_DSS_CONF_FILE=${LINKIS_DSS_CONF_FILE:-"${CONF_DIR}/config.sh"} +export DISTRIBUTION=${DISTRIBUTION:-"${CONF_DIR}/config.sh"} +source ${DISTRIBUTION} + +local_host="`hostname --fqdn`" +ipaddr="`hostname -i`" function isSuccess(){ if [ $? -ne 0 ]; then @@ -40,18 +45,40 @@ else fi } +function isLocal(){ + if [ "$1" == "127.0.0.1" ];then + return 0 + elif [ $1 == "localhost" ]; then + return 0 + elif [ $1 == $local_host ]; then + return 0 + elif [ $1 == $ipaddr ]; then + return 0 + fi + return 1 +} +function executeCMD(){ + isLocal $1 + flag=$? + echo "Is local "$flag + if [ $flag == "0" ];then + eval $2 + else + ssh -p $SSH_PORT $1 $2 + fi + +} -local_host="`hostname --fqdn`" #if there is no LINKIS_INSTALL_HOME,we need to source config again if [ -z ${DSS_INSTALL_HOME} ];then echo "Warning: DSS_INSTALL_HOME does not exist, we will source config" - if [ ! -f "${CONF_FILE}" ];then + if [ ! -f "${LINKIS_DSS_CONF_FILE}" ];then echo "Error: can not find config file, stop applications failed" exit 1 else - source ${CONF_FILE} + source ${LINKIS_DSS_CONF_FILE} fi fi @@ -59,18 +86,26 @@ function stopAPP(){ echo "<-------------------------------->" echo "Begin to stop $SERVER_NAME" SERVER_BIN=${DSS_INSTALL_HOME}/${SERVER_NAME}/bin -SERVER_STOP_CMD="source ~/.bash_profile;cd ${SERVER_BIN}; dos2unix ./* > /dev/null 2>&1; dos2unix ../conf/* > /dev/null 2>&1; sh stop-${SERVER_NAME}.sh" -if [ ! -d ${DSS_INSTALL_HOME}/${SERVER_NAME} ];then +SERVER_LOCAL_STOP_CMD="sh ${SERVER_BIN}/stop-${SERVER_NAME}.sh" +SERVER_REMOTE_STOP_CMD="source /etc/profile;source ~/.bash_profile;cd ${SERVER_BIN}; sh stop-${SERVER_NAME}.sh " +if test -z "$SERVER_IP" +then + SERVER_IP=$local_host +fi + +if ! executeCMD $SERVER_IP "test -e ${DSS_INSTALL_HOME}/${SERVER_NAME}"; then echo "$SERVER_NAME is not installed,the stop steps will be skipped" return fi -if [ -n "${SERVER_IP}" ];then - ssh -p $SSH_PORT ${SERVER_IP} "${SERVER_STOP_CMD}" +isLocal $SERVER_IP +flag=$? +echo "Is local "$flag +if [ $flag == "0" ];then + eval $SERVER_LOCAL_STOP_CMD else - ssh -p $SSH_PORT ${local_host} "${SERVER_STOP_CMD}" + ssh -p $SSH_PORT $SERVER_IP $SERVER_REMOTE_STOP_CMD fi -isSuccess "End to stop $SERVER_NAME" echo "<-------------------------------->" sleep 3 } @@ -89,7 +124,10 @@ stopAPP SERVER_NAME=linkis-appjoint-entrance SERVER_IP=$APPJOINT_ENTRANCE_INSTALL_IP stopAPP + #visualis-server SERVER_NAME=visualis-server SERVER_IP=$VISUALIS_SERVER_INSTALL_IP stopAPP + +echo "stop-all shell script executed completely" diff --git a/conf/config.sh b/conf/config.sh index 2d0172d23..5499f42c1 100644 --- a/conf/config.sh +++ b/conf/config.sh @@ -1,8 +1,13 @@ +#!/bin/sh + +shellDir=`dirname $0` +workDir=`cd ${shellDir}/..;pwd` + ### deploy user deployUser=hadoop ### The install home path of DSS,Must provided -DSS_INSTALL_HOME=/appcom/Install/DSS +DSS_INSTALL_HOME=$workDir ### Specifies the user workspace, which is used to store the user's script files and log files. ### Generally local directory @@ -72,4 +77,4 @@ AZKABAN_ADRESS_PORT=8091 QUALITIS_ADRESS_IP=127.0.0.1 QUALITIS_ADRESS_PORT=8090 -DSS_VERSION=0.7.0 \ No newline at end of file +DSS_VERSION=0.7.0 diff --git a/db/dss_dml.sql b/db/dss_dml.sql index 1d48c18b2..79de16e9a 100644 --- a/db/dss_dml.sql +++ b/db/dss_dml.sql @@ -9,7 +9,7 @@ INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `s INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.spark.sql', @linkis_appid, '1', '1', '0', '1', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.spark.scala', @linkis_appid, '1', '1', '0', '1', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.hive.hql', @linkis_appid, '1', '1', '0', '1', NULL); -INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.jdbc', @linkis_appid, '1', '1', '0', '1', NULL); +INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.jdbc.jdbc', @linkis_appid, '1', '1', '0', '1', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.control.empty', @linkis_appid, '1', '1', '0', '0', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.appjoint.sendemail', @linkis_appid, '1', '1', '0', '0', NULL); INSERT INTO `dss_workflow_node` (`id`, `icon`, `node_type`, `application_id`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `support_jump`, `jump_url`) VALUES (NULL, NULL, 'linkis.appjoint.eventchecker.eventsender', @linkis_appid, '1', '1', '0', '0', NULL); diff --git a/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md b/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md index d3dde44ae..6a24df612 100644 --- a/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md +++ b/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md @@ -7,7 +7,7 @@ ```xml 0.7.0 - 0.9.1 + 0.9.3 2.11.8 1.8 3.3.3 diff --git a/docs/en_US/ch2/DSS Quick Installation Guide.md b/docs/en_US/ch2/DSS Quick Installation Guide.md index f8837393d..f4b8cd159 100644 --- a/docs/en_US/ch2/DSS Quick Installation Guide.md +++ b/docs/en_US/ch2/DSS Quick Installation Guide.md @@ -17,7 +17,7 @@ DSS also implements the integration of many external systems, such as [Qualitis] DSS environment configuration can be divided into three steps, including basic software installation, backend environment configuration, and frontend environment configuration. The details are as below: ### 2.1 Frontend and backend basic software installation -Linkis standard version (above 0.9.1). How to install [Linkis](https://github.com/WeBankFinTech/Linkis/blob/master/docs/en_US/ch1/deploy.md) +Linkis standard version (above 0.9.3). How to install [Linkis](https://github.com/WeBankFinTech/Linkis/blob/master/docs/en_US/ch1/deploy.md) JDK (above 1.8.0_141). How to install [JDK](https://www.runoob.com/java/java-environment-setup.html) @@ -111,7 +111,7 @@ The environment is ready, click me to enter ****[4. Installation and use](https: ## Three Standard DSS environment configuration preparation The standard DSS environment preparation is also divided into three parts, the frontEnd-end and back-end basic software installation, back-end environment preparation, and frontEnd-end environment preparation. The details are as follows: ### 3.1 frontEnd and BackEnd basic software installation -Linkis standard version (above 0.9.1), [How to install Linkis](https://github.com/WeBankFinTech/Linkis/blob/master/docs/en_US/ch1/deploy.md) +Linkis standard version (above 0.9.3), [How to install Linkis](https://github.com/WeBankFinTech/Linkis/blob/master/docs/en_US/ch1/deploy.md) JDK (above 1.8.0_141), How to install [JDK](https://www.runoob.com/java/java-environment-setup.html) diff --git "a/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" "b/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" index 26f89d3dc..0b4d82f0b 100644 --- "a/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" @@ -7,7 +7,7 @@ ```xml 0.7.0 - 0.9.1 + 0.9.3 2.11.8 1.8 3.3.3 diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index d3d96b212..23c3008bc 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -32,7 +32,7 @@ ## 二、精简版DSS环境配置准备 DSS环境配置准备分为三部分,前后端基础软件安装、后端环境配置准备和前端环配置境准备,详细介绍如下: ### 2.1 前后端基础软件安装 -Linkis简单版(0.9.1及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) +Linkis简单版(0.9.3及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) @@ -143,7 +143,7 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/ ## 三、简单版DSS环境配置准备 DSS环境配置准备分为三部分,前后端基础软件安装、后端环境配置准备和前端环配置境准备,详细介绍如下: ### 3.1 前后端基础软件安装 -Linkis简单版(0.9.1及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) +Linkis简单版(0.9.3及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) @@ -251,7 +251,7 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/ ## 四、标准版DSS环境配置准备 标准版DSS环境准备也分为三部分,前后端基础软件安装、后端环境准备和前端环境准备,详细介绍如下: ### 4.1 前后端基础软件安装 -Linkis简单版(0.9.1及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) +Linkis简单版(0.9.3及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) diff --git a/dss-appjoint-auth/pom.xml b/dss-appjoint-auth/pom.xml index 04144de5c..595ad36f0 100644 --- a/dss-appjoint-auth/pom.xml +++ b/dss-appjoint-auth/pom.xml @@ -33,6 +33,11 @@ linkis-gateway-httpclient-support ${linkis.version} + + com.webank.wedatasphere.linkis + linkis-common + ${linkis.version} + diff --git a/dss-flow-execution-entrance/pom.xml b/dss-flow-execution-entrance/pom.xml index 12218e310..97d12b24b 100644 --- a/dss-flow-execution-entrance/pom.xml +++ b/dss-flow-execution-entrance/pom.xml @@ -33,12 +33,28 @@ com.webank.wedatasphere.linkis linkis-ujes-entrance ${linkis.version} + + + org.apache.poi + ooxml-schemas + + + + + com.webank.wedatasphere.linkis + linkis-cloudRPC + ${linkis.version} - com.webank.wedatasphere.dss dss-linkis-node-execution ${dss.version} + + + com.ibm.icu + icu4j + + diff --git a/dss-flow-execution-entrance/src/main/assembly/distribution.xml b/dss-flow-execution-entrance/src/main/assembly/distribution.xml index c080c0c09..d59e84970 100644 --- a/dss-flow-execution-entrance/src/main/assembly/distribution.xml +++ b/dss-flow-execution-entrance/src/main/assembly/distribution.xml @@ -84,7 +84,6 @@ com.google.code.gson:gson:jar com.google.guava:guava:jar com.google.inject:guice:jar - com.google.protobuf:protobuf-java:jar com.netflix.archaius:archaius-core:jar com.netflix.eureka:eureka-client:jar com.netflix.eureka:eureka-core:jar @@ -100,7 +99,6 @@ com.netflix.ribbon:ribbon-loadbalancer:jar com.netflix.ribbon:ribbon-transport:jar com.netflix.servo:servo-core:jar - com.ning:async-http-client:jar com.sun.jersey.contribs:jersey-apache-client4:jar com.sun.jersey:jersey-client:jar com.sun.jersey:jersey-core:jar @@ -113,15 +111,10 @@ com.webank.wedatasphere.linkis:linkis-common:jar com.webank.wedatasphere.linkis:linkis-module:jar commons-beanutils:commons-beanutils:jar - commons-beanutils:commons-beanutils-core:jar - commons-cli:commons-cli:jar commons-codec:commons-codec:jar commons-collections:commons-collections:jar commons-configuration:commons-configuration:jar - commons-daemon:commons-daemon:jar commons-dbcp:commons-dbcp:jar - commons-digester:commons-digester:jar - commons-httpclient:commons-httpclient:jar commons-io:commons-io:jar commons-jxpath:commons-jxpath:jar commons-lang:commons-lang:jar @@ -129,7 +122,6 @@ commons-net:commons-net:jar commons-pool:commons-pool:jar io.micrometer:micrometer-core:jar - io.netty:netty:jar io.netty:netty-all:jar io.netty:netty-buffer:jar io.netty:netty-codec:jar @@ -146,41 +138,21 @@ javax.annotation:javax.annotation-api:jar javax.inject:javax.inject:jar javax.servlet:javax.servlet-api:jar - javax.servlet.jsp:jsp-api:jar javax.validation:validation-api:jar javax.websocket:javax.websocket-api:jar javax.ws.rs:javax.ws.rs-api:jar javax.xml.bind:jaxb-api:jar javax.xml.stream:stax-api:jar joda-time:joda-time:jar - log4j:log4j:jar mysql:mysql-connector-java:jar - net.databinder.dispatch:dispatch-core_2.11:jar - net.databinder.dispatch:dispatch-json4s-jackson_2.11:jar org.antlr:antlr-runtime:jar org.antlr:stringtemplate:jar - org.apache.commons:commons-compress:jar org.apache.commons:commons-math:jar - org.apache.commons:commons-math3:jar - org.apache.curator:curator-client:jar - org.apache.curator:curator-framework:jar - org.apache.curator:curator-recipes:jar - org.apache.directory.api:api-asn1-api:jar - org.apache.directory.api:api-util:jar - org.apache.directory.server:apacheds-i18n:jar - org.apache.directory.server:apacheds-kerberos-codec:jar - org.apache.hadoop:hadoop-annotations:jar - org.apache.hadoop:hadoop-auth:jar - org.apache.hadoop:hadoop-common:jar - org.apache.hadoop:hadoop-hdfs:jar - org.apache.htrace:htrace-core:jar org.apache.httpcomponents:httpclient:jar - org.apache.httpcomponents:httpcore:jar org.apache.logging.log4j:log4j-api:jar org.apache.logging.log4j:log4j-core:jar org.apache.logging.log4j:log4j-jul:jar org.apache.logging.log4j:log4j-slf4j-impl:jar - org.apache.zookeeper:zookeeper:jar org.aspectj:aspectjweaver:jar org.bouncycastle:bcpkix-jdk15on:jar org.bouncycastle:bcprov-jdk15on:jar @@ -194,7 +166,6 @@ org.eclipse.jetty:jetty-continuation:jar org.eclipse.jetty:jetty-http:jar org.eclipse.jetty:jetty-io:jar - org.eclipse.jetty:jetty-jndi:jar org.eclipse.jetty:jetty-plus:jar org.eclipse.jetty:jetty-security:jar org.eclipse.jetty:jetty-server:jar @@ -210,7 +181,6 @@ org.eclipse.jetty.websocket:websocket-common:jar org.eclipse.jetty.websocket:websocket-server:jar org.eclipse.jetty.websocket:websocket-servlet:jar - org.fusesource.leveldbjni:leveldbjni-all:jar org.glassfish.hk2:class-model:jar org.glassfish.hk2:config-types:jar org.glassfish.hk2.external:aopalliance-repackaged:jar @@ -243,13 +213,10 @@ org.json4s:json4s-ast_2.11:jar org.json4s:json4s-core_2.11:jar org.json4s:json4s-jackson_2.11:jar - org.jsoup:jsoup:jar org.jvnet.mimepull:mimepull:jar org.jvnet:tiger-types:jar org.latencyutils:LatencyUtils:jar org.mortbay.jasper:apache-el:jar - org.mortbay.jetty:jetty:jar - org.mortbay.jetty:jetty-util:jar org.ow2.asm:asm-analysis:jar org.ow2.asm:asm-commons:jar org.ow2.asm:asm-tree:jar @@ -296,11 +263,8 @@ org.springframework:spring-jcl:jar org.springframework:spring-web:jar org.springframework:spring-webmvc:jar - org.tukaani:xz:jar org.yaml:snakeyaml:jar software.amazon.ion:ion-java:jar - xerces:xercesImpl:jar - xmlenc:xmlenc:jar xmlpull:xmlpull:jar xpp3:xpp3_min:jar diff --git a/dss-flow-execution-entrance/src/main/java/com/webank/wedatasphere/dss/flow/execution/entrance/job/FlowExecutionAppJointSignalSharedJob.java b/dss-flow-execution-entrance/src/main/java/com/webank/wedatasphere/dss/flow/execution/entrance/job/FlowExecutionAppJointSignalSharedJob.java index 8d0735e58..6cfcf877b 100644 --- a/dss-flow-execution-entrance/src/main/java/com/webank/wedatasphere/dss/flow/execution/entrance/job/FlowExecutionAppJointSignalSharedJob.java +++ b/dss-flow-execution-entrance/src/main/java/com/webank/wedatasphere/dss/flow/execution/entrance/job/FlowExecutionAppJointSignalSharedJob.java @@ -19,15 +19,27 @@ package com.webank.wedatasphere.dss.flow.execution.entrance.job; import com.webank.wedatasphere.dss.common.entity.node.DWSNode; import com.webank.wedatasphere.dss.flow.execution.entrance.conf.FlowExecutionEntranceConfiguration; +import com.webank.wedatasphere.dss.linkis.node.execution.job.JobSignalKeyCreator; import com.webank.wedatasphere.dss.linkis.node.execution.job.SignalSharedJob; import java.util.Map; /** - * Created by peacewong on 2019/11/14. + * Created by johnnwang on 2019/11/14. */ -public class FlowExecutionAppJointSignalSharedJob extends FlowExecutionAppJointLinkisSharedJob implements SignalSharedJob { +public class FlowExecutionAppJointSignalSharedJob extends FlowExecutionAppJointLinkisJob implements SignalSharedJob { + private JobSignalKeyCreator signalKeyCreator; + + @Override + public JobSignalKeyCreator getSignalKeyCreator() { + return this.signalKeyCreator; + } + + @Override + public void setSignalKeyCreator(JobSignalKeyCreator signalKeyCreator) { + this.signalKeyCreator = signalKeyCreator; + } @Override public String getMsgSaveKey() { diff --git a/dss-flow-execution-entrance/src/main/java/com/webank/wedatasphere/dss/flow/execution/entrance/job/FlowExecutionJobSignalKeyCreator.java b/dss-flow-execution-entrance/src/main/java/com/webank/wedatasphere/dss/flow/execution/entrance/job/FlowExecutionJobSignalKeyCreator.java new file mode 100644 index 000000000..e284b44d8 --- /dev/null +++ b/dss-flow-execution-entrance/src/main/java/com/webank/wedatasphere/dss/flow/execution/entrance/job/FlowExecutionJobSignalKeyCreator.java @@ -0,0 +1,39 @@ +/* + * Copyright 2019 WeBank + * + * 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.webank.wedatasphere.dss.flow.execution.entrance.job; + +import com.webank.wedatasphere.dss.flow.execution.entrance.conf.FlowExecutionEntranceConfiguration; +import com.webank.wedatasphere.dss.linkis.node.execution.job.Job; +import com.webank.wedatasphere.dss.linkis.node.execution.job.JobSignalKeyCreator; +import com.webank.wedatasphere.dss.linkis.node.execution.job.SignalSharedJob; + +public class FlowExecutionJobSignalKeyCreator implements JobSignalKeyCreator { + + @Override + public String getSignalKeyByJob(Job job) { + String projectId = job.getJobProps().get(FlowExecutionEntranceConfiguration.PROJECT_NAME()); + String flowId = job.getJobProps().get(FlowExecutionEntranceConfiguration.FLOW_NAME()); + String flowExecId = job.getJobProps().get(FlowExecutionEntranceConfiguration.FLOW_EXEC_ID()); + return projectId + "." + flowId + "." + flowExecId; + } + + @Override + public String getSignalKeyBySignalSharedJob(SignalSharedJob job) { + return getSignalKeyByJob((Job)job); + } +} diff --git a/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/conf/FlowExecutionEntranceConfiguration.scala b/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/conf/FlowExecutionEntranceConfiguration.scala index 91cdeedd6..245a23687 100644 --- a/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/conf/FlowExecutionEntranceConfiguration.scala +++ b/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/conf/FlowExecutionEntranceConfiguration.scala @@ -44,9 +44,10 @@ object FlowExecutionEntranceConfiguration { val NODE_STATUS_POLLER_THREAD_SIZE = CommonVars("wds.dds.flow.node.status.poller.thread.size", 20) - val NODE_STATUS_POLLER_SCHEDULER_TIME = CommonVars("wds.dds.flow.node.status.poller.scheduler.time", 2) + val NODE_STATUS_POLLER_SCHEDULER_TIME = CommonVars("wds.dds.flow.node.status.poller.scheduler.time", 5) val FLOW_EXECUTION_SCHEDULER_POOL_SIZE = CommonVars("wds.linkis.flow.execution.pool.size", 30) + val NODE_STATUS_INTERVAL = CommonVars("wds.dds.flow.node.status.poller.interval.time", 3000) val COMMAND = "command" diff --git a/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/execution/DefaultFlowExecution.scala b/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/execution/DefaultFlowExecution.scala index 04b56936e..d5a9cbf79 100644 --- a/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/execution/DefaultFlowExecution.scala +++ b/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/execution/DefaultFlowExecution.scala @@ -16,7 +16,7 @@ */ package com.webank.wedatasphere.dss.flow.execution.entrance.execution -import java.util + import java.util.concurrent.{Executors, LinkedBlockingQueue, TimeUnit} import com.webank.wedatasphere.dss.flow.execution.entrance.conf.FlowExecutionEntranceConfiguration @@ -31,13 +31,11 @@ import scala.collection.mutable.ArrayBuffer /** - * Created by peacewong on 2019/11/5. - */ + * Created by johnnwang on 2019/11/5. + */ @Service class DefaultFlowExecution extends FlowExecution with Logging { - private val executeService = Utils.newCachedThreadPool(FlowExecutionEntranceConfiguration.FLOW_EXECUTION_POOL_SIZE.getValue, - "DefaultFlowExecution",true) private val nodeRunnerQueue: LinkedBlockingQueue[NodeRunner] = new LinkedBlockingQueue[NodeRunner]() @@ -74,6 +72,7 @@ class DefaultFlowExecution extends FlowExecution with Logging { if (pollerCount < FlowExecutionEntranceConfiguration.NODE_STATUS_POLLER_THREAD_SIZE.getValue){ scheduledThreadPool.scheduleAtFixedRate(new NodeExecutionStatusPoller(nodeRunnerQueue), 1, FlowExecutionEntranceConfiguration.NODE_STATUS_POLLER_SCHEDULER_TIME.getValue ,TimeUnit.SECONDS) + pollerCount = pollerCount + 1 } } } diff --git a/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/job/parser/FlowJobNodeParser.scala b/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/job/parser/FlowJobNodeParser.scala index 158a8aebd..6447e45eb 100644 --- a/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/job/parser/FlowJobNodeParser.scala +++ b/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/job/parser/FlowJobNodeParser.scala @@ -19,6 +19,7 @@ package com.webank.wedatasphere.dss.flow.execution.entrance.job.parser import java.util +import com.webank.wedatasphere.dss.flow.execution.entrance.conf.FlowExecutionEntranceConfiguration import com.webank.wedatasphere.dss.flow.execution.entrance.conf.FlowExecutionEntranceConfiguration._ import com.webank.wedatasphere.dss.flow.execution.entrance.exception.FlowExecutionErrorException import com.webank.wedatasphere.dss.flow.execution.entrance.job.FlowEntranceJob @@ -34,8 +35,8 @@ import org.springframework.core.annotation.Order import org.springframework.stereotype.Component /** - * Created by peacewong on 2019/11/6. - */ + * Created by johnnwang on 2019/11/6. + */ @Order(2) @Component @@ -76,6 +77,8 @@ class FlowJobNodeParser extends FlowEntranceJobParser with Logging{ } } + propsMap.put(FlowExecutionEntranceConfiguration.FLOW_EXEC_ID, flowEntranceJob.getId) + params.put(PROPS_MAP, propsMap) params.put(FLOW_VAR_MAP, flowVar) params.put(PROJECT_RESOURCES, project.getProjectResources) diff --git a/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/AppJointJobBuilder.scala b/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/AppJointJobBuilder.scala index 02505695a..440e6a4aa 100644 --- a/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/AppJointJobBuilder.scala +++ b/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/AppJointJobBuilder.scala @@ -26,13 +26,28 @@ import com.webank.wedatasphere.dss.flow.execution.entrance.job._ import com.webank.wedatasphere.dss.flow.execution.entrance.utils.FlowExecutionUtils import com.webank.wedatasphere.dss.linkis.node.execution.conf.LinkisJobExecutionConfiguration import com.webank.wedatasphere.dss.linkis.node.execution.entity.BMLResource +import com.webank.wedatasphere.dss.linkis.node.execution.execution.impl.LinkisNodeExecutionImpl import com.webank.wedatasphere.dss.linkis.node.execution.job._ +import com.webank.wedatasphere.dss.linkis.node.execution.parser.JobParamsParser import org.apache.commons.lang.StringUtils /** - * Created by peacewong on 2019/11/5. - */ + * Created by johnnwang on 2019/11/5. + */ object AppJointJobBuilder { + + val signalKeyCreator = new FlowExecutionJobSignalKeyCreator + + init() + + def init(): Unit ={ + val jobParamsParser = new JobParamsParser + + jobParamsParser.setSignalKeyCreator(signalKeyCreator) + + LinkisNodeExecutionImpl.getLinkisNodeExecution.asInstanceOf[LinkisNodeExecutionImpl].registerJobParser(jobParamsParser) + } + def builder():FlowBuilder = new FlowBuilder class FlowBuilder extends Builder { @@ -95,9 +110,10 @@ object AppJointJobBuilder { override protected def createSignalSharedJob(isLinkisType: Boolean): SignalSharedJob = { if(isLinkisType){ - null + null } else { val signalJob = new FlowExecutionAppJointSignalSharedJob + signalJob.setSignalKeyCreator(signalKeyCreator) signalJob.setJobProps(this.jobProps) signalJob } diff --git a/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/DefaultNodeRunner.scala b/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/DefaultNodeRunner.scala index a9462dda8..89ddc910a 100644 --- a/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/DefaultNodeRunner.scala +++ b/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/DefaultNodeRunner.scala @@ -27,11 +27,12 @@ import com.webank.wedatasphere.dss.flow.execution.entrance.log.FlowExecutionLog import com.webank.wedatasphere.dss.flow.execution.entrance.node.NodeExecutionState.NodeExecutionState import com.webank.wedatasphere.dss.linkis.node.execution.execution.impl.LinkisNodeExecutionImpl import com.webank.wedatasphere.dss.linkis.node.execution.listener.LinkisExecutionListener +import com.webank.wedatasphere.linkis.common.exception.ErrorException import com.webank.wedatasphere.linkis.common.utils.{Logging, Utils} /** - * Created by peacewong on 2019/11/5. - */ + * Created by johnnwang on 2019/11/5. + */ class DefaultNodeRunner extends NodeRunner with Logging { private var node: SchedulerNode = _ @@ -48,6 +49,8 @@ class DefaultNodeRunner extends NodeRunner with Logging { private var startTime: Long = _ + private var lastGetStatusTime: Long = 0 + override def getNode: SchedulerNode = this.node def setNode(schedulerNode: SchedulerNode): Unit = { @@ -64,6 +67,15 @@ class DefaultNodeRunner extends NodeRunner with Logging { } override def isLinkisJobCompleted: Boolean = Utils.tryCatch{ + + val interval = System.currentTimeMillis() - lastGetStatusTime + + if ( interval < FlowExecutionEntranceConfiguration.NODE_STATUS_INTERVAL.getValue){ + return false + } + + lastGetStatusTime = System.currentTimeMillis() + if(NodeExecutionState.isCompleted(getStatus)) return true val toState = NodeExecutionState.withName(LinkisNodeExecutionImpl.getLinkisNodeExecution.getState(this.linkisJob)) if (NodeExecutionState.isCompleted(toState)) { @@ -75,9 +87,11 @@ class DefaultNodeRunner extends NodeRunner with Logging { } else { false } - }{ t => - warn(s"Failed to get ${this.node.getName} linkis job states", t) - false + }{ + case e:ErrorException => logger.warn(s"failed to get ${this.node.getName} state", e) + false + case t :Throwable => logger.error(s"failed to get ${this.node.getName} state", t) + true } override def setNodeRunnerListener(nodeRunnerListener: NodeRunnerListener): Unit = this.nodeRunnerListener = nodeRunnerListener @@ -102,7 +116,7 @@ class DefaultNodeRunner extends NodeRunner with Logging { } LinkisNodeExecutionImpl.getLinkisNodeExecution.runJob(this.linkisJob) - info(s"Finished to run node of ${node.getName}") + info(s"start to run node of ${node.getName}") /*LinkisNodeExecutionImpl.getLinkisNodeExecution.waitForComplete(this.linkisJob) val listener = LinkisNodeExecutionImpl.getLinkisNodeExecution.asInstanceOf[LinkisExecutionListener] val toState = LinkisNodeExecutionImpl.getLinkisNodeExecution.getState(this.linkisJob) diff --git a/dss-linkis-node-execution/pom.xml b/dss-linkis-node-execution/pom.xml index ecea3e8bf..b98c33987 100644 --- a/dss-linkis-node-execution/pom.xml +++ b/dss-linkis-node-execution/pom.xml @@ -33,13 +33,13 @@ com.webank.wedatasphere.linkis linkis-ujes-client - 0.9.1 + 0.9.3 com.webank.wedatasphere.linkis linkis-workspace-httpclient - 0.9.1 + 0.9.3 diff --git a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/WorkflowContextImpl.java b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/WorkflowContextImpl.java index e92881356..8f2ff84fa 100644 --- a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/WorkflowContextImpl.java +++ b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/WorkflowContextImpl.java @@ -21,12 +21,13 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.webank.wedatasphere.dss.linkis.node.execution.conf.LinkisJobExecutionConfiguration; import com.webank.wedatasphere.dss.linkis.node.execution.entity.ContextInfo; +import org.apache.commons.lang.StringUtils; import java.util.*; import java.util.concurrent.TimeUnit; /** - * Created by peacewong on 2019/9/26. + * Created by johnnwang on 2019/9/26. */ public class WorkflowContextImpl implements WorkflowContext { @@ -79,7 +80,7 @@ public class WorkflowContextImpl implements WorkflowContext { while (keys.hasNext()) { String key = keys.next(); if (key.startsWith(keyPrefix)) { - map.put(key, getValue(key)); + map.put(StringUtils.substringAfter(key, keyPrefix), getValue(key)); } } return map; diff --git a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/conf/LinkisJobExecutionConfiguration.java b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/conf/LinkisJobExecutionConfiguration.java index 852262bb5..9b75d73a0 100644 --- a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/conf/LinkisJobExecutionConfiguration.java +++ b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/conf/LinkisJobExecutionConfiguration.java @@ -68,7 +68,7 @@ public class LinkisJobExecutionConfiguration { public final static CommonVars LINKIS_CONNECTION_TIMEOUT = CommonVars.apply("wds.linkis.flow.connection.timeout",30000); - public final static CommonVars LINKIS_JOB_REQUEST_STATUS_TIME = CommonVars.apply("wds.linkis.flow.connection.timeout",1000); + public final static CommonVars LINKIS_JOB_REQUEST_STATUS_TIME = CommonVars.apply("wds.linkis.flow.connection.timeout",3000); public final static CommonVars LINKIS_ADMIN_USER = CommonVars.apply("wds.linkis.client.flow.adminuser","ws"); diff --git a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/execution/impl/LinkisNodeExecutionImpl.java b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/execution/impl/LinkisNodeExecutionImpl.java index 635ce6ac0..264e8288c 100644 --- a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/execution/impl/LinkisNodeExecutionImpl.java +++ b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/execution/impl/LinkisNodeExecutionImpl.java @@ -23,7 +23,6 @@ import com.webank.wedatasphere.dss.linkis.node.execution.execution.LinkisNodeExe import com.webank.wedatasphere.dss.linkis.node.execution.job.SharedJob; import com.webank.wedatasphere.dss.linkis.node.execution.job.SignalSharedJob; import com.webank.wedatasphere.dss.linkis.node.execution.listener.LinkisExecutionListener; -import com.webank.wedatasphere.dss.linkis.node.execution.parser.JobParamsParser; import com.webank.wedatasphere.dss.linkis.node.execution.parser.JobRuntimeParamsParser; import com.webank.wedatasphere.dss.linkis.node.execution.service.impl.BuildJobActionImpl; import com.webank.wedatasphere.dss.linkis.node.execution.conf.LinkisJobExecutionConfiguration; @@ -51,7 +50,7 @@ public class LinkisNodeExecutionImpl implements LinkisNodeExecution , LinkisExec private LinkisNodeExecutionImpl() { registerJobParser(new CodeParser()); - registerJobParser(new JobParamsParser()); + /*registerJobParser(new JobParamsParser());*/ registerJobParser(new JobRuntimeParamsParser()); } @@ -107,7 +106,7 @@ public class LinkisNodeExecutionImpl implements LinkisNodeExecution , LinkisExec job.getLogFromLine(), LinkisJobExecutionConfiguration.LOG_SIZE.getValue()); - job.setLogFromLint(jobLogResult.fromLine()); + job.setLogFromLine(jobLogResult.fromLine()); ArrayList logArray = jobLogResult.getLog(); @@ -191,12 +190,7 @@ public class LinkisNodeExecutionImpl implements LinkisNodeExecution , LinkisExec if (job instanceof SignalSharedJob){ SignalSharedJob signalSharedJob = (SignalSharedJob) job; String result = getResult(job, 0, -1); - String msgSaveKey = signalSharedJob.getMsgSaveKey(); - String key = SignalSharedJob.PREFIX ; - if (StringUtils.isNotEmpty(msgSaveKey)){ - key = key + msgSaveKey; - } - WorkflowContext.getAppJointContext().setValue(key, result , -1); + WorkflowContext.getAppJointContext().setValue(signalSharedJob.getSharedKey(), result , -1); } else if(job instanceof SharedJob){ String taskId = job.getJobExecuteResult().getTaskID(); job.getLogObj().info("Set shared info:" + taskId); diff --git a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/AbstractAppJointLinkisJob.java b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/AbstractAppJointLinkisJob.java index 1bce73c8a..7d9e47f06 100644 --- a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/AbstractAppJointLinkisJob.java +++ b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/AbstractAppJointLinkisJob.java @@ -146,7 +146,7 @@ public abstract class AbstractAppJointLinkisJob extends AppJointLinkisJob { } @Override - public void setLogFromLint(int index) { + public void setLogFromLine(int index) { this.logFromLine = index; } diff --git a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/AbstractCommonLinkisJob.java b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/AbstractCommonLinkisJob.java index 2d836eaac..c7f74f234 100644 --- a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/AbstractCommonLinkisJob.java +++ b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/AbstractCommonLinkisJob.java @@ -154,7 +154,7 @@ public abstract class AbstractCommonLinkisJob extends CommonLinkisJob { } @Override - public void setLogFromLint(int index) { + public void setLogFromLine(int index) { this.logFromLine = index; } diff --git a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/Job.java b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/Job.java index ac25c724b..1811ad105 100644 --- a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/Job.java +++ b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/Job.java @@ -63,6 +63,6 @@ public interface Job { int getLogFromLine(); - void setLogFromLint(int index); + void setLogFromLine(int index); } diff --git a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/JobSignalKeyCreator.java b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/JobSignalKeyCreator.java new file mode 100644 index 000000000..ce64bf901 --- /dev/null +++ b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/JobSignalKeyCreator.java @@ -0,0 +1,25 @@ +/* + * Copyright 2019 WeBank + * + * 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.webank.wedatasphere.dss.linkis.node.execution.job; + +public interface JobSignalKeyCreator { + + String getSignalKeyByJob(Job job); + + String getSignalKeyBySignalSharedJob(SignalSharedJob job); +} diff --git a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/SignalSharedJob.java b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/SignalSharedJob.java index a71a12555..13a9b8b44 100644 --- a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/SignalSharedJob.java +++ b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/job/SignalSharedJob.java @@ -24,6 +24,10 @@ public interface SignalSharedJob extends SharedJob { String PREFIX = "signal."; + JobSignalKeyCreator getSignalKeyCreator(); + + void setSignalKeyCreator(JobSignalKeyCreator signalKeyCreator); + @Override default int getSharedNum() { return -1; @@ -31,7 +35,7 @@ public interface SignalSharedJob extends SharedJob { @Override default String getSharedKey() { - return PREFIX + getMsgSaveKey(); + return PREFIX + getSignalKeyCreator().getSignalKeyBySignalSharedJob(this) + "." + getMsgSaveKey(); } String getMsgSaveKey(); diff --git a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/parser/JobParamsParser.java b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/parser/JobParamsParser.java index fca769d8a..5c9e013c6 100644 --- a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/parser/JobParamsParser.java +++ b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/parser/JobParamsParser.java @@ -19,19 +19,31 @@ package com.webank.wedatasphere.dss.linkis.node.execution.parser; import com.google.gson.reflect.TypeToken; import com.webank.wedatasphere.dss.linkis.node.execution.WorkflowContext; +import com.webank.wedatasphere.dss.linkis.node.execution.job.JobSignalKeyCreator; import com.webank.wedatasphere.dss.linkis.node.execution.job.LinkisJob; import com.webank.wedatasphere.dss.linkis.node.execution.job.Job; import com.webank.wedatasphere.dss.linkis.node.execution.job.SignalSharedJob; import com.webank.wedatasphere.dss.linkis.node.execution.utils.LinkisJobExecutionUtils; +import java.util.Collection; import java.util.List; import java.util.Map; /** - * Created by peacewong on 2019/11/3. + * Created by johnnwang on 2019/11/3. */ public class JobParamsParser implements JobParser { + private JobSignalKeyCreator signalKeyCreator; + + public JobSignalKeyCreator getSignalKeyCreator() { + return signalKeyCreator; + } + + public void setSignalKeyCreator(JobSignalKeyCreator signalKeyCreator) { + this.signalKeyCreator = signalKeyCreator; + } + @Override public void parseJob(Job job) throws Exception { @@ -44,11 +56,15 @@ public class JobParamsParser implements JobParser { Map flowVariables = linkisJob.getVariables(); putParamsMap(job.getParams(), "variable", flowVariables); //put signal info - Map sharedValue = WorkflowContext.getAppJointContext().getSubMapByPrefix(SignalSharedJob.PREFIX); + Map sharedValue = WorkflowContext.getAppJointContext() + .getSubMapByPrefix(SignalSharedJob.PREFIX + this.getSignalKeyCreator().getSignalKeyByJob(job)); if (sharedValue != null) { - putParamsMap(job.getParams(), "variable", sharedValue); + Collection values = sharedValue.values(); + for(Object value : values){ + Map variableMap = LinkisJobExecutionUtils.gson.fromJson(value.toString(), new TypeToken>() {}.getType()); + putParamsMap(job.getParams(), "variable", variableMap); + } } - // put configuration Map configuration = linkisJob.getConfiguration(); putParamsMap(job.getParams(), "configuration", configuration); diff --git a/dss-scheduler-appjoint-core/pom.xml b/dss-scheduler-appjoint-core/pom.xml index 1eaba100f..b09213fc8 100644 --- a/dss-scheduler-appjoint-core/pom.xml +++ b/dss-scheduler-appjoint-core/pom.xml @@ -48,6 +48,11 @@ ${dss.version} + + com.google.code.gson + gson + 2.8.5 + diff --git a/dss-server/pom.xml b/dss-server/pom.xml index f42dbb0a4..b0627677b 100644 --- a/dss-server/pom.xml +++ b/dss-server/pom.xml @@ -117,7 +117,7 @@ com.webank.wedatasphere.linkis - 0.9.1 + 0.9.3 diff --git a/dss-server/src/main/assembly/distribution.xml b/dss-server/src/main/assembly/distribution.xml index ffa6656d8..560fc34e3 100644 --- a/dss-server/src/main/assembly/distribution.xml +++ b/dss-server/src/main/assembly/distribution.xml @@ -176,7 +176,9 @@ org.eclipse.jetty:jetty-continuation:jar org.eclipse.jetty:jetty-http:jar org.eclipse.jetty:jetty-io:jar + org.eclipse.jetty:jetty-plus:jar org.eclipse.jetty:jetty-security:jar org.eclipse.jetty:jetty-server:jar @@ -225,7 +227,9 @@ org.json4s:json4s-ast_2.11:jar org.json4s:json4s-core_2.11:jar org.json4s:json4s-jackson_2.11:jar + org.jvnet.mimepull:mimepull:jar org.jvnet:tiger-types:jar org.latencyutils:LatencyUtils:jar diff --git a/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanAppJointSignalSharedJob.java b/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanAppJointSignalSharedJob.java index 01ebbf0b6..a24adcb69 100644 --- a/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanAppJointSignalSharedJob.java +++ b/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanAppJointSignalSharedJob.java @@ -17,17 +17,30 @@ package com.webank.wedatasphere.dss.plugins.azkaban.linkis.jobtype.job; +import com.webank.wedatasphere.dss.linkis.node.execution.job.JobSignalKeyCreator; import com.webank.wedatasphere.dss.linkis.node.execution.job.SignalSharedJob; import com.webank.wedatasphere.dss.plugins.azkaban.linkis.jobtype.conf.LinkisJobTypeConf; import java.util.Map; /** - * Created by peacewong on 2019/11/14. + * Created by johnnwang on 2019/11/14. */ -public class AzkabanAppJointSignalSharedJob extends AzkabanAppJointLinkisSharedJob implements SignalSharedJob { +public class AzkabanAppJointSignalSharedJob extends AzkabanAppJointLinkisJob implements SignalSharedJob { + private JobSignalKeyCreator signalKeyCreator; + + @Override + public JobSignalKeyCreator getSignalKeyCreator() { + return this.signalKeyCreator; + } + + @Override + public void setSignalKeyCreator(JobSignalKeyCreator signalKeyCreator) { + this.signalKeyCreator = signalKeyCreator; + } + @Override public String getMsgSaveKey() { Map configuration = this.getConfiguration(); diff --git a/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanJobSignalKeyCreator.java b/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanJobSignalKeyCreator.java new file mode 100644 index 000000000..30c6a6415 --- /dev/null +++ b/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkabanJobSignalKeyCreator.java @@ -0,0 +1,39 @@ +/* + * Copyright 2019 WeBank + * + * 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.webank.wedatasphere.dss.plugins.azkaban.linkis.jobtype.job; + +import com.webank.wedatasphere.dss.linkis.node.execution.job.Job; +import com.webank.wedatasphere.dss.linkis.node.execution.job.JobSignalKeyCreator; +import com.webank.wedatasphere.dss.linkis.node.execution.job.SignalSharedJob; +import com.webank.wedatasphere.dss.plugins.azkaban.linkis.jobtype.conf.LinkisJobTypeConf; + +public class AzkabanJobSignalKeyCreator implements JobSignalKeyCreator { + + @Override + public String getSignalKeyByJob(Job job) { + String projectId = job.getJobProps().get(LinkisJobTypeConf.PROJECT_ID); + String flowId = job.getJobProps().get(LinkisJobTypeConf.FLOW_NAME); + String flowExecId = job.getJobProps().get(LinkisJobTypeConf.FLOW_EXEC_ID); + return projectId + "." + flowId + "." + flowExecId ; + } + + @Override + public String getSignalKeyBySignalSharedJob(SignalSharedJob job) { + return getSignalKeyByJob((Job)job); + } +} diff --git a/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkanbanBuilder.java b/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkanbanBuilder.java index bcd88097b..c38fac244 100644 --- a/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkanbanBuilder.java +++ b/plugins/azkaban/linkis-jobtype/src/main/java/com/webank/wedatasphere/dss/plugins/azkaban/linkis/jobtype/job/AzkanbanBuilder.java @@ -20,7 +20,10 @@ package com.webank.wedatasphere.dss.plugins.azkaban.linkis.jobtype.job; import com.webank.wedatasphere.dss.linkis.node.execution.conf.LinkisJobExecutionConfiguration; import com.webank.wedatasphere.dss.linkis.node.execution.entity.BMLResource; import com.webank.wedatasphere.dss.linkis.node.execution.exception.LinkisJobExecutionErrorException; +import com.webank.wedatasphere.dss.linkis.node.execution.execution.LinkisNodeExecution; +import com.webank.wedatasphere.dss.linkis.node.execution.execution.impl.LinkisNodeExecutionImpl; import com.webank.wedatasphere.dss.linkis.node.execution.job.*; +import com.webank.wedatasphere.dss.linkis.node.execution.parser.JobParamsParser; import com.webank.wedatasphere.dss.linkis.node.execution.utils.LinkisJobExecutionUtils; import com.webank.wedatasphere.dss.plugins.azkaban.linkis.jobtype.conf.LinkisJobTypeConf; import com.webank.wedatasphere.dss.plugins.azkaban.linkis.jobtype.utils.LinkisJobTypeUtils; @@ -29,17 +32,29 @@ import org.apache.commons.lang.StringUtils; import java.util.*; /** - * Created by peacewong on 2019/11/3. + * Created by johnnwang on 2019/11/3. */ public class AzkanbanBuilder extends Builder{ private Map jobProps; + private JobSignalKeyCreator jobSignalKeyCreator = new AzkabanJobSignalKeyCreator(); + public AzkanbanBuilder setJobProps(Map jobProps) { this.jobProps = jobProps; return this; } + { + init(); + } + + private void init(){ + JobParamsParser jobParamsParser = new JobParamsParser(); + jobParamsParser.setSignalKeyCreator(jobSignalKeyCreator); + LinkisNodeExecutionImpl linkisNodeExecution = (LinkisNodeExecutionImpl)LinkisNodeExecutionImpl.getLinkisNodeExecution(); + linkisNodeExecution.registerJobParser(jobParamsParser); + } @Override protected String getJobType() { @@ -99,6 +114,7 @@ public class AzkanbanBuilder extends Builder{ return null; } else { AzkabanAppJointSignalSharedJob signalSharedJob = new AzkabanAppJointSignalSharedJob(); + signalSharedJob.setSignalKeyCreator(jobSignalKeyCreator); signalSharedJob.setJobProps(this.jobProps); return signalSharedJob; } diff --git a/plugins/linkis/linkis-appjoint-entrance/pom.xml b/plugins/linkis/linkis-appjoint-entrance/pom.xml index 26b80a750..0651c396e 100644 --- a/plugins/linkis/linkis-appjoint-entrance/pom.xml +++ b/plugins/linkis/linkis-appjoint-entrance/pom.xml @@ -54,8 +54,21 @@ - - + + com.webank.wedatasphere.linkis + linkis-cloudRPC + ${linkis.version} + + + com.webank.wedatasphere.linkis + linkis-storage + ${linkis.version} + + + com.webank.wedatasphere.linkis + linkis-httpclient + ${linkis.version} + diff --git a/plugins/linkis/linkis-appjoint-entrance/src/main/assembly/distribution.xml b/plugins/linkis/linkis-appjoint-entrance/src/main/assembly/distribution.xml index d4a200502..83c6ee1a0 100644 --- a/plugins/linkis/linkis-appjoint-entrance/src/main/assembly/distribution.xml +++ b/plugins/linkis/linkis-appjoint-entrance/src/main/assembly/distribution.xml @@ -84,7 +84,7 @@ com.google.code.gson:gson:jar com.google.guava:guava:jar com.google.inject:guice:jar - com.google.protobuf:protobuf-java:jar + com.netflix.archaius:archaius-core:jar com.netflix.eureka:eureka-client:jar com.netflix.eureka:eureka-core:jar @@ -100,7 +100,6 @@ com.netflix.ribbon:ribbon-loadbalancer:jar com.netflix.ribbon:ribbon-transport:jar com.netflix.servo:servo-core:jar - com.ning:async-http-client:jar com.sun.jersey.contribs:jersey-apache-client4:jar com.sun.jersey:jersey-client:jar com.sun.jersey:jersey-core:jar @@ -112,15 +111,15 @@ com.thoughtworks.xstream:xstream:jar com.webank.wedatasphere.linkis:linkis-common:jar com.webank.wedatasphere.linkis:linkis-module:jar - commons-beanutils:commons-beanutils:jar - commons-beanutils:commons-beanutils-core:jar - commons-cli:commons-cli:jar - commons-codec:commons-codec:jar - commons-collections:commons-collections:jar - commons-configuration:commons-configuration:jar - commons-daemon:commons-daemon:jar - commons-dbcp:commons-dbcp:jar - commons-digester:commons-digester:jar + + + + + + + + + commons-httpclient:commons-httpclient:jar commons-io:commons-io:jar commons-jxpath:commons-jxpath:jar @@ -155,11 +154,9 @@ joda-time:joda-time:jar log4j:log4j:jar mysql:mysql-connector-java:jar - net.databinder.dispatch:dispatch-core_2.11:jar - net.databinder.dispatch:dispatch-json4s-jackson_2.11:jar org.antlr:antlr-runtime:jar org.antlr:stringtemplate:jar - org.apache.commons:commons-compress:jar + org.apache.commons:commons-math:jar org.apache.commons:commons-math3:jar org.apache.curator:curator-client:jar @@ -169,13 +166,13 @@ org.apache.directory.api:api-util:jar org.apache.directory.server:apacheds-i18n:jar org.apache.directory.server:apacheds-kerberos-codec:jar - org.apache.hadoop:hadoop-annotations:jar - org.apache.hadoop:hadoop-auth:jar - org.apache.hadoop:hadoop-common:jar - org.apache.hadoop:hadoop-hdfs:jar - org.apache.htrace:htrace-core:jar - org.apache.httpcomponents:httpclient:jar - org.apache.httpcomponents:httpcore:jar + + + + + + + org.apache.logging.log4j:log4j-api:jar org.apache.logging.log4j:log4j-core:jar org.apache.logging.log4j:log4j-jul:jar @@ -194,7 +191,6 @@ org.eclipse.jetty:jetty-continuation:jar org.eclipse.jetty:jetty-http:jar org.eclipse.jetty:jetty-io:jar - org.eclipse.jetty:jetty-jndi:jar org.eclipse.jetty:jetty-plus:jar org.eclipse.jetty:jetty-security:jar org.eclipse.jetty:jetty-server:jar @@ -243,7 +239,6 @@ org.json4s:json4s-ast_2.11:jar org.json4s:json4s-core_2.11:jar org.json4s:json4s-jackson_2.11:jar - org.jsoup:jsoup:jar org.jvnet.mimepull:mimepull:jar org.jvnet:tiger-types:jar org.latencyutils:LatencyUtils:jar diff --git a/pom.xml b/pom.xml index c93448dc7..76737321d 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ 0.7.0 - 0.9.1 + 0.9.3 2.11.8 1.8 3.3.3 diff --git a/visualis-appjoint/appjoint/pom.xml b/visualis-appjoint/appjoint/pom.xml index 9c6016de1..ab48a6148 100644 --- a/visualis-appjoint/appjoint/pom.xml +++ b/visualis-appjoint/appjoint/pom.xml @@ -45,6 +45,14 @@ true + + com.webank.wedatasphere.linkis + linkis-httpclient + ${linkis.version} + provided + true + + diff --git a/visualis-appjoint/appjoint/src/main/scala/com/webank/wedatasphere/dss/appjoint/visualis/execution/VisualisNodeExecution.scala b/visualis-appjoint/appjoint/src/main/scala/com/webank/wedatasphere/dss/appjoint/visualis/execution/VisualisNodeExecution.scala index 9de32921c..fa2575726 100644 --- a/visualis-appjoint/appjoint/src/main/scala/com/webank/wedatasphere/dss/appjoint/visualis/execution/VisualisNodeExecution.scala +++ b/visualis-appjoint/appjoint/src/main/scala/com/webank/wedatasphere/dss/appjoint/visualis/execution/VisualisNodeExecution.scala @@ -17,7 +17,7 @@ package com.webank.wedatasphere.dss.appjoint.visualis.execution -import java.io.ByteArrayOutputStream +import java.io.{ByteArrayOutputStream, InputStream} import java.util import java.util.Base64 @@ -28,25 +28,34 @@ import com.webank.wedatasphere.dss.appjoint.service.session.Session import com.webank.wedatasphere.dss.appjoint.visualis.execution.VisualisNodeExecutionConfiguration._ import com.webank.wedatasphere.linkis.common.exception.ErrorException import com.webank.wedatasphere.linkis.common.log.LogUtils -import com.webank.wedatasphere.linkis.common.utils.{HttpClient, Logging, Utils} +import com.webank.wedatasphere.linkis.common.utils.{Logging, Utils} import com.webank.wedatasphere.linkis.storage.{LineMetaData, LineRecord} import org.apache.commons.io.IOUtils import scala.collection.JavaConversions.mapAsScalaMap -import scala.concurrent.ExecutionContext +import scala.concurrent.duration.Duration +import scala.concurrent.{Await, ExecutionContext} +import dispatch._ +import org.json4s.{DefaultFormats, Formats} /** * Created by enjoyyin on 2019/10/12. */ -class VisualisNodeExecution extends NodeExecution with HttpClient with Logging { - - override protected implicit val executors: ExecutionContext = Utils.newCachedExecutionContext(VISUALIS_THREAD_MAX.getValue, getName + "-NodeExecution-Thread", true) +class VisualisNodeExecution extends NodeExecution with Logging { private val DISPLAY = "display" private val DASHBOARD = "dashboard" var basicUrl:String = _ + protected implicit val executors: ExecutionContext = Utils.newCachedExecutionContext(VISUALIS_THREAD_MAX.getValue, getName + "-NodeExecution-Thread", true) + protected implicit val formats: Formats = DefaultFormats + + private implicit def svc(url: String): Req = + dispatch.url(url) + + + override def getBaseUrl: String = this.basicUrl override def setBaseUrl(basicUrl: String): Unit = this.basicUrl = basicUrl @@ -95,6 +104,17 @@ class VisualisNodeExecution extends NodeExecution with HttpClient with Logging { appJointResponse } + def download(url: String, queryParams: Map[String, String], headerParams: Map[String, String], + write: InputStream => Unit, + paths: String*): Unit = { + var req = url.GET + if(headerParams != null && headerParams.nonEmpty) req = req <:< headerParams + if(queryParams != null) queryParams.foreach{ case (k, v) => req = req.addQueryParameter(k, v)} + if(paths != null) paths.filter(_ != null).foreach(p => req = req / p) + val response = Http(req OK as.Response(_.getResponseBodyAsStream)).map(write) + Await.result(response, Duration.Inf) + } + private def getRealId(displayId:String):Int = { Utils.tryCatch{ val f = java.lang.Float.parseFloat(displayId) -- Gitee From 42621e18346a3605a9bb42be9c06af05b553c189 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Fri, 10 Jan 2020 21:00:50 +0800 Subject: [PATCH 055/238] 1.Automated installation enhancements. close #79 --- bin/start-all.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bin/start-all.sh b/bin/start-all.sh index 14016d020..4c4cd173f 100644 --- a/bin/start-all.sh +++ b/bin/start-all.sh @@ -23,10 +23,12 @@ echo ${info} source /etc/profile source ~/.bash_profile -workDir=`dirname "${BASH_SOURCE-$0}"` -workDir=`cd "$workDir"; pwd` +shellDir=`dirname $0` + +workDir=`cd ${shellDir}/..;pwd` + +CONF_DIR="${workDir}"/conf -CONF_DIR="${workDir}"/../conf export LINKIS_DSS_CONF_FILE=${LINKIS_DSS_CONF_FILE:-"${CONF_DIR}/config.sh"} export DISTRIBUTION=${DISTRIBUTION:-"${CONF_DIR}/config.sh"} source $LINKIS_DSS_CONF_FILE @@ -151,7 +153,7 @@ if ! executeCMD $SERVER_IP "test -e ${DSS_INSTALL_HOME}/${SERVER_NAME}"; then return fi -sh $workDir/checkServices.sh $SERVER_NAME $SERVER_IP $SERVER_PORT +sh $workDir/bin/checkServices.sh $SERVER_NAME $SERVER_IP $SERVER_PORT isSuccess "start $SERVER_NAME " sleep 3 echo "<-------------------------------->" -- Gitee From 9f59077409b0da9664e9782a278621877c64faa8 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Tue, 14 Jan 2020 14:59:54 +0800 Subject: [PATCH 056/238] fix visualis-server status check failed after startup close #84 --- bin/checkServices.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/checkServices.sh b/bin/checkServices.sh index a540d525f..a742a1104 100644 --- a/bin/checkServices.sh +++ b/bin/checkServices.sh @@ -71,7 +71,7 @@ echo $MICRO_SERVICE_IP echo $MICRO_SERVICE_PORT echo "===========================================================" -if [ $MICRO_SERVICE_NAME == "visualis-server" ]||[ $MICRO_SERVICE_IP == "127.0.0.1" ]; then +if [ $MICRO_SERVICE_NAME == "visualis-server" ] && [ $MICRO_SERVICE_IP == "127.0.0.1" ]; then MICRO_SERVICE_IP="`hostname -i`" fi -- Gitee From 416f09a0dec29c3516aed36d58a8e404f68090bf Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 15 Jan 2020 18:04:17 +0800 Subject: [PATCH 057/238] Optimized the way to obtain the local IP address close #86 --- bin/checkServices.sh | 4 ++-- bin/install.sh | 4 ++-- bin/start-all.sh | 3 +-- bin/stop-all.sh | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/bin/checkServices.sh b/bin/checkServices.sh index a742a1104..2b45c3e66 100644 --- a/bin/checkServices.sh +++ b/bin/checkServices.sh @@ -31,7 +31,7 @@ MICRO_SERVICE_PORT=$3 local_host="`hostname --fqdn`" -ipaddr="`hostname -i`" +ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') function isLocal(){ if [ "$1" == "127.0.0.1" ];then @@ -72,7 +72,7 @@ echo $MICRO_SERVICE_PORT echo "===========================================================" if [ $MICRO_SERVICE_NAME == "visualis-server" ] && [ $MICRO_SERVICE_IP == "127.0.0.1" ]; then - MICRO_SERVICE_IP="`hostname -i`" + MICRO_SERVICE_IP=$ipaddr fi result=`echo -e "\n" | telnet $MICRO_SERVICE_IP $MICRO_SERVICE_PORT 2>/dev/null | grep Connected | wc -l` diff --git a/bin/install.sh b/bin/install.sh index 01b8c3a04..8832f7401 100644 --- a/bin/install.sh +++ b/bin/install.sh @@ -104,7 +104,7 @@ source ${DISTRIBUTION} isSuccess "load config" local_host="`hostname --fqdn`" -ipaddr="`hostname -i`" +ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') function isLocal(){ if [ "$1" == "127.0.0.1" ];then @@ -277,7 +277,7 @@ fi if [[ '2' = "$MYSQL_INSTALL_MODE" ]];then mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -D$MYSQL_DB --default-character-set=utf8 -e "source ${workDir}/db/dss_ddl.sql" isSuccess "source dss_ddl.sql" - LOCAL_IP="`hostname -i`" + LOCAL_IP=$ipaddr if [ $GATEWAY_INSTALL_IP == "127.0.0.1" ];then echo "GATEWAY_INSTALL_IP is equals 127.0.0.1 ,we will change it to ip address" GATEWAY_INSTALL_IP_2=$LOCAL_IP diff --git a/bin/start-all.sh b/bin/start-all.sh index 4c4cd173f..12eda1fc3 100644 --- a/bin/start-all.sh +++ b/bin/start-all.sh @@ -41,9 +41,8 @@ else echo "INFO:" + $1 fi } -local_host="`hostname --fqdn`" -ipaddr="`hostname -i`" +ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') function isLocal(){ if [ "$1" == "127.0.0.1" ];then diff --git a/bin/stop-all.sh b/bin/stop-all.sh index af158c9b7..c707085a3 100644 --- a/bin/stop-all.sh +++ b/bin/stop-all.sh @@ -34,7 +34,7 @@ export DISTRIBUTION=${DISTRIBUTION:-"${CONF_DIR}/config.sh"} source ${DISTRIBUTION} local_host="`hostname --fqdn`" -ipaddr="`hostname -i`" +ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') function isSuccess(){ if [ $? -ne 0 ]; then -- Gitee From 775a69617a37069adb1dd18fcd9355b2b71e935a Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 16 Jan 2020 15:13:33 +0800 Subject: [PATCH 058/238] Add deployment user to dss-server configuration by default close #88 --- bin/install.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/install.sh b/bin/install.sh index 8832f7401..7b9c85ddf 100644 --- a/bin/install.sh +++ b/bin/install.sh @@ -452,6 +452,7 @@ executeCMD $SERVER_IP "sed -i \"s#wds.dss.appjoint.scheduler.azkaban.address.*# executeCMD $SERVER_IP "sed -i \"s#wds.linkis.gateway.ip.*#wds.linkis.gateway.ip=$GATEWAY_INSTALL_IP#g\" $SERVER_CONF_PATH" executeCMD $SERVER_IP "sed -i \"s#wds.linkis.gateway.port.*#wds.linkis.gateway.port=$GATEWAY_PORT#g\" $SERVER_CONF_PATH" executeCMD $SERVER_IP "sed -i \"s#wds.dss.appjoint.scheduler.project.store.dir.*#wds.dss.appjoint.scheduler.project.store.dir=$WDS_SCHEDULER_PATH#g\" $SERVER_CONF_PATH" +executeCMD $SERVER_IP "echo "$deployUser=$deployUser" >> $SERVER_HOME/$SERVERNAME/conf/token.properties" isSuccess "subsitution linkis.properties of $SERVERNAME" echo "<----------------$SERVERNAME:end------------------->" echo "" -- Gitee From 92c0cf3f8d20bddfaa00fb4d8490ce65173d82f1 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 16 Jan 2020 20:19:50 +0800 Subject: [PATCH 059/238] Optimized the way to obtain the local IP address close #86 --- bin/start-all.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/start-all.sh b/bin/start-all.sh index 12eda1fc3..b61af2ff0 100644 --- a/bin/start-all.sh +++ b/bin/start-all.sh @@ -41,6 +41,7 @@ else echo "INFO:" + $1 fi } +local_host="`hostname --fqdn`" ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') -- Gitee From 859b0bdee47a5c7801f66c22ee4ca42160dd91fc Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Fri, 17 Jan 2020 14:44:37 +0800 Subject: [PATCH 060/238] DSS Web installation optimization close #94 --- web/config.sh | 12 +++---- web/install.sh | 86 +++++++++++++++++++++++++++-------------------- web/vue.config.js | 4 +-- 3 files changed, 58 insertions(+), 44 deletions(-) diff --git a/web/config.sh b/web/config.sh index 0ebe48dbe..5cebe73d0 100644 --- a/web/config.sh +++ b/web/config.sh @@ -1,8 +1,8 @@ -#Configuring front-end ports -dss_port="8088" +#dss web port +dss_web_port="8088" -#URL of the backend linkis gateway -linkis_url="http://localhost:20401" +#dss web access linkis gateway adress +linkis_gateway_url="http://localhost:9001" -#dss ip address -dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') +#dss nginx ip +dss_nginx_ip=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') diff --git a/web/install.sh b/web/install.sh index 01a7b3322..9a5a410c6 100644 --- a/web/install.sh +++ b/web/install.sh @@ -1,12 +1,22 @@ #!/bin/bash #当前路径 -workDir=$(cd `dirname $0`; pwd) +shellDir=`dirname $0` +workDir=`cd ${shellDir}/..;pwd` + +echo "dss web install start" + +dss_web_port=$DSS_WEB_PORT +linkis_gateway_url=$LINKIS_GATEWAY_URL +dss_nginx_ip=$DSS_NGINX_IP +#linkis_eureka_url=$LINKIS_EUREKA_URL + +if [[ "$dss_web_port" == "" ]]; then +source ${workDir}/conf/config.sh +fi -echo "dss front-end deployment script" -source $workDir/config.sh # 前端放置目录,默认为解压目录 dss_basepath=$workDir @@ -44,11 +54,11 @@ version=`cat /etc/redhat-release|sed -r 's/.* ([0-9]+)\..*/\1/'` echo "========================================================================配置信息=======================================================================" -echo "前端访问端口:${dss_port}" -echo "后端Linkis的地址:${linkis_url}" -echo "静态文件地址:${dss_basepath}/dist" -echo "当前路径:${workDir}" -echo "本机ip:${dss_ipaddr}" +echo "DSS web访问端口:${dss_web_port}" +echo "Linkis gateway 的地址:${linkis_gateway_url}" +echo "DSS web 静态文件地址:${dss_basepath}/dist" +echo "DSS web 安装路径:${workDir}" +echo "DSS nginx ip:${dss_nginx_ip}" echo "========================================================================配置信息=======================================================================" echo "" @@ -56,19 +66,18 @@ echo "" # 创建文件并配置nginx dssConf(){ - - s_host='$host' + s_host='$host' s_remote_addr='$remote_addr' s_proxy_add_x_forwarded_for='$proxy_add_x_forwarded_for' s_http_upgrade='$http_upgrade' - echo " + sudo sh -c "echo ' server { - listen $dss_port;# 访问端口 + listen $dss_web_port;# 访问端口 server_name localhost; #charset koi8-r; #access_log /var/log/nginx/host.access.log main; location /dss/visualis { - root ${dss_basepath}/dss/visualis; # 静态文件目录 + root ${dss_basepath}; # 静态文件目录 autoindex on; } location / { @@ -76,14 +85,14 @@ dssConf(){ index index.html index.html; } location /ws { - proxy_pass $linkis_url;#后端Linkis的地址 + proxy_pass $linkis_gateway_url;#后端Linkis的地址 proxy_http_version 1.1; proxy_set_header Upgrade $s_http_upgrade; proxy_set_header Connection "upgrade"; } location /api { - proxy_pass $linkis_url; #后端Linkis的地址 + proxy_pass $linkis_gateway_url; #后端Linkis的地址 proxy_set_header Host $s_host; proxy_set_header X-Real-IP $s_remote_addr; proxy_set_header x_real_ipP $s_remote_addr; @@ -105,7 +114,7 @@ dssConf(){ root /usr/share/nginx/html; } } - " > /etc/nginx/conf.d/dss.conf + ' > /etc/nginx/conf.d/dss.conf" } @@ -114,28 +123,28 @@ centos7(){ # nginx是否安装 #sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm sudo yum install -y nginx - echo "nginx 安装成功" + sudo echo "nginx 安装成功" # 配置nginx dssConf # 解决 0.0.0.0:8888 问题 - yum -y install policycoreutils-python - semanage port -a -t http_port_t -p tcp $dss_port + sudo yum -y install policycoreutils-python + sudo semanage port -a -t http_port_t -p tcp $dss_web_port # 开放前端访问端口 - firewall-cmd --zone=public --add-port=$dss_port/tcp --permanent + sudo firewall-cmd --zone=public --add-port=$dss_web_port/tcp --permanent # 重启防火墙 - firewall-cmd --reload + sudo firewall-cmd --reload # 启动nginx - systemctl restart nginx + sudo systemctl restart nginx # 调整SELinux的参数 - sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config + sudo sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config # 临时生效 - setenforce 0 + sudo setenforce 0 } @@ -144,7 +153,7 @@ centos6(){ # yum S_basearch='$basearch' S_releasever='$releasever' - echo " + sudo echo " [nginx] name=nginx repo baseurl=http://nginx.org/packages/centos/$E_releasever/$S_basearch/ @@ -153,31 +162,31 @@ centos6(){ " >> /etc/yum.repos.d/nginx.repo # install nginx - yum install nginx -y + sudo yum install nginx -y # 配置nginx dssConf # 防火墙 - S_iptables=`lsof -i:$dss_port | wc -l` + S_iptables=`lsof -i:$dss_web_port | wc -l` if [ "$S_iptables" -gt "0" ];then # 已开启端口防火墙重启 - service iptables restart + sudo service iptables restart else # 未开启防火墙添加端口再重启 - iptables -I INPUT 5 -i eth0 -p tcp --dport $dss_port -m state --state NEW,ESTABLISHED -j ACCEPT - service iptables save - service iptables restart + sudo iptables -I INPUT 5 -i eth0 -p tcp --dport $dss_web_port -m state --state NEW,ESTABLISHED -j ACCEPT + sudo service iptables save + sudo service iptables restart fi # start - /etc/init.d/nginx start + sudo /etc/init.d/nginx start # 调整SELinux的参数 - sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config + sudo sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config # 临时生效 - setenforce 0 + sudo setenforce 0 } @@ -190,6 +199,11 @@ fi if [[ $version -eq 7 ]]; then centos7 fi -echo '安装visualis前端,用户自行编译DSS前端安装包,则安装时需要把visualis的前端安装包放置于此'$dss_basepath/dss/visualis',用于自动化安装:' + +if ! test -e $dss_basepath/dss/visualis/build.zip; then +echo "Error*************:用户自行编译安装DSS WEB时,则需要把visualis的前端安装包build.zip放置于$dss_basepath/dss/visualis用于自动化安装" +exit 1 +fi + cd $dss_basepath/dss/visualis;unzip -o build.zip > /dev/null -echo "请浏览器访问:http://${dss_ipaddr}:${dss_port}" +#echo "请浏览器访问:http://${dss_nginx_ip}:${dss_web_port}" diff --git a/web/vue.config.js b/web/vue.config.js index 376a13f4a..d95110227 100644 --- a/web/vue.config.js +++ b/web/vue.config.js @@ -38,8 +38,8 @@ module.exports = { onEnd: { copy: [ { source: 'node_modules/monaco-editor/dev/vs', destination: `./dist/dist/static/vs` }, - { source: './config.sh', destination: `./dist` }, - { source: './install.sh', destination: `./dist` } + { source: './config.sh', destination: `./dist/conf` }, + { source: './install.sh', destination: `./dist/bin` } ], // 先删除根目录下的zip包 delete: [`./wedatasphere-DataSphereStudio-${getVersion()}-dist.zip`], -- Gitee From f51c1ee5a0b55942b36ecff73250ecea806a87f2 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 6 Feb 2020 14:35:08 +0800 Subject: [PATCH 061/238] DSS workflow add shell node close #97 --- conf/config.sh | 2 +- db/azkaban.sql | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/conf/config.sh b/conf/config.sh index 5499f42c1..dea8a60d7 100644 --- a/conf/config.sh +++ b/conf/config.sh @@ -71,7 +71,7 @@ VISUALIS_NGINX_PORT=8088 #azkaban address for check AZKABAN_ADRESS_IP=127.0.0.1 -AZKABAN_ADRESS_PORT=8091 +AZKABAN_ADRESS_PORT=8081 #qualitis.address for check QUALITIS_ADRESS_IP=127.0.0.1 diff --git a/db/azkaban.sql b/db/azkaban.sql index 489ded7bb..7f18b3308 100644 --- a/db/azkaban.sql +++ b/db/azkaban.sql @@ -1,3 +1,4 @@ INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'schedulis', NULL, '0', '1', NULL, '0', NULL, NULL, '1', NULL, NULL); -UPDATE `dss_application` SET url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT', project_url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT/manager?project=${projectName}',homepage_url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT/homepage' WHERE `name` in - ('schedulis'); +UPDATE `dss_application` SET url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT', project_url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT/manager?project=${projectName}',homepage_url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT/homepage' WHERE `name` in ('schedulis'); +SELECT @shcedulis_id:=id FROM `dss_application` WHERE `name` = 'schedulis'; +insert into dss_workflow_node values(null,null,'linkis.shell.sh',@shcedulis_id,1,1,0,1,null); -- Gitee From 143d94aa622bee003fd7fc396740a04daa0674e9 Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Tue, 11 Feb 2020 19:51:55 +0800 Subject: [PATCH 062/238] =?UTF-8?q?=E6=96=B0=E5=BB=BAshell=E8=8A=82?= =?UTF-8?q?=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/js/service/mixin.js | 2 +- web/src/js/service/nodeType.js | 2 +- web/vue.config.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/web/src/js/service/mixin.js b/web/src/js/service/mixin.js index 90341c5dd..4ca8713dc 100644 --- a/web/src/js/service/mixin.js +++ b/web/src/js/service/mixin.js @@ -34,7 +34,7 @@ export default { { rule: /\.python$/i, lang: 'python', executable: true, application: 'python', runType: 'python', ext: '.python', scriptType: 'python', abbr: 'py', logo: 'fi-python', isCanBeNew: true, label: 'Python', isCanBeOpen: true, flowType: 'python' }, { rule: /\.py$/i, lang: 'python', executable: true, application: 'spark', runType: 'python', ext: '.py', scriptType: 'pythonSpark', abbr: 'py', logo: 'fi-spark-python', isCanBeNew: true, label: 'PythonSpark', isCanBeOpen: true, flowType: 'pyspark' }, { rule: /\.r$/i, lang: 'r', executable: true, application: 'spark', runType: 'r', ext: '.r', scriptType: 'r', abbr: 'r', logo: 'fi-r', isCanBeNew: true, label: 'R', isCanBeOpen: true }, - { rule: /\.sh$/i, lang: 'sh', executable: true, application: 'shell', runType: 'shell', ext: '.sh', scriptType: 'shell', abbr: 'shell', logo: 'fi-r', isCanBeNew: false, label: 'Shell', isCanBeOpen: true, flowType: 'shell' }, + { rule: /\.sh$/i, lang: 'sh', executable: true, application: 'shell', runType: 'shell', ext: '.sh', scriptType: 'shell', abbr: 'shell', logo: 'fi-r', isCanBeNew: true, label: 'Shell', isCanBeOpen: true, flowType: 'shell' }, { rule: /\.qmlsql$/i, lang: 'hql', executable: false, application: 'spark', runType: 'sql', ext: '.qmlsql', scriptType: 'qmlsql', abbr: 'qmlsql', logo: 'fi-spark', isCanBeNew: false, label: 'QMLSQL', isCanBeOpen: true }, { rule: /\.qmlpy$/i, lang: 'python', executable: false, application: 'spark', runType: 'python', ext: '.qmlpy', scriptType: 'qmlpy', abbr: 'qmlpy', logo: 'fi-python', isCanBeNew: false, label: 'QMLPy', isCanBeOpen: true }, { rule: /\.txt$/i, lang: 'text', executable: false, application: null, runType: null, ext: '.txt', scriptType: 'txt', abbr: '', logo: 'fi-txt', isCanBeNew: false, isCanBeOpen: true }, diff --git a/web/src/js/service/nodeType.js b/web/src/js/service/nodeType.js index bf0a65498..5b6a55803 100644 --- a/web/src/js/service/nodeType.js +++ b/web/src/js/service/nodeType.js @@ -34,7 +34,7 @@ import qualitis from '../module/process/images/newIcon/qualitis.svg'; import python from '../module/process/images/newIcon/python.svg'; import jdbc from '../module/process/images/newIcon/JDBC2.svg'; const NODETYPE = { - SHELL: 'azkaban.shell', + SHELL: 'linkis.shell.sh', HQL: 'linkis.hive.hql', SPARKSQL: 'linkis.spark.sql', SPARKPY: 'linkis.spark.py', diff --git a/web/vue.config.js b/web/vue.config.js index 376a13f4a..d95110227 100644 --- a/web/vue.config.js +++ b/web/vue.config.js @@ -38,8 +38,8 @@ module.exports = { onEnd: { copy: [ { source: 'node_modules/monaco-editor/dev/vs', destination: `./dist/dist/static/vs` }, - { source: './config.sh', destination: `./dist` }, - { source: './install.sh', destination: `./dist` } + { source: './config.sh', destination: `./dist/conf` }, + { source: './install.sh', destination: `./dist/bin` } ], // 先删除根目录下的zip包 delete: [`./wedatasphere-DataSphereStudio-${getVersion()}-dist.zip`], -- Gitee From 9394e02cb3748ad3473f62db4dc68f9e200c7a6e Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 12 Feb 2020 15:37:09 +0800 Subject: [PATCH 063/238] DSS_LINKIS Quick Install Documentation close #103 --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 497 +++++++++++++++++++++ 1 file changed, 497 insertions(+) create mode 100644 docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md new file mode 100644 index 000000000..3a0fca275 --- /dev/null +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -0,0 +1,497 @@ +# DataSphere Studio快速安装使用文档 + +由于DataSphere Studio依赖于[Linkis](https://github.com/WeBankFinTech/Linkis),本文档提供了以下两种部署方式供您选择: + +1. DSS & Linkis 一键部署 + +     该模式适合于DSS和Linkis都没有安装的情况。 +     进入[DSS & Linkis安装环境准备]() + +2. DSS 一键部署 + +     该模式适合于Linkis已经安装,需要安装DSS的情况。 + +     进入[DSS快速安装文档](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md) + +     **请根据实际情况,选择合理安装方式**。 + +## 一、DSS & Linkis安装环境准备 + +**根据安装难度,我们提供了以下两种环境准备方式,请根据需要选择:** + +1. **精简版** + +     没有任何安装难度,适合于调研和学习,10分钟即可部署起来。 + +     支持的功能有: + +- 数据开发IDE - Scriptis,仅支持:执行Python和JDBC脚本 +- Linkis管理台 + +**进入[DSS & Linkis精简版环境准备]()** + +2. **标准版**: + +     有一定的安装难度,体现在Hadoop、Hive和Spark版本不同时,可能需要重新编译,可能会出现包冲突问题。 + +适合于试用和生产使用,2~3小时即可部署起来。 + +     支持的功能有: + +- 数据开发IDE - Scriptis + +- 工作流实时执行(**单机版**) + +- 信号功能和邮件功能 + +- 数据可视化 - Visualis(**单机版**) + +- 数据质量 - Qualitis(**单机版**) + +- 工作流定时调度 - Azkaban(**单机版**) + +- Linkis管理台 + +**进入[DSS & Linkis标准版环境准备]()** + +---- + +## 二、DSS & Linkis精简版环境准备 + +### a. 基础软件安装 + +        下面的软件必装: + +- MySQL (5.5+),[如何安装MySQL](https://www.runoob.com/mysql/mysql-install.html) +- JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) +- Python(2.x和3.x都支持),[如何安装Python](https://www.runoob.com/python/python-install.html) +- Nginx,[如何安装Nginx](https://www.tecmint.com/install-nginx-on-centos-7/) + +### b. 创建用户 + +        例如: **部署用户是hadoop账号** + +1. 在部署机器上创建部署用户,用于安装 + +```bash + sudo useradd hadoop +``` + +2. 因为Linkis的服务是以 sudo -u ${linux-user} 方式来切换引擎,从而执行作业,所以部署用户需要有 sudo 权限,而且是免密的。 + +```bash + vi /etc/sudoers +``` + + hadoop ALL=(ALL) NOPASSWD: NOPASSWD: ALL + +3. **如果您的Python想拥有画图功能,则还需在安装节点,安装画图模块**。命令如下: + +```bash + python -m pip install matplotlib +``` + +### c. 安装包准备 +DSS_LINKIS一键部署,安装包准备有两种方式: +1. 下载DataSphereStudio官方预编译且打包在一起的安装包,进行安装. +2. 用户自行编译或者去各个组件的release页面下载后替换一键部署目录中预编译的安装包。 + +(1)使用DSS社区预编译好的release安装包 + +请访问[点我进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/issues/90))进行下载,解压后的安装目录结构如下 + +```text +├── dss_linkis # 一键部署主目录 + ├── backup # 用于兼容Linkis老版本的安装启动脚本 + ├── bin # 用于一键安装启动DSS+Linkis + ├── conf # 一键部署的配置文件 + ├── azkaban-solo-server-x.x.x.tar.gz #azkaban安装包 + ├── linkis-jobtype-x.x.x.zip #linkis jobtype安装包 + ├── wedatasphere-dss-x.x.x-dist.tar.gz # DSS后台安装包 + ├── wedatasphere-dss-web-x.x.x-dist.zip # DSS前端安装包 + ├── wedatasphere-linkis-x.x.x-dist.tar.gz # Linkis安装包 + ├── wedatasphere-qualitis-x.x.x.zip # Qualitis安装包 +``` + + +(2)用户自行编译或者去各个组件release页面下载得到的安装包 + +- [wedatasphere-linkis-x.x.x-dist.tar.gz](https://github.com/WeBankFinTech/Linkis/releases) +- [wedatasphere-dss-x.x.x-dist.tar.gz](https://github.com/WeBankFinTech/DataSphereStudio/releases) +- [wedatasphere-dss-web-x.x.x-dist.zip](https://github.com/WeBankFinTech/DataSphereStudio/releases) +- [linkis-jobtype-x.x.x.zip](https://github.com/WeBankFinTech/DataSphereStudio/releases) +- azkaban-solo-server-x.x.x.tar.gz +- [wedatasphere-qualitis-x.x.x.zip](https://github.com/WeBankFinTech/Qualitis/releases) + + +先下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases),并解压,再将自行编译或单独下载的安装包放置于该解压目录下,目录层级结构与上述保持一致: + +```text +├── dss_linkis # 一键部署主目录 + ├── backup # 用于兼容Linkis老版本的安装启动脚本 + ├── bin # 用于一键安装启动DSS+Linkis + ├── conf # 一键部署的配置文件 + ├── azkaban-solo-server-x.x.x.tar.gz #azkaban安装包 + ├── linkis-jobtype-x.x.x.zip #linkis jobtype安装包 + ├── wedatasphere-dss-x.x.x-dist.tar.gz # DSS后台安装包 + ├── wedatasphere-dss-web-x.x.x-dist.zip # DSS前端安装包 + ├── wedatasphere-linkis-x.x.x-dist.tar.gz # Linkis安装包 + ├── wedatasphere-qualitis-x.x.x.zip # Qualitis安装包 +``` +**注意事项:** +1. Azkaban: 社区没有提供单独的release安装包,用户需要自行编译后的将安装包放置于安装目录下。 +2. DSS: 用户自行编译DSS安装包,会缺失visualis-server部分,因此,visualis-server也需要用户自行编译。从[visualis项目](https://github.com/WeBankFinTech/Visualis)编译打包后放置于wedatasphere-dss-x.x.x-dist.tar.gz的share/visualis-server目录下,否则dss安装时可能报找不到visualis安装包。 + +### d. 修改配置 + +将conf目录下的config.sh.lite.template,修改为config.sh + +```shell + cp conf/config.sh.lite.template conf/config.sh +``` + +**精简版可以不修改任何配置参数**,当然您也可以按需修改相关配置参数。 + +``` + vi conf/config.sh + + SSH_PORT=22 #ssh默认端口 + deployUser="`whoami`" #默认获取当前用户为部署用户 + WORKSPACE_USER_ROOT_PATH=file:///tmp/linkis/ ##工作空间路径,默认为本地路径,尽量提前创建并授于写权限 + RESULT_SET_ROOT_PATH=file:///tmp/linkis ##结果集路径,默认为本地路径,尽量提前创建并授于写权限 + DSS_NGINX_IP=127.0.0.1 #DSS Nginx访问IP + DSS_WEB_PORT=8088 #DSS Web页面访问端口 + +``` + +```properties + # 说明:通常情况下,精简版,上述参数默认情况均可不做修改,即可直接安装使用 + +``` + +### e. 修改数据库配置 + +```bash + vi conf/db.sh +``` + +```properties + # 设置数据库的连接信息 + MYSQL_HOST= + MYSQL_PORT= + MYSQL_DB= + MYSQL_USER= + MYSQL_PASSWORD= +``` + + +```properties + # 说明:此为必须配置参数,并确保可以从本机进行访问,验证方式: + mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD +``` + +精简版配置修改完毕,进入[安装和使用]() + +## 三、DSS & Linkis标准版环境准备 + +### a. 基础软件安装 + +        下面的软件必装: + +- MySQL (5.5+),[如何安装MySQL](https://www.runoob.com/mysql/mysql-install.html) + +- JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) + +- Python(2.x和3.x都支持),[如何安装Python](https://www.runoob.com/python/python-install.html) + +- Nginx,[如何安装Nginx](https://www.tecmint.com/install-nginx-on-centos-7/) + +        下面的服务必须可从本机访问: + +- Hadoop(**2.7.2,Hadoop其他版本需自行编译Linkis**) + +- Hive(**1.2.1,Hive其他版本需自行编译Linkis**) + +- Spark(**支持2.0以上所有版本**) + +### b. 创建用户 + +        例如: **部署用户是hadoop账号** + +1. 在所有需要部署的机器上创建部署用户,用于安装 + +```bash + sudo useradd hadoop +``` + +2. 因为Linkis的服务是以 sudo -u ${linux-user} 方式来切换引擎,从而执行作业,所以部署用户需要有 sudo 权限,而且是免密的。 + +```bash + vi /etc/sudoers +``` + +```properties + hadoop ALL=(ALL) NOPASSWD: NOPASSWD: ALL +``` + +3. 确保部署 DSS 和 Linkis 的服务器可正常访问Hadoop、Hive和Spark。 + +        **部署DSS 和 Linkis 的服务器,不要求必须安装Hadoop,但要求hdfs命令必须可用,如:hdfs dfs -ls /**。 + +        **如果想使用Linkis的Spark,部署 Linkis 的服务器,要求spark-sql命令必须可以正常启动一个spark application**。 + +        **在每台安装节点设置如下的全局环境变量**,以便Linkis能正常读取Hadoop、Hive和Spark的配置文件,具备访问Hadoop、Hive和Spark的能力。 + +        修改安装用户hadoop的.bash_rc,命令如下: + +```bash + vim /home/hadoop/.bash_rc +``` + +        下方为环境变量示例: + +```bash + #JDK + export JAVA_HOME=/nemo/jdk1.8.0_141 + #HADOOP + export HADOOP_CONF_DIR=/appcom/config/hadoop-config + #Hive + export HIVE_CONF_DIR=/appcom/config/hive-config + #Spark + export SPARK_HOME=/appcom/Install/spark + export SPARK_CONF_DIR=/appcom/config/spark-config + export PYSPARK_ALLOW_INSECURE_GATEWAY=1 # Pyspark必须加的参数 +``` + +4. **如果您的Pyspark想拥有画图功能,则还需在所有安装节点,安装画图模块**。命令如下: + +```bash + python -m pip install matplotlib +``` + +### c. 安装包准备 + +(1)使用DSS社区预编译好的release安装包 + +请访问[点我进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/issues/90))进行下载,解压后的安装目录结构如下 + +```text +├── dss_linkis # 一键部署主目录 + ├── backup # 用于兼容Linkis老版本的安装启动脚本 + ├── bin # 用于一键安装启动DSS+Linkis + ├── conf # 一键部署的配置文件 + ├── azkaban-solo-server-x.x.x.tar.gz #azkaban安装包 + ├── linkis-jobtype-x.x.x.zip #linkis jobtype安装包 + ├── wedatasphere-dss-x.x.x-dist.tar.gz # DSS后台安装包 + ├── wedatasphere-dss-web-x.x.x-dist.zip # DSS前端安装包 + ├── wedatasphere-linkis-x.x.x-dist.tar.gz # Linkis安装包 + ├── wedatasphere-qualitis-x.x.x.zip # Qualitis安装包 +``` + + +(2)用户自行编译或通过各个组件release下载得到的安装包 + +- [wedatasphere-linkis-x.x.x-dist.tar.gz](https://github.com/WeBankFinTech/Linkis/releases) +- [wedatasphere-dss-x.x.x-dist.tar.gz](https://github.com/WeBankFinTech/DataSphereStudio/releases) +- [wedatasphere-dss-web-x.x.x-dist.zip](https://github.com/WeBankFinTech/DataSphereStudio/releases) +- [linkis-jobtype-x.x.x.zip](https://github.com/WeBankFinTech/DataSphereStudio/releases) +- azkaban-solo-server-x.x.x.tar.gz +- [wedatasphere-qualitis-x.x.x.zip](https://github.com/WeBankFinTech/Qualitis/releases) + +先下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases),并解压,再将自行编译或单独下载的安装包放置于该解压目录下,目录层级结构与上述保持一致: + +```text +├── dss_linkis # 一键部署主目录 + ├── backup # 用于兼容Linkis老版本的安装启动脚本 + ├── bin # 用于一键安装启动DSS+Linkis + ├── conf # 一键部署的配置文件 + ├── azkaban-solo-server-x.x.x.tar.gz #azkaban安装包 + ├── linkis-jobtype-x.x.x.zip #linkis jobtype安装包 + ├── wedatasphere-dss-x.x.x-dist.tar.gz # DSS后台安装包 + ├── wedatasphere-dss-web-x.x.x-dist.zip # DSS前端安装包 + ├── wedatasphere-linkis-x.x.x-dist.tar.gz # Linkis安装包 + ├── wedatasphere-qualitis-x.x.x.zip # Qualitis安装包 +``` +**注意事项:** +1. Azkaban: 社区没有提供单独的release安装包,用户需要自行编译后的将安装包放置于安装目录下。 +2. DSS: 用户自行编译DSS安装包,会缺失visualis-server部分,因此,visualis-server也需要用户自行编译。从[visualis项目](https://github.com/WeBankFinTech/Visualis)编译打包后放置于wedatasphere-dss-x.x.x-dist.tar.gz的share/visualis-server目录下,否则安装时可能报找不到visualis安装包。 + +### d. 修改配置 + +将conf目录下的config.sh.stand.template,修改为config.sh + +```shell + cp conf/config.sh.stand.template conf/config.sh +``` + +您可以按需修改相关配置参数: + +``` + vi conf/config.sh +``` + +参数说明如下: +```properties + WORKSPACE_USER_ROOT_PATH=file:///tmp/linkis/ ##本地工作空间路径,默认为本地路径,尽量提前创建并授于写权限 + HDFS_USER_ROOT_PATH=hdfs:///tmp/linkis ##hdfs工作空间路径,默认为本地路径,尽量提前创建并授于写权限 + RESULT_SET_ROOT_PATH=hdfs:///tmp/linkis ##结果集路径,默认为本地路径,尽量提前创建并授于写权限 + WDS_SCHEDULER_PATH=file:///appcom/tmp/wds/scheduler ##DSS工程转换为azkaban工程后的存储路径 + #DSS Web,注意distribution.sh中VISUALIS_NGINX的IP和端口必须和此处保持一致 + DSS_NGINX_IP=127.0.0.1 #DSS Nginx访问IP + DSS_WEB_PORT=8088 #DSS Web页面访问端口 + ##hive metastore的地址 + HIVE_META_URL=jdbc:mysql://127.0.0.1:3306/metastore?useUnicode=true + HIVE_META_USER=xxx + HIVE_META_PASSWORD=xxx + ###hadoop配置文件目录 + HADOOP_CONF_DIR=/appcom/config/hadoop-config + ###hive配置文件目录 + HIVE_CONF_DIR=/appcom/config/hive-config + ###spark配置文件目录 + SPARK_CONF_DIR=/appcom/config/spark-config + +``` + +### e. 使用分布式模式 + +        如果您打算将DSS和Linkis都部署在同一台服务器上, 本步骤可以跳过。 + +        如果您打算将 DSS 和 Linkis 部署在多台服务器上,首先,您需要为这些服务器配置ssh免密登陆。 + +        [如何配置SSH免密登陆](https://www.jianshu.com/p/0922095f69f3) + +        同时,您还需要修改分布式部署模式下的distribution.sh配置文件,使分布式部署生效。 + +```shell script + vi conf/distribution.sh +``` + +```说明:IP地址和端口 + LINKIS和DSS的微服务IP地址和端口,可配置成远程地址,例如您想把LINKIS和DSS安装在不同的机器上,那么只需把linkis各项微服务的IP地址修改成与DSS不同的IP即可。 + +``` + +### f. 修改数据库配置 + +```bash + vi conf/db.sh +``` + +```properties + # 设置数据库的连接信息 + MYSQL_HOST= + MYSQL_PORT= + MYSQL_DB= + MYSQL_USER= + MYSQL_PASSWORD= +``` + +```properties + # 说明:此为必须配置参数,并确保可以从本机进行访问,验证方式: + mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD +``` + +标准版配置修改完毕,进入[安装和使用]() + +---- + + +## 四、安装和使用 + +### 1. 执行安装脚本: + +```bash + sh bin/install.sh +``` + +### 2. 安装步骤 + +- 该安装脚本会检查各项集成环境命令,如果没有请按照提示进行安装,以下命令为必须项: +_yum java mysql unzip expect telnet tar sed dos2unix nginx_ + +- 安装过程如果有很多cp 命令提示您是否覆盖安装,说明您的系统配置有别名,输入alias,如果有cp、mv、rm的别名,如果有可以去掉,就不会再有大量提示。 + +- install.sh脚本会询问您安装模式。 +安装模式分为精简版、标准版,请根据您准备的环境情况,选择合适的安装模式。 + +- install.sh脚本会询问您是否需要初始化数据库并导入元数据,linkis和dss 均会询问。 + +     **第一次安装**必须选是。 + +### 3. 是否安装成功: + +     通过查看控制台打印的日志信息查看是否安装成功。 + +     如果有错误信息,可以查看具体报错原因。 + +     您也可以通过查看我们的[安装常见问题](https://github.com/WeBankFinTech/DataSphereStudio/wiki/FAQ),获取问题的解答。 + +### 4. 启动服务 + +#### (1) 启动服务: + +     在安装目录执行以下命令,启动所有服务: + +```shell script + sh bin/start-all.sh > start.log 2>start_error.log +``` + +     如果启动产生了错误信息,可以查看具体报错原因。启动后,各项微服务都会进行**通信检测**,如果有异常则可以帮助用户定位异常日志和原因。 + +     您可以通过查看我们的[启动常见问题](https://github.com/WeBankFinTech/DataSphereStudio/wiki/FAQ),获取问题的解答。 + +#### (2) 查看是否启动成功 + +     可以在Eureka界面查看 Linkis & DSS 后台各微服务的启动情况。如下图,如您的Eureka主页**启动日志会打印此访问地址**,出现以下微服务,则表示服务都启动成功,可以正常对外提供服务了: + + ![Eureka](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/images/zh_CN/chapter2/quickInstallUse/quickInstall.png) + +#### (3) 谷歌浏览器访问: + +请使用**谷歌浏览器**访问以下前端地址: + +`http://DSS_NGINX_IP:DSS_WEB_PORT` **启动日志会打印此访问地址**。登陆时管理员的用户名和密码均为部署用户名,如部署用户为hadoop,则管理员的用户名/密码为:hadoop/hadoop。 + +如果您想支持更多用户登录,详见 [Linkis LDAP](https://github.com/WeBankFinTech/Linkis/wiki/%E9%83%A8%E7%BD%B2%E5%92%8C%E7%BC%96%E8%AF%91%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93) + +如何快速使用DSS, 点我进入 [DSS快速使用文档](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch3/DSS_User_Manual.md) + +【DSS用户手册】提供了更加详尽的使用方法,点我进入 [DSS用户手册](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch3/DSS_User_Manual.md) +#### (4) 停止服务: +     在安装目录执行以下命令,停止所有服务:sh bin/stop-all.sh + +**注意** +1. 如果用户想启动和停止**单个应用**,可修改启动脚本注释掉其他应用的启动和停止命令即可。 + +2. 如果用户想启动和停止**单个微服务**,则可进入该微服务安装目录下执行sh bin/start-微服务名称.sh或sh bin/stop-微服务名称.sh + +## 五、云资源 +## 云资源 + +**我们提供了DSS + Linkis + Qualitis + Visualis + Azkaban【全家桶一键部署安装包】,由于安装包过大(1.3GB),Github下载缓慢,请通过以下方式获取**: + +#### Baidu cloud: +*   百度云链接:https://pan.baidu.com/s/1hmxuJtyY72D5X_dZoQIE5g  +*   Password: p82h  + +#### Tencent Cloud: +*   腾讯云链接:https://share.weiyun.com/5vpLr9t +*   Password: upqgib + +**以下为Linkis安装包资源:** +*   腾讯云链接:https://share.weiyun.com/5Gjz0zU +*   密码:9vctqg  +*   百度云链:https://pan.baidu.com/s/1uuogWgLE9r8EcGROkRNeKg  +*   密码:pwbz  + +**以下为DSS安装包资源:** +*   腾讯云链接:https://share.weiyun.com/5n2GD0h +*   密码:p8f4ug +*   百度云链接:https://pan.baidu.com/s/18H8P75Y-cSEsW-doVRyAJQ  +*   密码:pnnj + +**附Qualitis及Azkaban单机版安装包资源:** +*   腾讯云链接:https://share.weiyun.com/5fBPVIV +*   密码:cwnhgw +*   百度云链接:https://pan.baidu.com/s/1DYvm_KTljQpbdk6ZPx6K9g  +*   密码:3lnk -- Gitee From 2bffa90d1a49f4377b8b4c74b8dae367648dc953 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 12 Feb 2020 16:38:19 +0800 Subject: [PATCH 064/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index 3a0fca275..39f97b712 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -5,7 +5,7 @@ 1. DSS & Linkis 一键部署      该模式适合于DSS和Linkis都没有安装的情况。 -     进入[DSS & Linkis安装环境准备]() +     进入[DSS & Linkis安装环境准备](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md#%E4%B8%80dss--linkis%E5%AE%89%E8%A3%85%E7%8E%AF%E5%A2%83%E5%87%86%E5%A4%87) 2. DSS 一键部署 @@ -28,7 +28,7 @@ - 数据开发IDE - Scriptis,仅支持:执行Python和JDBC脚本 - Linkis管理台 -**进入[DSS & Linkis精简版环境准备]()** +**进入[DSS & Linkis精简版环境准备](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md#%E4%BA%8Cdss--linkis%E7%B2%BE%E7%AE%80%E7%89%88%E7%8E%AF%E5%A2%83%E5%87%86%E5%A4%87)** 2. **标准版**: @@ -52,7 +52,7 @@ - Linkis管理台 -**进入[DSS & Linkis标准版环境准备]()** +**进入[DSS & Linkis标准版环境准备](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md#%E4%B8%89dss--linkis%E6%A0%87%E5%87%86%E7%89%88%E7%8E%AF%E5%A2%83%E5%87%86%E5%A4%87)** ---- @@ -124,7 +124,7 @@ DSS_LINKIS一键部署,安装包准备有两种方式: - [wedatasphere-qualitis-x.x.x.zip](https://github.com/WeBankFinTech/Qualitis/releases) -先下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases),并解压,再将自行编译或单独下载的安装包放置于该解压目录下,目录层级结构与上述保持一致: +先下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.7.0/dss-linkis-one-click-0.7.0-scripts.zip),并解压,再将自行编译或单独下载的安装包放置于该解压目录下,目录层级结构与上述保持一致: ```text ├── dss_linkis # 一键部署主目录 @@ -190,7 +190,7 @@ DSS_LINKIS一键部署,安装包准备有两种方式: mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD ``` -精简版配置修改完毕,进入[安装和使用]() +精简版配置修改完毕,进入[安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md#%E5%9B%9B%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) ## 三、DSS & Linkis标准版环境准备 @@ -298,7 +298,7 @@ DSS_LINKIS一键部署,安装包准备有两种方式: - azkaban-solo-server-x.x.x.tar.gz - [wedatasphere-qualitis-x.x.x.zip](https://github.com/WeBankFinTech/Qualitis/releases) -先下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases),并解压,再将自行编译或单独下载的安装包放置于该解压目录下,目录层级结构与上述保持一致: +先下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.7.0/dss-linkis-one-click-0.7.0-scripts.zip),并解压,再将自行编译或单独下载的安装包放置于该解压目录下,目录层级结构与上述保持一致: ```text ├── dss_linkis # 一键部署主目录 @@ -391,7 +391,7 @@ DSS_LINKIS一键部署,安装包准备有两种方式: mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD ``` -标准版配置修改完毕,进入[安装和使用]() +标准版配置修改完毕,进入[安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md#%E5%9B%9B%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) ---- @@ -424,7 +424,7 @@ _yum java mysql unzip expect telnet tar sed dos2unix nginx_      如果有错误信息,可以查看具体报错原因。 -     您也可以通过查看我们的[安装常见问题](https://github.com/WeBankFinTech/DataSphereStudio/wiki/FAQ),获取问题的解答。 +     您也可以通过查看我们的[安装常见问题](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch1/DSS%E5%AE%89%E8%A3%85%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%88%97%E8%A1%A8.md),获取问题的解答。 ### 4. 启动服务 @@ -438,7 +438,7 @@ _yum java mysql unzip expect telnet tar sed dos2unix nginx_      如果启动产生了错误信息,可以查看具体报错原因。启动后,各项微服务都会进行**通信检测**,如果有异常则可以帮助用户定位异常日志和原因。 -     您可以通过查看我们的[启动常见问题](https://github.com/WeBankFinTech/DataSphereStudio/wiki/FAQ),获取问题的解答。 +     您可以通过查看我们的[启动常见问题](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch1/DSS%E5%AE%89%E8%A3%85%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%88%97%E8%A1%A8.md),获取问题的解答。 #### (2) 查看是否启动成功 -- Gitee From d939748a66341be73f22b133e88c8e3dfc9bde13 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 12 Feb 2020 16:45:37 +0800 Subject: [PATCH 065/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index 39f97b712..7fe0b6bd1 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -471,26 +471,32 @@ _yum java mysql unzip expect telnet tar sed dos2unix nginx_ **我们提供了DSS + Linkis + Qualitis + Visualis + Azkaban【全家桶一键部署安装包】,由于安装包过大(1.3GB),Github下载缓慢,请通过以下方式获取**: #### Baidu cloud: + *   百度云链接:https://pan.baidu.com/s/1hmxuJtyY72D5X_dZoQIE5g  *   Password: p82h  + #### Tencent Cloud: + *   腾讯云链接:https://share.weiyun.com/5vpLr9t *   Password: upqgib **以下为Linkis安装包资源:** + *   腾讯云链接:https://share.weiyun.com/5Gjz0zU *   密码:9vctqg  *   百度云链:https://pan.baidu.com/s/1uuogWgLE9r8EcGROkRNeKg  *   密码:pwbz  **以下为DSS安装包资源:** + *   腾讯云链接:https://share.weiyun.com/5n2GD0h *   密码:p8f4ug *   百度云链接:https://pan.baidu.com/s/18H8P75Y-cSEsW-doVRyAJQ  *   密码:pnnj **附Qualitis及Azkaban单机版安装包资源:** + *   腾讯云链接:https://share.weiyun.com/5fBPVIV *   密码:cwnhgw *   百度云链接:https://pan.baidu.com/s/1DYvm_KTljQpbdk6ZPx6K9g  -- Gitee From 70f02252fafcb305e9b13edefaac558bfdf6e8aa Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 12 Feb 2020 16:46:44 +0800 Subject: [PATCH 066/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index 7fe0b6bd1..84255fe12 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -473,31 +473,45 @@ _yum java mysql unzip expect telnet tar sed dos2unix nginx_ #### Baidu cloud: *   百度云链接:https://pan.baidu.com/s/1hmxuJtyY72D5X_dZoQIE5g  + *   Password: p82h  #### Tencent Cloud: *   腾讯云链接:https://share.weiyun.com/5vpLr9t + *   Password: upqgib **以下为Linkis安装包资源:** *   腾讯云链接:https://share.weiyun.com/5Gjz0zU + *   密码:9vctqg  + *   百度云链:https://pan.baidu.com/s/1uuogWgLE9r8EcGROkRNeKg  + *   密码:pwbz  + **以下为DSS安装包资源:** *   腾讯云链接:https://share.weiyun.com/5n2GD0h + *   密码:p8f4ug + *   百度云链接:https://pan.baidu.com/s/18H8P75Y-cSEsW-doVRyAJQ  + *   密码:pnnj + **附Qualitis及Azkaban单机版安装包资源:** *   腾讯云链接:https://share.weiyun.com/5fBPVIV + *   密码:cwnhgw + *   百度云链接:https://pan.baidu.com/s/1DYvm_KTljQpbdk6ZPx6K9g  + *   密码:3lnk + -- Gitee From fd65bfb7b8f711cfe228bfe87676a800d755f12e Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 12 Feb 2020 16:55:01 +0800 Subject: [PATCH 067/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 45 +++++++++++----------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index 84255fe12..dcb2f48c8 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -466,52 +466,51 @@ _yum java mysql unzip expect telnet tar sed dos2unix nginx_ 2. 如果用户想启动和停止**单个微服务**,则可进入该微服务安装目录下执行sh bin/start-微服务名称.sh或sh bin/stop-微服务名称.sh ## 五、云资源 -## 云资源 +## 云资源 -**我们提供了DSS + Linkis + Qualitis + Visualis + Azkaban【全家桶一键部署安装包】,由于安装包过大(1.3GB),Github下载缓慢,请通过以下方式获取**: +**我们提供了DSS + Linkis + Qualitis + Visualis + Azkaban【全家桶一键部署安装包】,由于安装包过大(1.3GB),Github下载缓慢,请通过以下方式获取**: -#### Baidu cloud: +### Baidu cloud: -*   百度云链接:https://pan.baidu.com/s/1hmxuJtyY72D5X_dZoQIE5g  +- 百度云链接: -*   Password: p82h  +https://pan.baidu.com/s/1hmxuJtyY72D5X_dZoQIE5g +- Password: p82h -#### Tencent Cloud: +### Tencent Cloud: -*   腾讯云链接:https://share.weiyun.com/5vpLr9t +- 腾讯云链接:https://share.weiyun.com/5vpLr9t -*   Password: upqgib +- Password: upqgib **以下为Linkis安装包资源:** -*   腾讯云链接:https://share.weiyun.com/5Gjz0zU +- 腾讯云链接:https://share.weiyun.com/5Gjz0zU -*   密码:9vctqg  +- 密码:9vctqg -*   百度云链:https://pan.baidu.com/s/1uuogWgLE9r8EcGROkRNeKg  - -*   密码:pwbz  +- 百度云链: +https://pan.baidu.com/s/1uuogWgLE9r8EcGROkRNeKg +- 密码:pwbz **以下为DSS安装包资源:** -*   腾讯云链接:https://share.weiyun.com/5n2GD0h - -*   密码:p8f4ug +- 腾讯云链接:https://share.weiyun.com/5n2GD0h -*   百度云链接:https://pan.baidu.com/s/18H8P75Y-cSEsW-doVRyAJQ  +- 密码:p8f4ug -*   密码:pnnj +- 百度云链接:https://pan.baidu.com/s/18H8P75Y-cSEsW-doVRyAJQ +- 密码:pnnj **附Qualitis及Azkaban单机版安装包资源:** -*   腾讯云链接:https://share.weiyun.com/5fBPVIV - -*   密码:cwnhgw +- 腾讯云链接:https://share.weiyun.com/5fBPVIV -*   百度云链接:https://pan.baidu.com/s/1DYvm_KTljQpbdk6ZPx6K9g  +- 密码:cwnhgw -*   密码:3lnk +- 百度云链接:https://pan.baidu.com/s/1DYvm_KTljQpbdk6ZPx6K9g +- 密码:3lnk -- Gitee From 229d942713a6c102bff8d3d76da482a94216fc25 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 12 Feb 2020 16:56:05 +0800 Subject: [PATCH 068/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index dcb2f48c8..e58fc4a5c 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -472,9 +472,7 @@ _yum java mysql unzip expect telnet tar sed dos2unix nginx_ ### Baidu cloud: -- 百度云链接: - -https://pan.baidu.com/s/1hmxuJtyY72D5X_dZoQIE5g +- 百度云链接:https://pan.baidu.com/s/1hmxuJtyY72D5X_dZoQIE5g - Password: p82h -- Gitee From c0bc9e29e8bf2105a3b62382aeb15754b307bc75 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 12 Feb 2020 16:59:58 +0800 Subject: [PATCH 069/238] Update README-ZH.md --- README-ZH.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README-ZH.md b/README-ZH.md index 216b6af86..bcfcfb709 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -157,7 +157,7 @@ DSS主要特点: ## 快速安装使用 -点我进入[快速安装使用](docs/zh_CN/ch2/DSS快速安装使用文档.md) +点我进入[快速安装使用](docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md) ## 架构 @@ -167,7 +167,7 @@ DSS主要特点: #### 1. 安装编译文档 -[快速安装使用文档](docs/zh_CN/ch2/DSS快速安装使用文档.md) +[快速安装使用文档](docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md) [**DSS安装常见问题列表**](docs/zh_CN/ch1/DSS安装常见问题列表.md) @@ -203,4 +203,4 @@ DSS主要特点: ## License -DSS is under the Apache 2.0 license. See the [License](LICENSE) file for details. \ No newline at end of file +DSS is under the Apache 2.0 license. See the [License](LICENSE) file for details. -- Gitee From ef1f3140210dd37e6477cdf802b3ed7b1102a762 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 12 Feb 2020 17:26:13 +0800 Subject: [PATCH 070/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index e58fc4a5c..68d6d3291 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -5,6 +5,7 @@ 1. DSS & Linkis 一键部署      该模式适合于DSS和Linkis都没有安装的情况。 +      进入[DSS & Linkis安装环境准备](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md#%E4%B8%80dss--linkis%E5%AE%89%E8%A3%85%E7%8E%AF%E5%A2%83%E5%87%86%E5%A4%87) 2. DSS 一键部署 -- Gitee From 67688aaa16cad5f7637ed1f35569daa1c8296a60 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 12 Feb 2020 17:40:11 +0800 Subject: [PATCH 071/238] =?UTF-8?q?Update=20DSS=E5=BF=AB=E9=80=9F=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E4=BD=BF=E7=94=A8=E6=96=87=E6=A1=A3.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...4\275\277\347\224\250\346\226\207\346\241\243.md" | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index 23c3008bc..70f03db11 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -78,7 +78,7 @@ Nginx,[如何安装Nginx](https://www.tecmint.com/install-nginx-on-centos-7/) deployUser=hadoop #指定部署用户 - DSS_INSTALL_HOME=/appcom/Install/DSS #指定DSS的安装目录 + DSS_INSTALL_HOME=$workDir #默认为上一级目录 WORKSPACE_USER_ROOT_PATH=file:///tmp/Linkis #指定用户根目录,存储用户的脚本文件和日志文件等,是用户的工作空间。 @@ -189,7 +189,7 @@ Nginx,[如何安装Nginx](https://www.tecmint.com/install-nginx-on-centos-7/) deployUser=hadoop #指定部署用户 - DSS_INSTALL_HOME=/appcom/Install/DSS #指定DSS的安装目录 + DSS_INSTALL_HOME=$workDir #默认为上一级目录 WORKSPACE_USER_ROOT_PATH=file:///tmp/Linkis #指定用户根目录,存储用户的脚本文件和日志文件等,是用户的工作空间。 @@ -302,7 +302,7 @@ Azkaban [如何安装Azkaban](https://github.com/azkaban/azkaban) deployUser=hadoop #指定部署用户 - DSS_INSTALL_HOME=/appcom/Install/DSS #指定DSS的安装目录 + DSS_INSTALL_HOME=$workDir #默认为上一级目录 WORKSPACE_USER_ROOT_PATH=file:///tmp/Linkis #指定用户根目录,存储用户的脚本文件和日志文件等,是用户的工作空间。 @@ -386,14 +386,12 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/      安装模式就是简单模式或标准模式,请根据您准备的环境情况,选择合适的安装模式,精简版、简单模式和标准模式都会检查mysql服务,标准模式还会检测Qualitis服务和Azkaban外部server服务,如果检测失败会直接退出安装。 +- 安装过程如果有很多cp 命令提示您是否覆盖安装,说明您的系统配置有别名,输入alias,如果有cp、mv、rm的别名,如果有可以去掉,就不会再有大量提示。 + - install.sh脚本会询问您是否需要初始化数据库并导入元数据。      因为担心用户重复执行install.sh脚本,把数据库中的用户数据清空,所以在install.sh执行时,会询问用户是否需要初始化数据库并导入元数据。      **第一次安装**必须选是。 -- install.sh脚本会询问您是否需要初始化使用[davinci](https://github.com/edp963/davinci)所依赖的库表,如果您没有安装过davinci,则需要进行初始化建表,如果您已经安装了davinci,则无需再次初始化。 -     因为担心用户会mysql中已安装好的davinci数据清空,所以在install.sh执行时,会询问用户是否需要初始化。 -     **第一次安装**必须选是。 - ### c. 是否安装成功: -- Gitee From 911993942f5bceb2e588b24e49c255c54bbd2179 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 12 Feb 2020 21:27:27 +0800 Subject: [PATCH 072/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index 68d6d3291..a8397ecf0 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -350,6 +350,12 @@ DSS_LINKIS一键部署,安装包准备有两种方式: HIVE_CONF_DIR=/appcom/config/hive-config ###spark配置文件目录 SPARK_CONF_DIR=/appcom/config/spark-config + ###azkaban服务端IP地址及端口,单机版安装时请勿修改 + AZKABAN_ADRESS_IP=127.0.0.1 + AZKABAN_ADRESS_PORT=8081 + ####Qualitis服务端IP地址及端口,单机版安装时请勿修改 + QUALITIS_ADRESS_IP=127.0.0.1 + QUALITIS_ADRESS_PORT=8090 ``` -- Gitee From 866f8009665b140c766d7548445a80c646764984 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 13 Feb 2020 14:52:30 +0800 Subject: [PATCH 073/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 52 ++++------------------ 1 file changed, 8 insertions(+), 44 deletions(-) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index a8397ecf0..4e16ee932 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -93,30 +93,11 @@ ``` ### c. 安装包准备 -DSS_LINKIS一键部署,安装包准备有两种方式: -1. 下载DataSphereStudio官方预编译且打包在一起的安装包,进行安装. -2. 用户自行编译或者去各个组件的release页面下载后替换一键部署目录中预编译的安装包。 -(1)使用DSS社区预编译好的release安装包 - -请访问[点我进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/issues/90))进行下载,解压后的安装目录结构如下 - -```text -├── dss_linkis # 一键部署主目录 - ├── backup # 用于兼容Linkis老版本的安装启动脚本 - ├── bin # 用于一键安装启动DSS+Linkis - ├── conf # 一键部署的配置文件 - ├── azkaban-solo-server-x.x.x.tar.gz #azkaban安装包 - ├── linkis-jobtype-x.x.x.zip #linkis jobtype安装包 - ├── wedatasphere-dss-x.x.x-dist.tar.gz # DSS后台安装包 - ├── wedatasphere-dss-web-x.x.x-dist.zip # DSS前端安装包 - ├── wedatasphere-linkis-x.x.x-dist.tar.gz # Linkis安装包 - ├── wedatasphere-qualitis-x.x.x.zip # Qualitis安装包 -``` - - -(2)用户自行编译或者去各个组件release页面下载得到的安装包 +如果您想使用DSS & Linkis全家桶一键部署安装包(1.3GB)([点我进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/issues/90)),直接解压即可,以下步骤可忽略。 +下列步骤为用户自行编译或者去各个组件release页面下载安装包: +1. 下载安装包 - [wedatasphere-linkis-x.x.x-dist.tar.gz](https://github.com/WeBankFinTech/Linkis/releases) - [wedatasphere-dss-x.x.x-dist.tar.gz](https://github.com/WeBankFinTech/DataSphereStudio/releases) - [wedatasphere-dss-web-x.x.x-dist.zip](https://github.com/WeBankFinTech/DataSphereStudio/releases) @@ -124,8 +105,7 @@ DSS_LINKIS一键部署,安装包准备有两种方式: - azkaban-solo-server-x.x.x.tar.gz - [wedatasphere-qualitis-x.x.x.zip](https://github.com/WeBankFinTech/Qualitis/releases) - -先下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.7.0/dss-linkis-one-click-0.7.0-scripts.zip),并解压,再将自行编译或单独下载的安装包放置于该解压目录下,目录层级结构与上述保持一致: +2. 下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.7.0/dss-linkis-one-click-0.7.0-scripts.zip),并解压,再上述下载的安装包放置于该目录下,目录层级如下: ```text ├── dss_linkis # 一键部署主目录 @@ -272,26 +252,10 @@ DSS_LINKIS一键部署,安装包准备有两种方式: ### c. 安装包准备 -(1)使用DSS社区预编译好的release安装包 - -请访问[点我进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/issues/90))进行下载,解压后的安装目录结构如下 - -```text -├── dss_linkis # 一键部署主目录 - ├── backup # 用于兼容Linkis老版本的安装启动脚本 - ├── bin # 用于一键安装启动DSS+Linkis - ├── conf # 一键部署的配置文件 - ├── azkaban-solo-server-x.x.x.tar.gz #azkaban安装包 - ├── linkis-jobtype-x.x.x.zip #linkis jobtype安装包 - ├── wedatasphere-dss-x.x.x-dist.tar.gz # DSS后台安装包 - ├── wedatasphere-dss-web-x.x.x-dist.zip # DSS前端安装包 - ├── wedatasphere-linkis-x.x.x-dist.tar.gz # Linkis安装包 - ├── wedatasphere-qualitis-x.x.x.zip # Qualitis安装包 -``` - - -(2)用户自行编译或通过各个组件release下载得到的安装包 +如果您想使用DSS & Linkis全家桶一键部署安装包(1.3GB)([点我进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/issues/90)),直接解压即可,以下步骤可忽略。 +下列步骤为用户自行编译或者去各个组件release页面下载安装包: +1. 下载安装包 - [wedatasphere-linkis-x.x.x-dist.tar.gz](https://github.com/WeBankFinTech/Linkis/releases) - [wedatasphere-dss-x.x.x-dist.tar.gz](https://github.com/WeBankFinTech/DataSphereStudio/releases) - [wedatasphere-dss-web-x.x.x-dist.zip](https://github.com/WeBankFinTech/DataSphereStudio/releases) @@ -299,7 +263,7 @@ DSS_LINKIS一键部署,安装包准备有两种方式: - azkaban-solo-server-x.x.x.tar.gz - [wedatasphere-qualitis-x.x.x.zip](https://github.com/WeBankFinTech/Qualitis/releases) -先下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.7.0/dss-linkis-one-click-0.7.0-scripts.zip),并解压,再将自行编译或单独下载的安装包放置于该解压目录下,目录层级结构与上述保持一致: +2. 下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.7.0/dss-linkis-one-click-0.7.0-scripts.zip),并解压,再上述下载的安装包放置于该目录下,目录层级如下: ```text ├── dss_linkis # 一键部署主目录 -- Gitee From 8bd89ad21df0fa4d02dababd1befbd9ebb17d0be Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 13 Feb 2020 14:54:42 +0800 Subject: [PATCH 074/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index 4e16ee932..d75e5e13d 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -105,7 +105,7 @@ - azkaban-solo-server-x.x.x.tar.gz - [wedatasphere-qualitis-x.x.x.zip](https://github.com/WeBankFinTech/Qualitis/releases) -2. 下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.7.0/dss-linkis-one-click-0.7.0-scripts.zip),并解压,再上述下载的安装包放置于该目录下,目录层级如下: +2. 下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.7.0/dss-linkis-one-click-0.7.0-scripts.zip),并解压,再将上述所下载的安装包放置于该目录下,目录层级如下: ```text ├── dss_linkis # 一键部署主目录 @@ -263,7 +263,7 @@ - azkaban-solo-server-x.x.x.tar.gz - [wedatasphere-qualitis-x.x.x.zip](https://github.com/WeBankFinTech/Qualitis/releases) -2. 下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.7.0/dss-linkis-one-click-0.7.0-scripts.zip),并解压,再上述下载的安装包放置于该目录下,目录层级如下: +2. 下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.7.0/dss-linkis-one-click-0.7.0-scripts.zip),并解压,再将上述所下载的安装包放置于该目录下,目录层级如下: ```text ├── dss_linkis # 一键部署主目录 -- Gitee From ae148c1bc9ca819a439a511b8d38a79a65f6c7a3 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 13 Feb 2020 15:05:20 +0800 Subject: [PATCH 075/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index d75e5e13d..21f72398b 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -94,7 +94,7 @@ ### c. 安装包准备 -如果您想使用DSS & Linkis全家桶一键部署安装包(1.3GB)([点我进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/issues/90)),直接解压即可,以下步骤可忽略。 +**如果您想使用DSS & Linkis全家桶一键部署安装包(1.3GB)([点我进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/issues/90)),直接解压即可,以下步骤可忽略。 下列步骤为用户自行编译或者去各个组件release页面下载安装包: 1. 下载安装包 @@ -252,7 +252,7 @@ ### c. 安装包准备 -如果您想使用DSS & Linkis全家桶一键部署安装包(1.3GB)([点我进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/issues/90)),直接解压即可,以下步骤可忽略。 +**如果您想使用DSS & Linkis全家桶一键部署安装包(1.3GB)([点我进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/issues/90)),直接解压即可,以下步骤可忽略。 下列步骤为用户自行编译或者去各个组件release页面下载安装包: 1. 下载安装包 -- Gitee From 346663c92980ad37f5f650ab04df648059efd5a7 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 13 Feb 2020 15:05:57 +0800 Subject: [PATCH 076/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index 21f72398b..377c42b56 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -94,7 +94,7 @@ ### c. 安装包准备 -**如果您想使用DSS & Linkis全家桶一键部署安装包(1.3GB)([点我进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/issues/90)),直接解压即可,以下步骤可忽略。 +**如果您想使用DSS & Linkis全家桶一键部署安装包(1.3GB)([点我进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/issues/90)),直接解压即可,以下步骤可忽略。** 下列步骤为用户自行编译或者去各个组件release页面下载安装包: 1. 下载安装包 @@ -252,7 +252,7 @@ ### c. 安装包准备 -**如果您想使用DSS & Linkis全家桶一键部署安装包(1.3GB)([点我进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/issues/90)),直接解压即可,以下步骤可忽略。 +**如果您想使用DSS & Linkis全家桶一键部署安装包(1.3GB)([点我进入下载页面](https://github.com/WeBankFinTech/DataSphereStudio/issues/90)),直接解压即可,以下步骤可忽略。** 下列步骤为用户自行编译或者去各个组件release页面下载安装包: 1. 下载安装包 -- Gitee From 700d3a75ad924c527dcfdd1795e1b76dc5195af7 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 13 Feb 2020 22:59:43 +0800 Subject: [PATCH 077/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index 377c42b56..af8348586 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -105,7 +105,7 @@ - azkaban-solo-server-x.x.x.tar.gz - [wedatasphere-qualitis-x.x.x.zip](https://github.com/WeBankFinTech/Qualitis/releases) -2. 下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.7.0/dss-linkis-one-click-0.7.0-scripts.zip),并解压,再将上述所下载的安装包放置于该目录下,目录层级如下: +2. 下载DSS&LINKIS[一键部署脚本](https://share.weiyun.com/5Qvl07X),并解压,再将上述所下载的安装包放置于该目录下,目录层级如下: ```text ├── dss_linkis # 一键部署主目录 @@ -263,7 +263,7 @@ - azkaban-solo-server-x.x.x.tar.gz - [wedatasphere-qualitis-x.x.x.zip](https://github.com/WeBankFinTech/Qualitis/releases) -2. 下载[一键部署脚本](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.7.0/dss-linkis-one-click-0.7.0-scripts.zip),并解压,再将上述所下载的安装包放置于该目录下,目录层级如下: +2. 下载DSS&LINKIS[一键部署脚本](https://share.weiyun.com/5Qvl07X),并解压,再将上述所下载的安装包放置于该目录下,目录层级如下: ```text ├── dss_linkis # 一键部署主目录 -- Gitee From 938163da58d47a5822cee511a4794845bbad4950 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 13 Feb 2020 23:14:00 +0800 Subject: [PATCH 078/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index af8348586..b7cc4d789 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -374,6 +374,7 @@ ```bash sh bin/install.sh ``` +注意:安装脚本里面有两处是相对路径,请严格按照以上命令执行。 ### 2. 安装步骤 @@ -453,6 +454,10 @@ _yum java mysql unzip expect telnet tar sed dos2unix nginx_ - Password: upqgib +**DSS&Linkis 一键部署脚本** + +- URL:https://share.weiyun.com/5Qvl07X + **以下为Linkis安装包资源:** - 腾讯云链接:https://share.weiyun.com/5Gjz0zU -- Gitee From e88cfb34210bd126c4e694fbcca96c127cfcaa1c Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 13 Feb 2020 23:14:34 +0800 Subject: [PATCH 079/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index b7cc4d789..fd9f85977 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -374,7 +374,7 @@ ```bash sh bin/install.sh ``` -注意:安装脚本里面有两处是相对路径,请严格按照以上命令执行。 +注意:安装脚本有两处是相对路径,请严格按照以上命令执行。 ### 2. 安装步骤 -- Gitee From 4b11a52db3cd64decc32472982ca90b385d2dad4 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 13 Feb 2020 23:16:35 +0800 Subject: [PATCH 080/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index fd9f85977..03b5e9bf3 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -442,13 +442,13 @@ _yum java mysql unzip expect telnet tar sed dos2unix nginx_ **我们提供了DSS + Linkis + Qualitis + Visualis + Azkaban【全家桶一键部署安装包】,由于安装包过大(1.3GB),Github下载缓慢,请通过以下方式获取**: -### Baidu cloud: +** Baidu cloud:** - 百度云链接:https://pan.baidu.com/s/1hmxuJtyY72D5X_dZoQIE5g - Password: p82h -### Tencent Cloud: +** Tencent Cloud:** - 腾讯云链接:https://share.weiyun.com/5vpLr9t -- Gitee From 11275570b9b182da8dbb25b3420691a0a0df9473 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 13 Feb 2020 23:17:13 +0800 Subject: [PATCH 081/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index 03b5e9bf3..911bff347 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -442,13 +442,13 @@ _yum java mysql unzip expect telnet tar sed dos2unix nginx_ **我们提供了DSS + Linkis + Qualitis + Visualis + Azkaban【全家桶一键部署安装包】,由于安装包过大(1.3GB),Github下载缓慢,请通过以下方式获取**: -** Baidu cloud:** +**Baidu cloud:** - 百度云链接:https://pan.baidu.com/s/1hmxuJtyY72D5X_dZoQIE5g - Password: p82h -** Tencent Cloud:** +**Tencent Cloud:** - 腾讯云链接:https://share.weiyun.com/5vpLr9t -- Gitee From d062888d8ef3161bb0fefc3c6b239c8b433f549b Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Thu, 13 Feb 2020 23:33:19 +0800 Subject: [PATCH 082/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index 911bff347..45459a1eb 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -374,7 +374,7 @@ ```bash sh bin/install.sh ``` -注意:安装脚本有两处是相对路径,请严格按照以上命令执行。 +注意:安装脚本有两处是相对路径,为了正确安装,请按照以上命令执行。 ### 2. 安装步骤 -- Gitee From f4b5b3387aa6119cd98eb733c556d4ed098a7408 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Fri, 14 Feb 2020 16:01:43 +0800 Subject: [PATCH 083/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index 45459a1eb..230116755 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -41,11 +41,11 @@ - 数据开发IDE - Scriptis -- 工作流实时执行(**单机版**) +- 工作流实时执行 - 信号功能和邮件功能 -- 数据可视化 - Visualis(**单机版**) +- 数据可视化 - Visualis - 数据质量 - Qualitis(**单机版**) -- Gitee From 458fbdfd54c1e0a160c41a1091f2cba10a0ad057 Mon Sep 17 00:00:00 2001 From: 5herhom <35916131+5herhom@users.noreply.github.com> Date: Tue, 18 Feb 2020 11:54:50 +0800 Subject: [PATCH 084/238] Update install.sh Repair the issue that two ips are gotten when installing. --- bin/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/install.sh b/bin/install.sh index 7b9c85ddf..a7c6daa91 100644 --- a/bin/install.sh +++ b/bin/install.sh @@ -104,7 +104,7 @@ source ${DISTRIBUTION} isSuccess "load config" local_host="`hostname --fqdn`" -ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') +ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}'|awk 'NR==1' ) function isLocal(){ if [ "$1" == "127.0.0.1" ];then -- Gitee From 2164eb6d991196f51c24220d8e19ff3aaf9c5e2b Mon Sep 17 00:00:00 2001 From: 5herhom <35916131+5herhom@users.noreply.github.com> Date: Tue, 18 Feb 2020 12:00:50 +0800 Subject: [PATCH 085/238] Update checkServices.sh Repair the bug that two ips are gotten. --- bin/checkServices.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/checkServices.sh b/bin/checkServices.sh index 2b45c3e66..72df04be4 100644 --- a/bin/checkServices.sh +++ b/bin/checkServices.sh @@ -31,7 +31,7 @@ MICRO_SERVICE_PORT=$3 local_host="`hostname --fqdn`" -ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') +ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}'|awk 'NR==1') function isLocal(){ if [ "$1" == "127.0.0.1" ];then -- Gitee From c8aa755771e9a6d93be6bdbc4c3b51b79c309a3e Mon Sep 17 00:00:00 2001 From: 5herhom <35916131+5herhom@users.noreply.github.com> Date: Tue, 18 Feb 2020 12:01:43 +0800 Subject: [PATCH 086/238] Update install.sh --- bin/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/install.sh b/bin/install.sh index a7c6daa91..7a0b46db6 100644 --- a/bin/install.sh +++ b/bin/install.sh @@ -104,7 +104,7 @@ source ${DISTRIBUTION} isSuccess "load config" local_host="`hostname --fqdn`" -ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}'|awk 'NR==1' ) +ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}'|awk 'NR==1') function isLocal(){ if [ "$1" == "127.0.0.1" ];then -- Gitee From 3a4d969789d92abdbb845a5df44cf3151689f895 Mon Sep 17 00:00:00 2001 From: 5herhom <35916131+5herhom@users.noreply.github.com> Date: Tue, 18 Feb 2020 12:03:47 +0800 Subject: [PATCH 087/238] Update start-all.sh Repair bug that two ips are gotten. --- bin/start-all.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/start-all.sh b/bin/start-all.sh index b61af2ff0..98a07f6bd 100644 --- a/bin/start-all.sh +++ b/bin/start-all.sh @@ -43,7 +43,7 @@ fi } local_host="`hostname --fqdn`" -ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') +ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}'|awk 'NR==1') function isLocal(){ if [ "$1" == "127.0.0.1" ];then -- Gitee From 8c571cf8abb94bd9767c54a81d0700fbcbed693b Mon Sep 17 00:00:00 2001 From: 5herhom <35916131+5herhom@users.noreply.github.com> Date: Tue, 18 Feb 2020 12:05:02 +0800 Subject: [PATCH 088/238] Update stop-all.sh Repair the bug that two ips are gotten. --- bin/stop-all.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/stop-all.sh b/bin/stop-all.sh index c707085a3..838b9babc 100644 --- a/bin/stop-all.sh +++ b/bin/stop-all.sh @@ -34,7 +34,7 @@ export DISTRIBUTION=${DISTRIBUTION:-"${CONF_DIR}/config.sh"} source ${DISTRIBUTION} local_host="`hostname --fqdn`" -ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') +ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}'|awk 'NR==1') function isSuccess(){ if [ $? -ne 0 ]; then -- Gitee From 2733feb3518546f16780f3012ebfa300cdf42007 Mon Sep 17 00:00:00 2001 From: 5herhom <35916131+5herhom@users.noreply.github.com> Date: Tue, 18 Feb 2020 14:54:01 +0800 Subject: [PATCH 089/238] Update config.sh --- web/config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/config.sh b/web/config.sh index 5cebe73d0..864e49271 100644 --- a/web/config.sh +++ b/web/config.sh @@ -5,4 +5,4 @@ dss_web_port="8088" linkis_gateway_url="http://localhost:9001" #dss nginx ip -dss_nginx_ip=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') +dss_nginx_ip=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}'|awk 'NR==1') -- Gitee From a5fa2fbbf59ed07988c2a5acd84f0cde3ddf8b12 Mon Sep 17 00:00:00 2001 From: 5herhom <35916131+5herhom@users.noreply.github.com> Date: Tue, 18 Feb 2020 15:00:20 +0800 Subject: [PATCH 090/238] =?UTF-8?q?Update=20DSS=E5=BF=AB=E9=80=9F=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E4=BD=BF=E7=94=A8=E6=96=87=E6=A1=A3.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\205\344\275\277\347\224\250\346\226\207\346\241\243.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index 70f03db11..4657b3bb2 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -132,7 +132,7 @@ dss_port="8088" linkis_url="http://127.0.0.1:9001" # dss ip address -dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') +dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}'|awk 'NR==1') ``` 环境准备完毕,点我进入 [五、安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E4%BA%94%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) @@ -243,7 +243,7 @@ dss_port="8088" linkis_url="http://127.0.0.1:9001" # dss ip address -dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') +dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}'|awk 'NR==1') ``` 环境准备完毕,点我进入 [五、安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E4%BA%94%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) @@ -365,7 +365,7 @@ dss_port="8088" linkis_url="http://127.0.0.1:9001" # dss ip address -dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') +dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}'|awk 'NR==1') ``` 环境准备完毕,点我进入 [五、安装和使用](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch2/DSS%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#%E4%BA%94%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8) -- Gitee From 4c818a02e60a860405ebf1f629c111c91635d2ea Mon Sep 17 00:00:00 2001 From: 5herhom <35916131+5herhom@users.noreply.github.com> Date: Tue, 18 Feb 2020 15:01:44 +0800 Subject: [PATCH 091/238] Update DSS Quick Installation Guide.md --- docs/en_US/ch2/DSS Quick Installation Guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en_US/ch2/DSS Quick Installation Guide.md b/docs/en_US/ch2/DSS Quick Installation Guide.md index f4b8cd159..b05eac6f6 100644 --- a/docs/en_US/ch2/DSS Quick Installation Guide.md +++ b/docs/en_US/ch2/DSS Quick Installation Guide.md @@ -103,7 +103,7 @@ dss_port="8088" linkis_url="http://127.0.0.1:9001" # dss ip address -dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') +dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}'|awk 'NR==1') ``` The environment is ready, click me to enter ****[4. Installation and use](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/en_US/ch2/DSS%20Quick%20Installation%20Guide.md#four-installation-and-use)** @@ -219,7 +219,7 @@ dss_port="8088" linkis_url="http://127.0.0.1:9001" # dss ip address -dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') +dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}'|awk 'NR==1') ``` The environment is ready, click me to enter **[Four Installation and use](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/en_US/ch2/DSS%20Quick%20Installation%20Guide.md#four-installation-and-use)** -- Gitee From 84942596afcb9628a29e13f8c05a4bc783152fbe Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Wed, 19 Feb 2020 11:23:50 +0800 Subject: [PATCH 092/238] =?UTF-8?q?Update=20DSS=E5=BF=AB=E9=80=9F=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E4=BD=BF=E7=94=A8=E6=96=87=E6=A1=A3.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...43\205\344\275\277\347\224\250\346\226\207\346\241\243.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index 70f03db11..e775e8380 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -32,7 +32,7 @@ ## 二、精简版DSS环境配置准备 DSS环境配置准备分为三部分,前后端基础软件安装、后端环境配置准备和前端环配置境准备,详细介绍如下: ### 2.1 前后端基础软件安装 -Linkis简单版(0.9.3及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) +Linkis精简版(0.9.3及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) @@ -251,7 +251,7 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/ ## 四、标准版DSS环境配置准备 标准版DSS环境准备也分为三部分,前后端基础软件安装、后端环境准备和前端环境准备,详细介绍如下: ### 4.1 前后端基础软件安装 -Linkis简单版(0.9.3及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) +Linkis标准版(0.9.3及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) -- Gitee From 682460f5aa6f38cb62db19f2fdcf6f76e2e7148d Mon Sep 17 00:00:00 2001 From: "lindaluo83@126.com" Date: Wed, 11 Mar 2020 11:17:12 +0800 Subject: [PATCH 093/238] fix editor version bug --- web/package.json | 2 +- web/src/js/component/editor/editor.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/package.json b/web/package.json index 09814a5fb..95693d327 100644 --- a/web/package.json +++ b/web/package.json @@ -35,7 +35,7 @@ "md5": "^2.2.1", "mitt": "^1.1.3", "moment": "^2.22.2", - "monaco-editor": "^0.15.1", + "monaco-editor": "^0.20.0", "pinyin": "^2.9.0", "qs": "^6.9.1", "reconnecting-websocket": "^4.1.10", diff --git a/web/src/js/component/editor/editor.vue b/web/src/js/component/editor/editor.vue index 1418ae01a..dad5484c9 100644 --- a/web/src/js/component/editor/editor.vue +++ b/web/src/js/component/editor/editor.vue @@ -91,7 +91,7 @@ export default { if (newValue == this.getValue()) { return; } - let readOnly = this.editor.getConfiguration().readOnly; + let readOnly = this.editor.getRawOptions().readOnly; if (readOnly) { // editor.setValue 和 model.setValue 都会丢失撤销栈 this.editor.setValue(newValue); -- Gitee From af7676b39e60e8ff7d6ceca6d63e1002d1a8ed8a Mon Sep 17 00:00:00 2001 From: "xyqiao@vip.qq.com" Date: Sun, 15 Mar 2020 15:34:11 +0800 Subject: [PATCH 094/238] #116 --- .../service/AbstractEventCheckReceiver.java | 57 +++++++++++++------ 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/eventchecker-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/schedulis/jobtype/service/AbstractEventCheckReceiver.java b/eventchecker-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/schedulis/jobtype/service/AbstractEventCheckReceiver.java index 4f0a85e07..fbd1c887a 100644 --- a/eventchecker-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/schedulis/jobtype/service/AbstractEventCheckReceiver.java +++ b/eventchecker-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/schedulis/jobtype/service/AbstractEventCheckReceiver.java @@ -80,39 +80,62 @@ public class AbstractEventCheckReceiver extends AbstractEventCheck{ boolean result = false; String vNewMsgID = "-1"; PreparedStatement updatePstmt = null; + PreparedStatement pstmtForGetID = null; Connection msgConn = null; vNewMsgID = setConsumedMsg(props,log,consumedMsgInfo); try { if(StringUtils.isNotEmpty(vNewMsgID) && StringUtils.isNotBlank(vNewMsgID) && !"-1".equals(vNewMsgID)){ msgConn = getEventCheckerConnection(props,log); if(msgConn == null) return false; - int vProcessID = jobId; - String vReceiveTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");; - String sqlForUpdateMsg = "INSERT INTO event_status(receiver,topic,msg_name,receive_time,msg_id) VALUES(?,?,?,?,?) ON DUPLICATE KEY UPDATE receive_time=VALUES(receive_time),msg_id= CASE WHEN msg_id= " + lastMsgId + " THEN VALUES(msg_id) ELSE msg_id END"; - log.info("last message offset {} is:" + lastMsgId); - updatePstmt = msgConn.prepareCall(sqlForUpdateMsg); - updatePstmt.setString(1, receiver); - updatePstmt.setString(2, topic); - updatePstmt.setString(3, msgName); - updatePstmt.setString(4, vReceiveTime); - updatePstmt.setString(5, vNewMsgID); - int updaters = updatePstmt.executeUpdate(); - log.info("updateMsgOffset successful {} update result is:" + updaters); - if(updaters != 0){ - log.info("Received message successfully , update message status succeeded, consumed flow execution ID: " + vProcessID); - //return true after update success - result = true; + msgConn.setAutoCommit(false); + String sqlForReadMsgID = "SELECT msg_id FROM event_status WHERE receiver=? AND topic=? AND msg_name=? for update"; + pstmtForGetID = msgConn.prepareCall(sqlForReadMsgID); + pstmtForGetID.setString(1, receiver); + pstmtForGetID.setString(2, topic); + pstmtForGetID.setString(3, msgName); + ResultSet rs = pstmtForGetID.executeQuery(); + String nowLastMsgId = rs.last()==true ? rs.getString("msg_id"):"0"; + log.info("receive message successfully , Now check to see if the latest offset has changed ,nowLastMsgId is {} " + nowLastMsgId); + if("0".equals(nowLastMsgId) || nowLastMsgId.equals(lastMsgId)){ + + int vProcessID = jobId; + String vReceiveTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");; + String sqlForUpdateMsg = "INSERT INTO event_status(receiver,topic,msg_name,receive_time,msg_id) VALUES(?,?,?,?,?) ON DUPLICATE KEY UPDATE receive_time=VALUES(receive_time),msg_id= CASE WHEN msg_id= " + lastMsgId + " THEN VALUES(msg_id) ELSE msg_id END"; + log.info("last message offset {} is:" + lastMsgId); + updatePstmt = msgConn.prepareCall(sqlForUpdateMsg); + updatePstmt.setString(1, receiver); + updatePstmt.setString(2, topic); + updatePstmt.setString(3, msgName); + updatePstmt.setString(4, vReceiveTime); + updatePstmt.setString(5, vNewMsgID); + int updaters = updatePstmt.executeUpdate(); + log.info("updateMsgOffset successful {} update result is:" + updaters); + if(updaters != 0){ + log.info("Received message successfully , update message status succeeded, consumed flow execution ID: " + vProcessID); + //return true after update success + result = true; + }else{ + log.info("Received message successfully , update message status failed, consumed flow execution ID: " + vProcessID); + result = false; + } }else{ - log.info("Received message successfully , update message status failed, consumed flow execution ID: " + vProcessID); + log.info("the latest offset has changed , Keep waiting for the signal"); result = false; } + msgConn.commit(); }else{ result = false; } }catch (SQLException e){ log.error("Error update Msg Offset" + e); + try { + msgConn.rollback(); + } catch (SQLException ex) { + log.error("transaction rollback failed " + e); + } return false; }finally { + closeQueryStmt(pstmtForGetID, log); closeQueryStmt(updatePstmt, log); closeConnection(msgConn, log); } -- Gitee From 6350601f58ca6d807de01e27802ffa0e5def5f83 Mon Sep 17 00:00:00 2001 From: chaogefeng <673120261@163.com> Date: Fri, 20 Mar 2020 10:52:53 +0800 Subject: [PATCH 095/238] =?UTF-8?q?Update=20DSS=E5=AE=89=E8=A3=85=E5=B8=B8?= =?UTF-8?q?=E8=A7=81=E9=97=AE=E9=A2=98=E5=88=97=E8=A1=A8.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\256\351\242\230\345\210\227\350\241\250.md" | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git "a/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" "b/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" index 0b9e77982..795de8451 100644 --- "a/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" +++ "b/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" @@ -3,17 +3,20 @@ **本文档汇总DSS安装过程中所有问题列表及解决方式,为社区用户安装DSS提供参考。** -#### (1) 创建工程提示用户token为空 +#### (1) 创建工程失败:add scheduler project用户token为空 ``` -sudo vi dss-server/conf/token.properties -``` - -添加用户 +{"method":null,"status":1,"message":"error code(错误码): 90002, error message(错误信息): add scheduler project failederrCode: 90019 ,desc: errCode: 90020 ,desc: 用户token为空 ,ip: dss.com ,port: 9004 ,serviceKind: dss-server ,ip: dss.com ,port: 9004 ,serviceKind: dss-server.","data":{"errorMsg":{"serviceKind":"dss-server","level":2,"port":9004,"errCode":90002,"ip":"dss.com","desc":"add scheduler project failederrCode: 90019 ,desc: errCode: 90020 ,desc: 用户token为空 ,ip: dss.com ,port: 9004 ,serviceKind: dss-server ,ip: dss.com ,port: 9004 ,serviceKind: dss-server"}}} ``` -xxx=xxx -``` + +确保dss-server的token.properties中添加了此用户,并保持与 azkaban 的 azkaban-users.xml用户一致 +以hadoop用户为例: +1、在dss-server的token.properties添加 +hadoop=hadoop +2、在azkaban azkaban-users.xml 文件 添加 + Date: Thu, 2 Apr 2020 18:46:59 +0800 Subject: [PATCH 096/238] Update DSS_LINKIS_Quick_Install.md --- docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md index 230116755..60e5735fb 100644 --- a/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md +++ b/docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md @@ -105,7 +105,7 @@ - azkaban-solo-server-x.x.x.tar.gz - [wedatasphere-qualitis-x.x.x.zip](https://github.com/WeBankFinTech/Qualitis/releases) -2. 下载DSS&LINKIS[一键部署脚本](https://share.weiyun.com/5Qvl07X),并解压,再将上述所下载的安装包放置于该目录下,目录层级如下: +2. 下载DSS&LINKIS[一键部署脚本](https://share.weiyun.com/58yxh3n),并解压,再将上述所下载的安装包放置于该目录下,目录层级如下: ```text ├── dss_linkis # 一键部署主目录 @@ -263,7 +263,7 @@ - azkaban-solo-server-x.x.x.tar.gz - [wedatasphere-qualitis-x.x.x.zip](https://github.com/WeBankFinTech/Qualitis/releases) -2. 下载DSS&LINKIS[一键部署脚本](https://share.weiyun.com/5Qvl07X),并解压,再将上述所下载的安装包放置于该目录下,目录层级如下: +2. 下载DSS&LINKIS[一键部署脚本](https://share.weiyun.com/58yxh3n),并解压,再将上述所下载的安装包放置于该目录下,目录层级如下: ```text ├── dss_linkis # 一键部署主目录 -- Gitee From 4c505a3fa57f1b82e37a281833a8c9e7ea5555a3 Mon Sep 17 00:00:00 2001 From: Adamyuanyuan Date: Thu, 9 Apr 2020 16:25:04 +0800 Subject: [PATCH 097/238] #120 add test sample: scala, hive and spark-sql --- docs/zh_CN/ch3/DSS_User_Tests1_Scala.md | 82 +++++++++++++ docs/zh_CN/ch3/DSS_User_Tests2_Hive.md | 132 +++++++++++++++++++++ docs/zh_CN/ch3/DSS_User_Tests3_SparkSQL.md | 61 ++++++++++ images/zh_CN/chapter3/tests/hive-6.png | Bin 0 -> 36938 bytes images/zh_CN/chapter3/tests/hive1.png | Bin 0 -> 26542 bytes images/zh_CN/chapter3/tests/hive2.png | Bin 0 -> 37850 bytes images/zh_CN/chapter3/tests/hive3.png | Bin 0 -> 19704 bytes images/zh_CN/chapter3/tests/hive4.png | Bin 0 -> 42837 bytes images/zh_CN/chapter3/tests/hive5.png | Bin 0 -> 14989 bytes images/zh_CN/chapter3/tests/hive7.png | Bin 0 -> 17396 bytes images/zh_CN/chapter3/tests/home.png | Bin 0 -> 135287 bytes images/zh_CN/chapter3/tests/udf-3.png | Bin 0 -> 9506 bytes images/zh_CN/chapter3/tests/udf1.png | Bin 0 -> 12946 bytes images/zh_CN/chapter3/tests/udf2.png | Bin 0 -> 4208 bytes 14 files changed, 275 insertions(+) create mode 100644 docs/zh_CN/ch3/DSS_User_Tests1_Scala.md create mode 100644 docs/zh_CN/ch3/DSS_User_Tests2_Hive.md create mode 100644 docs/zh_CN/ch3/DSS_User_Tests3_SparkSQL.md create mode 100644 images/zh_CN/chapter3/tests/hive-6.png create mode 100644 images/zh_CN/chapter3/tests/hive1.png create mode 100644 images/zh_CN/chapter3/tests/hive2.png create mode 100644 images/zh_CN/chapter3/tests/hive3.png create mode 100644 images/zh_CN/chapter3/tests/hive4.png create mode 100644 images/zh_CN/chapter3/tests/hive5.png create mode 100644 images/zh_CN/chapter3/tests/hive7.png create mode 100644 images/zh_CN/chapter3/tests/home.png create mode 100644 images/zh_CN/chapter3/tests/udf-3.png create mode 100644 images/zh_CN/chapter3/tests/udf1.png create mode 100644 images/zh_CN/chapter3/tests/udf2.png diff --git a/docs/zh_CN/ch3/DSS_User_Tests1_Scala.md b/docs/zh_CN/ch3/DSS_User_Tests1_Scala.md new file mode 100644 index 000000000..338390611 --- /dev/null +++ b/docs/zh_CN/ch3/DSS_User_Tests1_Scala.md @@ -0,0 +1,82 @@ +# DSS用户测试样例1:Scala + +DSS用户测试样例的目的是为平台新用户提供一组测试样例,用于熟悉DSS的常见操作,并验证DSS平台的正确性 + +![image-20200408211243941](../../../images/zh_CN/chapter3/tests/home.png) + +## 1.1 Spark Core(入口函数sc) + +在script中,已经默认为您注册了SparkContext,所以直接使用sc即可: + +### 1.1.1 单Value算子(Map算子为例) + +```scala +val rddMap = sc.makeRDD(Array((1,"a"),(1,"d"),(2,"b"),(3,"c")),4) +val res = rddMap.mapValues(data=>{data+"||||"}) +res.collect().foreach(data=>println(data._1+","+data._2)) +``` + +### 1.1.2 双Value算子(union算子为例) + +```scala +val rdd1 = sc.makeRDD(1 to 5) +val rdd2 = sc.makeRDD(6 to 10) +val rddCustom = rdd1.union(rdd2) +rddCustom.collect().foreach(println) +``` + +### 1.1.3 K-V算子(reduceByKey算子为例子) + +```scala +val rdd1 = sc.makeRDD(List(("female",1),("male",2),("female",3),("male",4))) +val rdd2 = rdd1.reduceByKey((x,y)=>x+y) +rdd2.collect().foreach(println) +``` + +### 1.1.4 执行算子(以上collect算子为例) + +### 1.1.5 从hdfs上读取文件并做简单执行 + +```scala +case class Person(name:String,age:String) +val file = sc.textFile("/test.txt") +val person = file.map(line=>{ + val values=line.split(",") + + Person(values(0),values(1)) +}) +val df = person.toDF() +df.select($"name").show() +``` + + + +## 1.2 UDF函数测试 + +### 1.2.1 函数定义 + + + +```scala +def ScalaUDF3(str: String): String = "hello, " + str + "this is a third attempt" +``` + +### 1.2.2 注册函数 + +函数-》个人函数-》右击新增spark函数=》注册方式同常规spark开发 + +​ ![img](../../../images/zh_CN/chapter3/tests/udf1.png) + +## 1.3 UDAF函数测试 + +### 1.3.1 Jar包上传 + +​ idea上开发一个求平均值的udaf函数,打成jar(wordcount)包,上传dss jar文件夹。 + +​ ![img](../../../images/zh_CN/chapter3/tests/udf2.png) + +### 1.3.2 注册函数 + +函数-》个人函数-》右击新增普通函数=》注册方式同常规spark开发 + + ![img](../../../images/zh_CN/chapter3/tests/udf-3.png) \ No newline at end of file diff --git a/docs/zh_CN/ch3/DSS_User_Tests2_Hive.md b/docs/zh_CN/ch3/DSS_User_Tests2_Hive.md new file mode 100644 index 000000000..859edd993 --- /dev/null +++ b/docs/zh_CN/ch3/DSS_User_Tests2_Hive.md @@ -0,0 +1,132 @@ +# DSS用户测试样例2:Hive + +DSS用户测试样例的目的是为平台新用户提供一组测试样例,用于熟悉DSS的常见操作,并验证DSS平台的正确性 + +![image-20200408211243941](../../../images/zh_CN/chapter3/tests/home.png) + +## 2.1 数仓建表 + +​ 进入“数据库”页面,点击“+”,依次输入表信息、表结构和分区信息即可创建数据库表: + +image-20200408212604929 + +​ ![img](../../../images/zh_CN/chapter3/tests/hive2.png) + +​ 通过以上流程,分别创建部门表dept、员工表emp和分区员工表emp_partition,建表语句如下: + +```sql +create external table if not exists default.dept( + deptno int, + dname string, + loc int +) +row format delimited fields terminated by '\t'; + +create external table if not exists default.emp( + empno int, + ename string, + job string, + mgr int, + hiredate string, + sal double, + comm double, + deptno int +) +row format delimited fields terminated by '\t'; + +create table if not exists emp_partition( + empno int, + ename string, + job string, + mgr int, + hiredate string, + sal double, + comm double, + deptno int +) +partitioned by (month string) +row format delimited fields terminated by '\t'; +``` + +## 2.2 基本SQL语法测试 + +### 2.2.1 简单查询 + +```sql +select * from dept; +``` + +### 2.2.2 Join连接 + +```sql +select * from emp +left join dept +on emp.deptno = dept.deptno; +``` + +### 2.2.3 聚合函数 + +```sql +select dept.dname, avg(sal) as avg_salary +from emp left join dept +on emp.deptno = dept.deptno +group by dept.dname; +``` + +### 2.2.4 内置函数 + +```sql +select ename, job,sal, +rank() over(partition by job order by sal desc) sal_rank +from emp; +``` + +### 2.2.5 分区表简单查询 + +```sql +show partitions emp_partition; +select * from emp_partition where month='202001'; +``` + +### 2.2.6 分区表联合查询 + +```sql +select * from emp_partition where month='202001' +union +select * from emp_partition where month='202002' +union +select * from emp_partition where month='202003' +``` + +## 2.3 UDF函数测试 + +### 2.3.1 Jar包上传 + +进入scripts页面后,右键目录路径上传jar包: + +​ ![img](../../../images/zh_CN/chapter3/tests/hive3.png) + +### 4.3.2 自定义函数 + +进入“UDF函数”选项(如1),右击“个人函数”目录,选择“新增函数”: + +image-20200408214033801 + +输入函数名称、选择jar包、并填写注册格式、输入输出格式即可创建函数: + + ![img](../../../images/zh_CN/chapter3/tests/hive5.png) + +image-20200409155418424 + +获得的函数如下: + +​ ![img](../../../images/zh_CN/chapter3/tests/hive7.png) + +### 4.3.3 利用自定义函数进行SQL查询 + +完成函数注册后,可进入工作空间页面创建.hql文件使用函数: + +```sql +select deptno,ename, rename(ename) as new_name +from emp; +``` diff --git a/docs/zh_CN/ch3/DSS_User_Tests3_SparkSQL.md b/docs/zh_CN/ch3/DSS_User_Tests3_SparkSQL.md new file mode 100644 index 000000000..aaf2fb44d --- /dev/null +++ b/docs/zh_CN/ch3/DSS_User_Tests3_SparkSQL.md @@ -0,0 +1,61 @@ +# DSS用户测试样例3:SparkSQL + +DSS用户测试样例的目的是为平台新用户提供一组测试样例,用于熟悉DSS的常见操作,并验证DSS平台的正确性 + +![image-20200408211243941](../../../images/zh_CN/chapter3/tests/home.png) + +## 3.1RDD与DataFrame转换 + +### 3.1.1 RDD转为DataFrame + +```scala +case class MyList(id:Int) + +val lis = List(1,2,3,4) + +val listRdd = sc.makeRDD(lis) +import spark.implicits._ +val df = listRdd.map(value => MyList(value)).toDF() + +df.show() +``` + +### 3.1.2 DataFrame转为RDD + +```scala +case class MyList(id:Int) + +val lis = List(1,2,3,4) +val listRdd = sc.makeRDD(lis) +import spark.implicits._ +val df = listRdd.map(value => MyList(value)).toDF() +println("------------------") + +val dfToRdd = df.rdd + +dfToRdd.collect().foreach(print(_)) +``` + +## 3.2 DSL语法风格实现 + +```scala +val df = df1.union(df2) +val dfSelect = df.select($"department") +dfSelect.show() +``` + +## 3.3 SQL语法风格实现(入口函数sqlContext) + +```scala +val df = df1.union(df2) + +df.createOrReplaceTempView("dfTable") +val innerSql = """ + SELECT department + FROM dfTable + """ +val sqlDF = sqlContext.sql(innerSql) +sqlDF.show() +``` + +​ \ No newline at end of file diff --git a/images/zh_CN/chapter3/tests/hive-6.png b/images/zh_CN/chapter3/tests/hive-6.png new file mode 100644 index 0000000000000000000000000000000000000000..f1cb9d661504ba851a6c06339daf29b1a58f17e2 GIT binary patch literal 36938 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�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 C=!4q; literal 0 HcmV?d00001 diff --git a/images/zh_CN/chapter3/tests/hive1.png b/images/zh_CN/chapter3/tests/hive1.png new file mode 100644 index 0000000000000000000000000000000000000000..19322869c0091824fe75f37480d92120cf35c746 GIT binary patch literal 26542 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 literal 0 HcmV?d00001 diff --git a/images/zh_CN/chapter3/tests/hive2.png b/images/zh_CN/chapter3/tests/hive2.png new file mode 100644 index 0000000000000000000000000000000000000000..8232e3b46dfb0103d9724e369454e045d24c2937 GIT binary patch literal 37850 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 literal 0 HcmV?d00001 diff --git a/images/zh_CN/chapter3/tests/hive3.png b/images/zh_CN/chapter3/tests/hive3.png new file mode 100644 index 0000000000000000000000000000000000000000..523f1e13cc8284eb6f6ee00a7f3bd9699581a63c GIT binary patch literal 19704 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 LNkvXXu0mjff_qVS literal 0 HcmV?d00001 diff --git a/images/zh_CN/chapter3/tests/hive4.png b/images/zh_CN/chapter3/tests/hive4.png new file mode 100644 index 0000000000000000000000000000000000000000..77e26589e8b122ea3bd46e0c496f11cebba0a5b4 GIT binary patch literal 42837 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

!$Cv~1TgUlnxqWNw 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 literal 0 HcmV?d00001 diff --git a/images/zh_CN/chapter3/tests/hive5.png b/images/zh_CN/chapter3/tests/hive5.png new file mode 100644 index 0000000000000000000000000000000000000000..f2ecae30192fd0c6b3fa183d5bb4f4f3fa2cd8e5 GIT binary patch literal 14989 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

2h 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 literal 0 HcmV?d00001 diff --git a/images/zh_CN/chapter3/tests/hive7.png b/images/zh_CN/chapter3/tests/hive7.png new file mode 100644 index 0000000000000000000000000000000000000000..efe7141071fe8330297a7a00af010a43e33e19a8 GIT binary patch literal 17396 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 O_#-7QFIFa^@AqF-Ofc;L literal 0 HcmV?d00001 diff --git a/images/zh_CN/chapter3/tests/home.png b/images/zh_CN/chapter3/tests/home.png new file mode 100644 index 0000000000000000000000000000000000000000..1564c5150faa8694485800bd52dd9839bcb1cc1e GIT binary patch literal 135287 zcmZU)1ymecw=GN(G`Ks&aCe6U4GuwrOK^9G;O_2jjR*JOu8q5U^d1HV237LA=nohe1UVR(x4Ve&z&9eZeQ7W-A7CU! zzbU(BoUFRICf+>1UhE5u3sQN+e-l>Mw-Lp_#I>{OYdM}*wJ2)>sdkztFD=;=&o1R! zS^1dv@g9|EC@N$0u#dt>e(?YDYk%j&VZBr6t#1#H@9z&9>(R%TpPKjg1-GN--7@bU z^HYkdmO3!2dkoKf}3`3RJ58_wHMC@_tJH`;5J6S>ELcAAk!E`7EJ`vqFZRKOm>K zSN;3k(DR;EwMs|U#DuDdCi5ZiUxzi&{Xh5csObEfPOZT|*{Y&?;%~N_Xxm!x&ZZ^jIKzQe0g?Atd%YWbN6PFV7llLuM zFJ_JzQH%Ar#)E?vI2DyCCsNs2W*PtQUu4+LF(SnggFlOY(vL7z_IvZOV~f8o1Zwl@$-k)cddDo=Aws)@YrM`^9)}oigS*LCLagpLd21v&(LQ8wW&gqTEkk z*B@OU$G8w-pAh&f^Qdufll4UNPZo3>Chh+H2zrwfVT-pq!-|f%N#x>`eo#}>8ZVs3 zM$i+FRbzhsE-gt(L4#B_CiexasJ1L#y8>caRjS|f;AFYh6h+E0Th~~>b$1^k+KrX> z{sPxg(wuT$Lu*EZ-Fs!}>#Sf`ULJK@jILCuP%nBNA`|B<6@P!pl;M4!p?q9=yx144 zZ*Shd5jyL*;*@{BK(}1{bN~A;S!pk`OGN19qZ6vEmRH|fUfv~iZsYLT;gxv#-NtAk zIXiv9BD3k~rT)&>XHF)1jozf;F{pbRfp|i?wa%c^ypHtloE3fBJs-Vp2g+w6$lXHL z&aXLD}e!^#M^VwxxAKZU)Vs8Eg<6QbTZLivQGTPEj#NF5r`rt2%2H(VT z`G~sAYGd&c^^pS?K!FOlaIK&`B1%lLkETS_VZz47@N7kLfA=9po_+7%dJ7eb1l#p+ zb^5-2f({7v9z(?Eos`8WutI?Vf`JR~>rP=YB;ap~VOTb=R->pAs3xu9?urA+Er@ZDBU3lDgyt2D3F&+=pxXL{40j zbiwcA5;F}GhTCxWA)1}tR)T2Cg>l!=GPYlYMSAmyknNT0fz~mV6j)%sE7y| z#;`x>pAmjT#h04n1M!kcq?6MRL0+D5%-U1M-iUglO85Nqel9IAUD^R2e za-lbkBYjKq^Or-H(HD=;8Jw?<;*mtMMn)7xWxvn@#@;LMQHz zTH+OaI1u5itoq>odsyw?`ICDI$kw_VLo{X)+3cxwl@Gl584i>*lH=ZukTJfoH*lb^ zw}&*=<3d-;a#;>#Rs8sOiYJ>G zEp(ygD2}=bnRuBs`oymmS9(F+bs8LhIFKz)ti6lG2v`eXdzeivEQ&ii(0W3CsI~fo zK<4~eUn-l9G$`fMeyyGxm#vtaj-l^m})9a5gQ)j>{lF9lTV3+TU|Khntox+m&az|NC)#eMiPU=Z~?a zPy&+L+`wXNyS8{bdq%e(J|W~Lo%262GDsu&K>^C6UZ}tmk0j}@+cxn9fmc>UO(cQ? ziiMw&X=`{=^3@0JxNDB_f?&I6j%XP_sHxN}ouHrvEbjbak*|&0M*l;<*k|xrG|-t!RxSk;~g%XXul2OT$~QZDVv*ZNehkj6tZRQmV$3VbjFb9koya@o2&cXpLdB z(WVvuZTbKKmp*H)vCJmKCE51&r%7yb@(8KRGgCNz=LnGdyYy=nn(M>(&YIqZi|tQL z@Jru^B_<>$#%5%QejqS-xGvp6A2xK@#e2C~I&M4PlBU;bODU`BNNaX5zPfECKi}_s zK~3fhjo%;L*}j|w>K9q6yY{~-fnE9czEbFqDF(d$h|IrE>rJuJjQr6vIOs<(Jqk`R z4w;mB)bB;!J2c;&p8Zhej2j^Lh)CQWL4@-UcH;loi?7D{UXq$R7I7QJe~k8tb)}~s zk1F0@zi9d7;P-@eesz9i4Cn_53xTDbL8SQM4;)qjvLG~KIUsUc9(ZBcWs5%uWw*8Q z509u-J44Lj@$uqx6~1@nXj!V#d3R=mtTYdfZnv&(CKt-j?@Y3aDjV>AZ+@1z+6*RF zP*C{381k{8s0afEdT|4_<%6)y>o+c^xEu}1Wb#JV;~u;1?k4~9#D88#?{n+#T||)Z zywz5E!;C`k<3|J&hVgdLduPk_{@XN&Xg<6+`*4Y(5j*?oR^R@Ml(QVC@7I{G%zizG z#-?US3>8)x?ngAHX<@T@*oaUX>Om?tws_e@P3T25`QEJBOX&K%$Z5{oAT%2BMs)(g z@&ubz+jnTe{z=*l+$VB4V!V0C|C$If>2Lr*CRntD0tUkf|Ld4 zJ$9(*;OO`K($ZJ}AzsAf%A~S}9+5iDaIwcEr;qvIb;^I(pkfe+{}LUHOQ$xq4WT4J znVOmD9gt4mxN*1R(N68!ZCEyip$4=CDhFtBvssRFl+?VrB ze${|H35yDf{sqrN48QwcMR^POpXb z*yVB*Y?ekqNf6|#pYl6YKc!V9*h@qe4o-msR~!7Wq>;sH0&hKm-Za7NdIsTQi8zRD z61~7Jpq4uG@w!XwebZ@1Aeyfzqog59E*q8?qfguP`*-CP2y63QC%!KGu!n%Q*3s|> z9uhc}-S$f7B26ol(3FxQNf>Op_i5m7#UoAuYz;b-3+G;=R z8~h@V=Pzz7s&b15Ci-u1MTNaJmiY$1OH*K=Ty#m0Uv(pgD=>!!^e9`eeb=^PFv)V_ z+#ZPhwybT{QV)Vxu;sO+4(s=WLnhGTPnenc^>Vh~`Gt-RJ6+6hyI=O8B{1%z2umdM z@w|#cdqo^>nQDA$Y*bze0GM!Qg_9c*(p5y}of@o`r8F(1*9}+xl%*PtjL*b{)+n+792Txe%xy`c^=o3N%5c>pt-mF|qZISUN6TN1Qq?at8rl@tQ zvitY&oKGza3JX&k8dSS;F~r%WxUoKBgO(%PPS6&tVq0b^EB{gcF--_%5aTb2_%0iU7kX>Y^zDlM=xTwxn zJ2gFx)SRJi>8x=5vMkqFzoD%pr@4CDq;k6AS)Tec#r*`L#UlH(OpD~`;$_xNEiXq# zBNCLae%CRe0?ui-|GXM`RL8}t4 z#@lL&8VqBK0g!I@9((HF+!8K}-&RHlE2=?`$E7SNDpXR_jW+9ky1zmU z6rP!#zuL+ZYrCHCiAzfo*U>?v=l_D4fhEZa@nrk0k!dWsm>xj1w5&gb}EH>Z)AK42hL7ygMu zU-!XRQL$^z*xA{$n_g+wvh9LHA^h?7S~b1n@`z5o0*?d@!B;OJUS1%xC=>PRNUd{k zLjF06kSb$zdbjN7!_*HPm2dME^v|vobZV6aE#}0pceN7D=YGg3{6<7w3L#dSjn&>g z?n_Ip>X(~88Y~y3*oh83B6@N^Og!yQ1o(MV%BK!Lv5n_d7~ziyzNmK){6o0^t59<9 z;cOgu=6P?0R=Zy0LgKT~tgPCFiVMG49OpuWOwiiy)^Z^Zh;b6p`5Rpl2U(nMe;-qd zLNO8btSmk^<-_~z8k3aGP1f&dx43YS)z_dUa8M++S#*S+?eN$gTM~0&dOpyk%~uG* ze_k#tX-eQbdm%$+?D##iW{$b`&!UT@-yj!n~oKqXHbo7oOGxXCdmc6}K=%rY0t$0= zj_++cqbu!;84g0VCCu%xgUGkkvxyEGhJdOEpkmo@Xx88Q_zdJ z33mAKB9`IPPxA))nqNdC*CnW1xFQ(rTL_G6uvKvd4@@b{({P#uBB~b@WaBeaEK#8Z ztd_9xRCh0#3NSt&{x*PUIjvT{s+k}F5Kb|FfZ2Wru{>#w=@+cu$2Hw2MpRTMZW6{K zaxVXG{`O{PC&te$@119qH*dc<43`$i)jfuP2gr7HZEWM3Cu;iYct*V3UT!d%f%+i^ zr}fh411hnCO61NL^m{ls6dIcTZM*zQO}oyWp28KUd6!fc2Tqr@h8SIeTUhC2MnjJq zRr5wQ%t-MeCi>i82exw++F~Xi$bo%@JA1g*RwLqR&U5*Pys1BVaPSf_(1I6g+TZKS zql;09T)4)SF13WtY0KJ0*N;GQ3mmzv<*~+O`4)BB6TfpmrDh5JD|H4y%cFGq4x_zi z9?v|^zPa&0JwqEuMguG=-vqxq?PzVh#Buk5KY!dTE!LZ_?0w|RWHyqrQFzQJ@46Tu zUp!urVCMH=?^r2A&J?!IAfxYkdzN3 z3IA|r9KSc|X;We@mM^B_3P)T1YttU4A18w$E$s>YRm+DYml<>y;Rb6}Q#CdE;M_em zm|V0pbLxmm$`WVAM!D_s^D$|Eu6{DVl%Vz9=uGKA{)#sOL;L_%&8=XRd2h~W(q*bY z*p_`bEsJsPy4Jh3Dj0IzOJ8>5tR(F+`X@|&Ug5&bN5WU{?*s@pyV|^u3TgiFS%BXA z4$`!%oe80T7;tzdVf*{1kob*41F+)VWF4w&SEXe%RRT58!0l9szMNf;{Fof>>j4YAsl zRVX~3l=G1BFnIU1c%?2`>U<}n+k!brx~7-ps`)yM8mK;}>xuJz)DG87o|*2BYDi*| zwFR}tf22zPEpXdj#KoTH)oo${qlOY(c+)zbNBYAeF)cLLw(%vSh|7m z|Bzv!ARhOw(&g1hn`fA%fK#)HW7`w$hW&kkW3*orJhvHF)YS_l>VF)}95m27E?}UU zs%hgqnOy?j{EaJLT?Sw(uMm|~a3#bkA%~@Q$K}2l!{d}Kd>Vpxc97U~-Cno-%!!35 zBh#b5bh@8o5hny*`GuZ`vXM`$V_oCLQ5jQ>^=dH?<5?>imT~d%EGYg_QD^{#Grl>RRaR5O4!s^1 zc-SMZ%BK!nVfs%g?GXL*=MRC9H-F0-@s;Q&%(?QPA`T8$EM%z|y4Dg*+|M@Kw!%7s zv9O8Sr_M~Ne9i_}r`DUMez|6jg%se#_^9>mzslSGks)IF7vaN~$$PKUZND`ImpLRV`>oJgyVfm{xR;cop)HCLH|S>YLYtXV zx0U0nu)8XnNN}{l;3Oshehh1G;kP!wJKmLdwyU^{NJ$M2g;qGL+)DpdR?+XT3(fGD zDtx-Q&_#Rt6b-8_K}Snr5b32&L<$Kg13fHCl31k%iYRoty&E&hkfNr!z~{y3>7Cjh zSe*W5Z-Jlmn>+#PsA6MYRGXK_w6ml}%@%Gdq)ULL;u%IL$a%KjlUrnxgGPkYItiQa zj36#yQ(pl(Bmj-S(9}^7P(CctWrM$WLIEtAn9ilx?1qgOj@!B#q@M!o?;B8+&(uTG z^dHP}Ydn!PcCuLe=-1No51lfM7I21@xS3@&oBqPsyn{t4pA|8%{cZ8=N)*g~czSBw z7lzA!x8hK))qF`1sT{(@gd~UXU0SM}*V42b#B%(A8j$_;xr3qApBGz3h2p?|gO>Kw z_7)ubc!ty0kr(EfMX)3et+o%`4Ig!9Vs0EFQN= z2{^bUp4(oo&-&h1%L9+7vhhmO+(s{p86KyLKs}{oVCSR%Pk6( z#>x3_Zod_7u`?Junk_^g-e-Rv`KYL(;xy_Hrco+lHX6pUx3@nyJk$qfh$j$#P|uDO zNQN90o5}dE?f|4FEk+_@Vj3o<;Bc}LWN@}YhUd{lR zG37e#X#?aw8DU{z6LxjNp3RcBykCQs#hRGEg_!uMss-EJOVp|KHwM=8Wr(U)eR^F( zD9scKu3p7!Z3RuU>$AHBij*w=*)&BJVkyHFN0D!$U78j)eXOzY;<0`b{UzMs)cFg8R)>ReXV$y&W{`I;sP}c^1E5PT1fdYHL6LF<(#W@q# zMNm3qcg(-~(UT9voUa?TF=JetZ(_79AKIR@qZgncBH(RvMpC?~5HeTn6Kn|9_<R`^*EvGvA^!vqBb14Ge|tGsZ=PXN#OHH77T5w5%8 z+kQt^>&k0rEPaHS)TpQMI?)yu z7V_Wk#J8PyBTJYC2tT>RZa99xfzz_?ZuZ|&HQPiqSHhkezYS=Ge-iX78=L(a7N$^ekVJR^x!Ef{4v55_KI1<0hAVG zU2AytC7*}11SHOm^XUXac>wuDBnb6P1A(@Nhx@jiG1F<&u1_pKEP#8mIEO%>Tn+jK zZR<&Tf>!b$aM)}lz4H?uXkTZY%H{A|dLmC9bIge_JF{)0lY!UwFKu^XZUH<&D8*$Z zzpFXy4uo7CQ2Ab;5Lz_RtSaBMQX!eRQ=V7{8o0C|p%RIH=yJ<|WD>NW_mo=HAnji&hYCq=rXRgTd^DHtM3Y2n@E`kgPVak92^?je0e+*0&RD^JRCPaU5?oCW(Ipj z)YY+fTxFicBqjC7%L}@}O1PW|ygpsw;NYC^3%#aNWw~ytqZd!`>}T|}xm~#)l@<#o zzu$eAc?K%0+?tkVqWGMD=df{lYAp!ect_^86Wc_4{QL~`7xdQJ+{)E!{D^JZE=nR_ z!^Qo;Z>kqh3UJVhK6hyaR(=imZbhnH(fY8u&MxcB_!^UUlX#7@i@8`etvKaG;*T91 zkk;o1K(vgS_$ey+e2eci+B}D_TAX=dVZNbnO@qFPi_i_dzHm8JG2|83^DzFUewt&L z(Q>_AyV9U{O#UKhv%jDS^?6~={Vik+??>79UtRz=DK(6dXrHg=komjj-)lMS6m-Ee zvD?*hnV~*fgsoc6Z)vPQ1%*o5$P^J%9-@x9>Uj7Uap@GaR#2R-xZMZ-qmb{AL05`A zEKAEzT(tiY3emq<)_Z(8z{>v%dxWdfPqUtoZO=l4qOEF=I`w9(7&5m zd7y$F-02LGM+q>y?6snyTdH`M8; z6-p`({>_tgDIJ+8^J1u3<82fNR^JwCjG9U~q<-Gi^9;3()asdxu2m25sa#ygqd<$v z*x%N54*beh;dw5`0U3<7V?5-;zMjDh7c>aCcq%DVYSOrCMg<2a!ImJI>ucB14OG|7 zcdvfe?oQx8?Dt~V>2ipQ&0?Tn4^~yy#KWZVC>JFb6(nj zvP7?5y}=e(`Q~xELyGOfo`hD#E(+1Sg-% z=|2=fWU+Jepw3(wf_CjE>}jpJ!aKGcxwy8ZhB=$9HyK@H$upYy<`J%#5<}H6nI~Rp zDBA^1U|;w9$fT#al9FOvTnKlDXgRN~`J1D|r%jJ}Ps5vTpvl`rCX}6W7>zluBT zJ_O8Wgn@GL6F1gv(B@)P^4)gy5-`O?*-=H5zP_1dMheV#%;Y6D>bl2iyXLj>@$`#= zXkw#@DdI?(jP`jPlg>mDhs7m|{MG*qqVd>Q=J;rk!Y+?&z+*-!NuD8lgdMHa`t%%- zYxCuE{Nw?PU6qJQdUn^qL|5A_JW)SRt-$AZY#fQzV^X4OhG>Nz&(+r0FJ8j(WvkzA zGr-J%dw`EBqJMPw%T67(is1kehYXS5#{?cQwR%HP!=rU^yYVt+1xA!Re~PL_=W$~q zs{W1{e)VDfJ`241{jsA*briw3yMoXFt!HwN=$M}O`4W8$YTf$K=USK&G^#A@y+5D3 z1iDt|0zbchoU?A_9}*Rh&NCSn6@G-vaEn~6b9Cunv3cmvN*k|EKP$S7XtpG053x0W z|FLXM)2#}IGC;QW&TZ+8!DeR8pzd~@@I*>3-(*GIGoH%eM2&?^3sb1L21r-9$#GYZ zvmZ`d?C$pVh*VUV4F?3YCp@VJX^zB{UE4)D*-o@>6P@1&vVG(wtejR@{^JqqO_nz^ zqd^Z!bUs6DeAm9d z6s21mtTfqad0zDKKVO6G9-|1^f<_oyPfFTsI#8l?Y+Hu!_+ld{nZ z3)_XxG#Q%q_Z9Q?M(|3?q}zNnh)_sd?lL5N&1x}6N4sPu*JkJDf~J>z0#`e=X3vb=N~@iAqAY^3H#fZjC?PiyeIaX*A2CiaMGpzMapIO zb(zQb!W%u?_WmK63HE|8Y@js%}ngO#FCjiEU9V85Yn7~S^ts?&J2w& zKJOoy7@%+5+u!ECQPyx!LidEh?oO!_N8yc5htcIro~mk--R-&Cwpp$M{hY5(i0qm% zAa_tw+45ufT~dTGt1NtrlW_g(=;~_Fp*8g73A5!6ITS}szxQ=T3R1y^L82wf-F4y4 z1uLS2*m4pOhKy)z5|b4xH~txqNXV7X+MzxNk%ETC+U>95ZoKA8aP_k6q%}p;>xgOg z`m8OYrU&xW>XnQ8G@GQhE$$j|hop<-8+{LrvkX)+iwOOp)Omc?*mW?vQi7d18k)ob>4(mNhQ(wj2CC1Qjx5;Zn<4K6GkM^0@ zkD5h9JpBG_IvgzvTy&MZ&gG~t& z7F7u;a8-y4!h9I#8k|yzpz;<`GZgZ1`Hv(Kz#RreAFI8C!=ty2g~fJhah5?(5NZSv zmH;xsOdspNg)A@rF+zqB2}Ua{DFI9ZgEl^onzXdE)O2))fJ(EoyZa_4J$=L|S-XGL zW!+1rQrgqINIqLmO6t94gJmd^1U`dCZ*M3z&&`ZdDzB4y_r^8AJ3jL9r5_!chlPg= zP3Zf4Bx&Ecj^f+626t`#t}#Stn0SZY`_fh{m3w4R#J z8Rdi<0a56#%3GO#h}tM0X%TxO-u1)B^gsxeTp`p#xA;K~9sAZZsB^d*a?JF*N$0jip#?y36~SU|DWk<_3Iw%eT#Yx8e$fD z(t22F|;?EL*(aMB) z%vmdvwf!FB3j=h_zcjT9l;%;Rw4UNMth?~Nd|P~mm%A7^@se}NWRH(%P-RUgT2N^g zG$xk#N$48^wOy_@b!9`ieNgsruU57}_?ws@d|9YAd9%uQFgzkd0J@<%sGfH1{u1 zHE5{Rbg?-ln`Oi0I-t6aE7zPT>x3jNK7PBQMnX2B$k>^qcWs{jXR|09+m@d@%zhN_ z%rmGxcp^*UD!wzn^-K2Pi~jLxj1r57E?0YJFWLMocK6ES*OFovK_iL9@1ABz9j`gV zJ6v2`1pf8OToFZ;L9f?UN_W#6BDyEZ3)i1W+Z1TYW%~F*-1WE6&y@<)Csz&y=+p% zs;lS=u+>DC@_6FU42Al|1}Lf0{+3;D?KY_21hBG1T=A>F*x1^+{(3{{BcdjQ?NlGN zk2^}+DwI^x(F1L5>*_a3{6-W}cZEk4mli7l7;@x84i-fg4dun^oN1#WyDr5ZWFVB( zHi9cPGuzqU->g0gCP{l6!9ce;-b%iaOTH#iko{ql8O2jT2Y98W6D>9r#wF`Oi6te6 zMpHPFEvj0xQo&Rk_9PG6g~zd4x)H>NQL8l z&N8Lnb0BvpM32sGxiR=LE`Dt3Pp<8dnfh`ofl3G2P3d~A-GxPfv(KBqaq<53JGHOA z!)NC;K*x-IRakWhk&|azciY{C%Uwi7D~4oH=5s;@G^;>uJ_q*h1zmkJq^3^jg^xD~ zuV0XflH2_)if&D6#HBq+k?;Dh{^ND1WhyhuEm8-mw$588C#XjojA$@Qzl^QCV*`Te zQWKGb3rFXvZQRo!QwfP84t@b$P-t0u@F=O3UUy~Jp{tU1&HAK5P9bx+AGZ9*>b#88 zAYU&Q@&9hmY?YN47Y9o-wI_7>Baq*+bZ;{IJT9+8!Pzg4uoAbsY#z6kKYsi$NNQfS z20&ELc7K9!o1vAuFkwnLtV~ zY`R&njJ{ugn`C<>*=_fe?$zGzI$!%K z9iXxbS>T%HeZ6r2TsvVSvL1fJ^cLKH`R)FC@^`w1NDjK2tL-h(>UIl^%n z=#p<|)|%<+L%xYCQT6R+V|m_)rKvI&))vMpFn_&>Xm(t2z;7*z2)FQGR7jAJTKk}p zMtm`6N$D|cN8O73mV*L!0zC1@%+?Yv8H?k)+ugfqAE==_@A7v4k;RgvUUpJV{|45m z0JgCNs{Ii!!Hk2u<+bJegy?M zfVP9qd++SyC~LIIz@_g%anbW=O;z0*_D8753*jC@G)`;kXiW1D|wvaXa~Hs@dvC`TqOATAZ|->XhgLRPH@ z4jsvEUp8%_ISww~xDiAgwASOpM@L6JX~}hYd49lODYh~yDu7G+CUxN6jhdc*2avqG zA~<5?E_<=%nO#n`fW}2h zMaAyzvd!7D^LPdi;G59?_3IbV>Im?j-~v9I{(98XZ)<|~BDX~0-D))-4ZiU7w9i)_;!%DYE9z=Rm2Qep`tXc67&NaP2Z^nv@ z+gT^>0LkIcee5}RyjFOa3%-83-B+%F{@zm{ka;Il%k*X8Wsc5uoSSqRIt6>19?Y6! zwqvwE1**(#%||^u{h+Lf!wQ&tW^sLFqZDxFquhzqd}N}z1TofJ(0XWNUGuz2M|5Ci zfdE@E6E}xa97|BY8gfzl1!w=eJ0+!>KQ4SY???J`1+J-49ipk4)~}lLx&33WCX9M& z<@2d&??3m~I(LH9B|Pv?*PngmPdm%bcue2&e9`|HJd2% znc?VLoHVam3E*hCvWy6M5`!1`$;%pT#gaeo z9rsPJ4{bVTycVAHDchdj2*^K&rKw0C9-ZV=g$A4D5x{4G$G;MPDBaS+N9Fc7*)4u)+0Qt}`nrG?|>^tv4GUhnr;5#r>y2sc7-)!I>snu3OfF8(r^1%y*JkaKpP%d~$~Yf? zfNr1NtIZ=NqDd|w^Q|oTRk>@9vZk*_C8Y<)>Ul3ERDRgpgCAYR1r@4!hDQ!WM!D%I z_k6K3#2xP2uW=gbPk9VEw9VN?4J*r-KXS=~m_r04G~mtcFcnSwHtMXYA_dwvxx?PB zzi{?@SNLkTY7D&`R+U2g&{-ne*S}hcClmN@BY=rDBFaBhDO*xZKL{kmD#nt{A)*`==eiHVY2agt1tXfc-aDS6j0cX7}6gE57ZJ?t=wEX?;&zr{!Fb= zN%4EVfkl()p|DbWIErx|ZSKej~>XU_)8t9q8b&ULOhTQmKVbqkNO_|$dU zn{9OZp9e~Rmdm^>ajCmpxFJPjqXr{Bx-Z+Ar}Rfcey>Cs-a)x z1HJuWc{;a?zqFEbL?jN!=&G54Djs3TmU%W4qhu9J%0$WvyvxRl!Q*Y2&hsjY&bqT0z-0OlVal*~Kef%>~##<573O`lY^X zP^U4JRB7Nuo141vu5;C|c~KN?#+yjNACt1ZCBUjtYveMBl;zEGhgK@jm$4K{FZYv+ zxK@!8V0{A=ocJ7-=);d}k^wvZ)Pes~=}%@{_eTkOZaC&V%(?daPe*)J3f$)W{!DFY zOSSUFMeOK3#&1-3HlAvNil#Zt_=h>vV*i*ikOF-sKY0eBY*SU^?&lxvtBzuy0v_B> zV3f;nCl)S3=bfDLAeJFN_iWt`BxUoKv4nI@t>t6V`ZIyGhH-I9htO;bmfJ_;oH+=^ z)gyXMF6&FW@S9-LAKSVPz994N)`3mAks>y#Oa;I5W{<-GFGyLiT-s3o^n&VQl5Il4 z?6H~W0~bp!&E&FFTP2y31Oo&3D>NmvwMhZl$#Anf@E=+XQ1IJ z1131Fq2gWx7zSa6)7($kw{NoC_ELM^AEFxrl$ju?i_j$F4F-M|aL)D&yM97o2f)0Y zbbyhao{yh_Mg&`5|8D)|<#Buei2pCbE6X@9a>wK9T26yt$M8`tGb!393JRos%z9_% z9CTZq*^I89(sAj}Ek3s9DPPpAjSR2W1i{*^L_Z&*h5Yhz%y~g$L9^Q*8-H=9=2LAF zaD`UJ8d;KSd^M7LKjlrkINkQ`tv0Eb!|P3^64*8&a$shAe}$cQDO4HtL~LrMx&i6xW+WJu*~vPQbmTfF z47qa>votAZch=&G)NZp{s;Qev|MJ!9NPIkoE#2@JaS<=b=}^tKu7!>b*GQ6AuOtUQ-{bRuA0hT_DJbkS9kPYwiB@tI1i%b^++@Il6N^wSld+T`B3$2Minq zOH=w9Q3@gs7Qm&{PY|C?F||XK-!B^3-;b_x?MQt2;IW@ z$+p?R7Cm*Zk|3jgDrTdtQ=LJubB4qrVnq2#or}_f#r)qWVz^PT36?CVz@@H!Q~Uh= za$5Q{8Ts<3Rld(NvvT}IlG?hW|99JgA>=T}VN~0?D^D_lD8b;4q)j zIlIaSN?**S=k?rL7WDbSA6@V}H_2W%GE+fybqp{Ohlht#cpNCl#>N0iEchRj4xsRQ z-<0Y81ApxS*H1ja!)HqWQGsazC`&=7TD}34TQ6awgO`m9SAdqEUD*M0*!r0XAUXfT zwE@dhqD%&N?9-E{@n}jHAWJs^$orq#d_P;|J-hF80ZiGc#YIUS9i62C7x?R3g%EZ6 zegHkl>FAKXKFoKjSL=0o^UVK}7r4QJnb&fVm2zF;W6uQgQKb`l(mVW&H5c89iOR~X zu*u8{oOoQ^u5s_B#?^+_%Q_dhqhNAj5s{+?7;hhWv9k4bhf!q41)=Tru5)+0Wb(L| zng{WSmYGl|a7{EH86PoXbG0bh~fge6hEKeL<*5PpLIji_j@D zGm!=ND)MHir(rCCF>@V8+_z#CvJIJK<1^wgXG{vmxnlKya;K*)5PdJ_c1l9)VPuqh z)Nxi(HGmZnnBCpaL>}t$pcn7IV#0_l=!jm)Lh&^EjD#+o!N<|c_kOt%`{cyUr)hYE z#X*TKWXv>UGzdbFwCb?kOPDRM)dk;Ln0OG^aW=^Il$!D~BW3Dhg2A@*n)&n7|J_6+ zzhLFIw(?oU;G&_Q@+rsqnwpz`B7!_VZbh(*eU0Y7MEvI+PbI&X;V`a0oIn#n%9rHl z_m;8q$)1Ra2#D1;WolJ>|MVUKFdN9^>AM{*lm+ldMP=pQngOyAj(M#fVA*W`v%4S% z2Zxpiq#m%Fp4qJyN+1T5XyFgXOzsGXYC3?W%lNmIh@^d*k9+e4(LHU_IVs2^ABfQ^BR5b zWkx~i%pOdc;bV$u68m+mn&;$E3375{4VlP5dYKt=)z<#D6|N)AT|`9{-3>P0YQHeC zOySLH8X-|oNE@xS!xm4&7 zN_1eC_EC#o$du;Ev0G$HIO5S)Ps$AQYk>k^FXP$Crrfz8NW+zLZ!eesszLqOmq>Eg z5OZ6Lj&KC+1tlJH5Ha|3256(o#xh`sgLMM6;_qcpXa3rDuB)kzijU+OA6x1WL^2?L zTxuy&nrBfX#f6J7?TXJp#Y2KR-GgKSKuRb2+PRF9`a>W0OH| zb~7{N#H+1gmix~&Yee>s??0=XNkZlo`9~F1QGh_+Hq8HH@x0>$=@O{`T8ltl0QxK> zVe|$xudXgxojrj-(G&nR+)s>Ny!Z@mqYCYfWd@^10#NH6NmG4s@h5M4n?gffy$49$ zI)R+9a<>dXY@Y}ELvs~irczgwK|w+DzPC4bbV@^d1@M|3fUAB|SAXa3E^-_q}mr0TvK_0@jWedB8a`9bWV zX~-1B8f*-U>^Q1+UbWusAe7f-H7#7a_hbA?-~QS80ClQYGY__`H!Z!2 zm;P{U0kpi7JOOUZoy=+7?_sBT`$WusVCWsrQnkmdmU4k9-${f$F1;Lk-h_n>%WK(v zllC^w)ft_4%GNvhGQHb-bf@&28=3}UFUlPwLI^onp2y{C!%Gp9<@+lwdlm>$f&|>r zY-~uSRbyt4PE^&err2ET05gte`p!2`UzapRG9*dzyEr+mSeeb7HSqC;yt99*Z@c5X zonOQ_HamNG-IT;s#*BE~0TwM4N?lH_T zG<^-S1mhJa(PNLMN1H2fWbHE0LO50s3Um^3E(6=7n_mGCV57Zsb`}7-ySJfWM?iOW zs9956n*?Tyy>_=tD zbFSU5_G|6~3Ia58Z6`vY>YLJ$VD3!^I?YW6Q)KS;3?~qAH0&=~m+jn-65}f-QfEC{ zsc}{;%(6Z4^wERx8L`V$W4i?s?#PIEre=MN&je z0ZjfWBMlxLm9Nr3Ze(l_&%A)t511Jb9F6lC>h%9)XwJdGl=kIQ(!{Jnf1m69o>VV% zXN|C@KS=kUm78nNdQ%0-B<1AjG3f*z>`>LGXqB>KSFp`P%LRK0*@TvLQ7*GL=U_*u zhv4}67cQ}rh%k~hL&heQ$v``DD=V;iig5t9fjL+|_N#3&VK|RH5)0>Q8Ew@w=~^^7 zs|u93gEi^m>B|RFj9fA9kjSI&4z@O|t~TJ`qf6EJ{Mfs4Fse`^U_njm6hwn(Am`-)d6~e&40K_ps zb&~vXL6icZ`v4g-0R9706MP5mboPZB6>g`avPgjF@3}aJ-7%AZqXpQC1B=)OfY;Yn zDFONj*}G|7X@G2Qc?wXW0%!#TRn+G%U!(!L0v8u|AXTVj3C5vb>NgA|W&>#=vGSaC zzl=-(;YsSW#=x%*APSzPy2oo#yc;4Go!v z>irKiQZ9&6Ib3;!3)8sU{BJRe-0I?Jz{5o+>ZWH@zb>&l6;@2LM|ZCac&Pa1sp`#U zQ~EI_=35uR;~&P4c7?O-4YX>AET6#X$`3%V@$(g}nyfPTFpnb1Vz5hQ<+$ z@8PZHzhC;vpOPWl$gN;Gmp>@6ukr07!D66T@BMpPGi!t0;S%QQMc-fPg|6zxiBTP# zJxUtP4SBKA@$zM_y@z{~qxt9{)Y}hSS_BCbf;!zgS~8K6M`lvKX_XC?UnNg=YGf;O>`rE{mL6#+mh{} z%Ryb1-(Op)2lZK7TLIv)jE%#VSm^=nJTN_{Wu>O&hU4t)3~g4;-k#?!50j;HH|jG~ zQBgrlF@?jHJIQr{sR2QUK8S|9${nD$M;8_bwQQS$hBxK^EP5T(ZH9IleD&DQ0m!^? z;AQ#tho85v%?`5Z!vkwS$T9tfGh!w?;r2%FxTA$+o@0EiPD~Y#7a5dMe!MuS4 z?G6P1bpMVNf>sp3xDV4&M*D+uRzzuvZR!XSR(b2Y_jPgl$75`LqJ>Vg2 z>VoL6m$7Ke;pCxV8Lg%k;+f!!KfAw?Iy7j+>I*nIW7P(ib7Pr^JT?9F_%GuT&J$XY($%)V0 zch5X!vrEBx_r`(0p6z6rMiW?t%s0q=#5qxdUK>>~F zpyHzv8|lD&yk0{S`RS zt#x9`wECVe(P-AOEVC#pBEH`<|22q{y!rR%dN|SClZ*CGG-qd(;5-vJDH*ZU)n5AJ z^+i}%SJ=%ieS`ne^46#v7M7@JnDzAcawVwKGCOOhqK&aNTGhnJ3^cm3%7vl1-lIJv zj`+}dsEV1k|EL5Yh!3Q;tPXtXK0;TXFqGT_W$5 zlX7&(H53pe^!62qob^`ZNeq|{V_pU!W&D*S-~Op9TjCz){!sonqL+dv0|oxC8@NTjjG$? zA%V@Ih^gn=yLT3h4$}a@GST^WXUNpDmF*Yz??Sxyjyp^S zT6ah_sS~0ck-YW!FNnL?{(>e>KB?C`vC7gqlK_lbU*CK7{yQBqFxDsULxv;>n0FOh z=eT(;vbnw18;k5yYi^fg2E~p2Ciln}b`7@4AOV{BX^)b00p0R_3U5Qp! z0=thS4Ko^tZylZk{*5qQz=~`?*H++huJz#a)+)S>j??yGl%Hm#a@h$ z)9vLN!_2H1QogLH)|oTVdmTLmr=N&4rgtQ?d#fZDyZK7EF51r>pbo|0ymMV$OjKbb zi<7VUsWOXl!hnG(&sILp>J4%$;DJOz@L{pU6$qxJt&KRH>EPvy>M!S&!gd~wZg1m8 zx0JjT_-4iICxr+UEVA|nd$W!T$e~W{Jb{g20P%WQ0zO98>2=xzzCkHH?Wop#rdD%y z`%lpaO10qO5W@>@QAZ-JBGD}S!W|BEF@I?Eq)As(gMV~ZF5&PDEeeBgfq&`TG5iE> z*Vs%TyP)bn7&Wbm(_ao)dM$5-9a*9QF1_LgPxp@u<(E+6m~v-ii@h)?2_l<~+mZ$h zn9-S^ASzi>^xD>PQ%e)-`2m!0ZV%<}Ju=q6;x!*aK(*tBgXaeV zzt;=7YB4VgEoNUu1vMmyq$#qnKTD5|-MELD$r`dEe#YOpZ=ED5RcD;llPn%}@ib)g z?500YyM^kWQi^JqeWIMvm~bPx7w!_)?Tm9kFl;1Gx+@Xv4W~>kaB1>U5J)`|tRbdV z{b{Ehw0}0@d^WKrXdR+J{YXg2pcCficygqa@>=;bww^C{WI;|)G;M}!@u(p;{BuE0 z6D{GY^F%4byp@*PH#Q=M*@AWZ0sS#<7m}b&pZH=K>_=6C`YB99X2$AG$?tgOyQWGYUo6zBiB9G-y;HCOyQu%Jj}5>= zI);5w@IdRsM!4dTFf20gysB5wcCoQwupl)1v)wEf;5YlZel^u{@53^WVWmDtZyp;+ zyaHLL1i~w}Is3ABxKc}}qCgvvUcw3%4@=4g*ZH@uvL%Awt8ukKZteE%iyiyyV7aZ* zUSX~}lBGGrG6*3~E0Agzzv)xnh(hO{Eb4w30*!9s;H!E~`Xnt?reCNz+;$^bFG<>q z68)O8gN8}w)+5DDR!LrsVH$Vzbl*!$Dec=~d4E{RCH_YAa_5no8P%th@?zkW8EP@m zDtzlWt`dZ2s1*FkD>7`a9c7)%sc=~LY^*!#jN^7F{Qy98*U|tE+CbxZ>NH>ctwp9j z;Ay(|!HhQCl8RDi;FIC!jp9lw>eA{%8|W_JwPUE{C$~+N|(v%q`xB5i`WJIpZ< zS7;2YI6^+@kdv|2m^d?9Finv>xc|*i(y`qZNeW(S$HuC7A-S%p??B3~gweAiUEzR) zEc~TS@4EUoB<$|gSEC~QwoCPv?r($1p_>dpO?;I7g0Y)J4=ZDjyR4rr;!s^vS~-fa znr}Uu9Cfs&I2NvpPo44jVsH_yKjQpO`kvxI4rHot50ql;o))DCBZUm1rB+tqjH;9vvTM26#kKHaG>SAxh-LZq(0 zead=kKdm1Eo_doI-*q>?v+McyIh%tR$ktk z=ws7>?sI!!?P0rgRfgIVe=93{yNe49#Cz^2O{wKL781D+d2B|XU^3L>Q~TzVLjrrJ z_muV*-wT~~Ll^P4g(lcRyFwMtnilbv-GB50i;88fRw;NQCn2Sv8r-%H_6#o0g~@ zbpv89ErZHSxLrSOu6lGPo#Nwk^2p;BM_2Yy)ES@i$d5g^fg1P&_?vz}GDzV( zEF%jJ2aihr7JgcK>MYCRaY9)wfq1T(&76(ErB={ZU9~g{d`+<{L%5eoT6#h&NGmQjnpnK#6rqheB*E zWXoKZI?AxRO5gcxo?@Ae<*DXZ>FIbkFVp9Wl@^8>Q|7)_{m-sft}f`j;|j;|_D&&`ncB-0wfr5hAqR8KkQ_!!4Xq#rC5O8#%j%UYMl6 zcO7#!O2uqrx4j&We~!|Ni{5$vJ2U;(NaI*IvzxBXx4o<~hAzQwzXOCYKen;Hhm@`r0jN+94H^I{G#+e?~aAJnN9oR@z+X00q*PGy7479j!_+W zW)}#Lia9#R`1%$?855vSATXGY&?tE$WhcwW&X|O+w zYEiRqSOA&{0tN;aXbl;`(rGu112y{`iw=6fdAq%>9tu4luaAeSHQS1Ib^#&nD8G#^iun z>HoASSQjjIb-jI^dAf9~mC*THCL#&w_PkGx0QUm(8V3Q%rJ}w4v0sfl&_Q~q)xcZ+ zvzBGI>C|2Y**$)otGH9Tgx?nnKzrFW<#G{qhzPxXEXriJ5UD5SHY>7Xr zmQ|i*^=)y=rL;_NhkB$*%PVhId@w-|5U$Q?;S^M}HacEqr171%kE9y)ZJ4*?@5+s` zR8EI}bEsRuq2~#v?DkG5@!hxdI#?S9=3B?7ZJtU6zl#H>d#BHGq`GjOB12>3ijwwU z&@1fCTJ}5)=COKc?DnVsoKOiE6Kje8`RH1{auK1`KB%x)7|xG}#Burj&>ZVc$5e^D zm|#UVy6l+I>b+>|Ic`ri2`I6TfFw%jxxVBExyvDZVp+cEfNJscG-bvH6CII z_%F4cE%HNUu;|ksplhYrN#63;$;cc3E0J+lrx!SjtonNFMM&2J2nTW`EB zm8Gnz=VyGag181Iw;5tX31nv5dC`Nclya4|q3=>snZHsC>Pr)`4N%jeuo=7QI?t7r zo@~5tBwJOCb)%p1XC`^-xQ-=^I=Q!R+xY%@9!LFONX6bv#_jdy{UX;k405|cfvNBD z6MR9+#>VUSL9#r6m=r(&00aLn$dBQIk1QSHPS^?;wOw>GL8q1K)$@ zt2=;B_;M>tWam#-?alcd5KlbafKKPj`P|>XpIO^k%n9}Ky5dKM2V9&&8&8Qp z=VxLLV7fkkYojeO>8rY`T^V?8x-q7sJYm{OzPp!=)OGCPVri{1iV*rs3*f$@W=!2~VtM z!`U`APS$A;4mfCJuZNd^rVF5bWe?x zu?*Dp`OyYpx(cP}`0*9x>LZ z?m%^is}=0FiLQqwl{RE_a|*J5-3~wO@1l)@p-O*Gaaz@*%^lsMY);CyP}g~to0nKO z8m3=V2yLz9C`_M|WS^ltd!qx7z1JUTGATUSazsdo*c0(t=vx;-@|PAJBio;?Vz}q+ z_gGVVLOkB#DHaHFuMW+znl&Z#Y=cLBCMFY2BNjuLNf;|U*oJBr+b>&gv#f#6pjl0< zYns0{K+m!S&|G=%(aQEWexSDon0?gLeWv5Kf^i3be}Jw<2`z59E&%*X3~;yg#pNji zpy=Wjlm}3zb4E*{-0t3|D7yU|=+v2*nE2|@%ZN4`W3175HmP;Ti&~6|Jp`V=K5%Uj zn}&Q3SO#p|_lnwT79HSIKY$)Ly+0&Ie{gi@3&HpKt{$(ch0P$_?u}?OmBME9{zB{G z(tdRaQSyE4dBIJM1JPeSH~myvXVW?-%$^!)M^aFg+*4gtnnQ)aA`M)0k7&(x24=5Z zrpk|2bJSN)>J3~<%xLAah@O3+A!a5V>g}SE&i$mWH9T2gw2j6(mz!sSmebM*8gSNS z@Z9+#p4BxHztY9qN?c**>`ZK(-)&*@be5oX_KS>Nr`V$ga~;G}kqXqix5kW%%1WKr z14ix1s8^BDRuzpmg%-*gmR4U|g2^`q4QJyZN!&hG8Fh**MC&80vfLJ@>Q=z=Tc>}F zckHKs7~sd{<^5W_z*$~V4h)COu`;4G>{0;A81z2b_@A-s3k8d(ZFX^3^q17BlZSZV zuQvEI41Hz;RBqo*x;PwC#OyhBqpv!Vl~PwEAgzM3qK>K2WZjoGXXn~2)P5D^!5`Oy z##s|RWescZ6ZRZeDD9Mq0hkaBa{;Vb0rNL|+F8PbYl zCl?}MpoACf?N@qL0#6`&pHw5*S1H>Z80aF7Bs_HXx;LDUD4U(dBz0r1;E0Hx9h9cK z5)&yv1t2Mcw?BJECzPQ7ov^~LvWlpnfU()0_y8gG9qS7b6Gzo68r>1KULj_ z+v2a5EJfee!tA1GWrf8elFXOGwcOt5zmB?3v%imyHkX-~yrH(qyax%FG5?Chb9cS* zAHbLDa6SEzWY|qObV^LWtkqh!jR^AUaXqi2>!*;{rzYi;b0ct~k~bN7blLHof3(aaL*vy$ehcj9lSNBO$*xX8Mvo1=~{orR?epPWw; z&9bQy?(ck{et{=-b{#$gj za#9@!H86t@caQ50u4p9TAm zy#ehu^S3M?{*=*GWP$XQ(aO$UUW2SV4D$|kA^g2PLr*RD&}p)|i6}b;@uT|`DvLB< zRr1};j|J;5_xE0gE%X{|NK1ZIxVmC1V~=RGkF`?-y=C9-qK1}- zaeBlL)u+U{bcx|bcW*LVei14DWLOHveki7Z(*S-jH8cCZv^e3{ZsCuxO6$~#Ta7j}{COpP{rj>?8NvNC2rsbb;?km$R;rb}wcngg zLzD{Jl7jod(WRYYT3q>jeqJW5)6`t2!eXjC`c?3LfOj!s)6#Hm^4Ag(eW$>+z3>5@ z6xUuL{S~72YDFA>4{mIzX_Q3UYJqp8JK~c?=b9bD-;F!C|a$i>Ac%{hmYE>P#4OY?F*;-UEwaCF1d96SjlcD!y>M!67C z#h>}l{S5e015l+KuK3hR;wb6MrJnsRDlI%Y>u<0#Txmg-0|d{%zP4EzSnIoE^~e+s z6>-$j?a}#9p}J*D-OY0O7P*WHR6IMjE`Ooe+x0 zFn8GYA^&nO#(1vMHAwxYO;aZc@t~xUKPF#+dTYy!nJxm?O$x6jWbX}=fvL%Xj@evC zO3Fj)yk}$)cpInx{Gm05U&~)41#qCxA+WZLWEtesSmDd*VFv&c<96Qp0&t%_=bpr~ z$S#hE^C255DlPRE8`{I>D?H$;O=Q%QKJT852{3Ni?>sf_K|K4GQ zgg>4RYiMiZnib3b^I1a5`ZPr_TrcL;zrJtnmjlpXu9EuC|39?n`-YP!=&|BI4OrUf z9bgszT-viY>ChFsdo1Gr_3QoSDI0Bc0smTM&#QGOVVZow|9b17IR$30KFyx}zup{5 z!><^W`>&tk9sl14DL#!x@UJ5jnf_w`-z$9aUkB0izYoG+`Cs2cc|wx*UuOgSUw=Zd zI0pFN%UkVx_#EL;K$+ zIc&@fu-Na<`A{!zps*$#SI-i8JB32`SNFeQ=GHdY)rGkKZvWbtD^sblko@Gxo68@Tx1hX zz`c=jeGEAHxz6YIp5%WUfaE?&8lGm{M1deP2Q?(_q-kNn17#1-NYUG49}){qQHFfj5P#naI?-!!0U0k0OhYZ&*ZjyoNwt1O+Nrgl?Z-B8twoCKW{*2Ov*l!@tJziMY7fdjG^~&6FTfNC3}ZC) zu?m2qJ)K=pe7ja<~+@&OUKD_)4-@_4a#^Z&K%UgYUq=w}f|Zh2YClO`bZo_f&6hG;OqN zH_t9>!nL@XUF=d%@$&FP?_nP{v+?*z>c#)Lzp><@)}rsqt7anz%uV?q0wgeE=jcoa zyNz{MGI6bab>b5)FVsK|+&j)$l{Ok}?P>|-mA{iOH(csnnz6Jw-=DxKdE9yVBwcBk zV>o8cnlHDCRx=|^`K0t`m~GRSVp`C=C200`y?>2)H^_i{&5zD`Z+=E30Uv~?dKQrs zt*^9j>RqO9h&k6$h#0@%8y1d-W?^4k9%8E5zo4fdopgCnw2%HmsNzU>_@l$#%)H$U zWu%0rdG|?4K_-| zf@~EOD-?Qv%sW8Ul6A%l`kb71EKt9#cn4`))L*4g|CUx(yHbB4auy=);k9aJNxs;x z;FwCJHjvS_?+Q|AQ63a+yf8nojfw%aioq`qRSIfXqj!@;t{Dm?qlC&%GJMw$klzAa zikym41`)oo7e3RmX0m>DE!P;koL4+G87TW=vbZ+UUsI6oWsko|0wCrE*a9||Yz$3u zH&K?dl?`7 za(FL&h-!EFFy7Ib-AIY+-(Cl)PT|m&=X)~q^+&OXBX|R2{`6!cP-Y$CIhOAnv9!_Z zQ*~f`$++pbDh3bLxsZJ9Zd=7C8RG*L8c!XDIPL@PlEW)*>Dp1^8%wK{ zyU`_jaZ0uChWCQh*x;*&9a&D!HOei36U)$PZSTvDjhs9gxq&C4;1yT4bJuwU>-)Fz z-k@HVmHGabwt;O1mfmSXzo3*qnj$e8_{G0o=-)hn(gn-@l()D z{pI@a+3fd|Khj*cb3Vvv#viDNpT?4YarP8Jf~V|kkgfiMt?eS>X)4cBRGn#l@3jwK7J?tHXCY9o6VNfipK4IjFIgATb>cgOFwFNLVU8 zRgIe<4I?d#`(X0kp;OYyk~k zoA_zcp=O5F?MGef^fv-K?up4w?aa*cGqb)M$mqgNq^WBlEiuH=MWR?6k+D;*HJZ_? zMS>nsQl-)nZ>slqpt3PqAtj(B5 zc2k^&=z+_#?fkEvlO6l;RneqZ7PSdg1#`s1P41+wD3|+)o72d) zs;DTyA@qCx%zv9zn101>OLqkuC$I@AcD`NPY>`h{8WH$udvhe-2itc#!>e?RhRtu6 zINtW@$f^q@YRKn$x4#f*0`e%lWg89AWx=Fg{(eQw; z$AhVPCjsVjp>a2{f{gS|kP_BAx@VbBzV!_@q|Z?%;#N<%exGnewH9G}s!SXTABtsR z3^X6dEeO%kjM(Fh$l6KJ@EQ2T;jC>C+YVG&OKGRkI39vmcamtp* zJA0nd4>q+tik>_i#M$ejT4=q>#z2hL-P&JK%TxEPMrzcBY|$0JnA&zdob^f)YtKi*Cs^n# zWydYG;gD_FbV(#@*ssfZ4{_1bjU{vddRBmHL)=Pvy3*53cyD^5ydh5h>{%>k>n3sy z&q$uu@o#Ta%4ryp&0tTytm^C(RHMWH&hnOWrp?5S!XGVAodNdHs{1|-&7|tH+V_6D zWtej$;qU9i>o6a8ydARwJF1WoWXFlIcWdh7O1~U~nA~pJ+gb9&kD33SYPCV;r;R@1fndwAv! z6#|G$_Ki&EoMZ7Jt}a27Lc02pPO!VahRxTOVH9H5ZPc*&@b{|wt5?ut>ySJxJBfMG zW=T)v+R@GKzVop|PKbv6?J|*G+VVR2?i*cTLb2a21@$B->$eBP&}dh-l;KLnO8?K; zTF4+yRWNl?4;xB_YZ}`#D?0O4{xDwck7Nmp`NEvSL0CE z$}52Ae7S9=F;7c32Z?#m3~Lf`96nf>yLhiX(jM`Rq-Q3oq;UduT@q82snIN|)BC0b zypDw**jnmAYMK?0h^1esfC{(bDDCk-bEINsRLlDodhnLCD98N@{;r29c=hvrZLw+} zq;@V7g#+SW)yGU8>uMic8@jdg?cd~*0_KjhP}0>vn`_f{W>-MLVOz@gcEo99U9!HU zONZm>)YtLn1pKs4kT-(~LS{{ZeK4?AZ=`wx@5!&flhk+qOd4IRFCWXW$zODKjo|bV zU*R3=6$c!YM!wtKBaxiT@DJL3^$mksegl_mj!}H|JD+3l?d|0jYD*LtQ=TjsF`$+F zO7wN_xkGhgQ#+NfAA8mECmnS@daX1@d5&tLd>uJhHy6$C9P%e&?JB#5reY={Zf2Tn zvRzMJE@OW$*=!y?v}m8_W5C_Q)}A)hU8_#gl9R1|goLg6Bky^O+t$Osf~Wz6K}WcdFh6$43bwn zJ&&jMmXu{-++2H+k>m)ikZZUSmi%wK8Qui)O@ma6`?mB8Ef#visryb?Lg!uT1I(a6 zV=4ltmJ9*Ix8qfR7lmE3&vDWoY-78h|4^MA$HD-F{L>W@4kNSa$x7)ANpE(m{?Y>3%|#gXov zulKZ}B-Iu}t~VKbfv1DlXX7)iW(%e+lsm|DE=w?r413q9houH38g|WwxnQiaL}+S* ze0xbLugfu#e##&JCW#)G)xgKjn|v-wUb&XeHQXhL`wQPyd3c#7GhyI0T^fl05~n}x zGh|(fSk)AE(xTwIwN8_xOWxM;GiO zVV<`-kuu=h{8KfNb9*c;ukM$z@-*=LdS228D2JBb_c4`)v7 zOL@51EbhV%V{eXEg*OhuTQQ3=yk3ry52exjp#AFlB)LvHaghTdTK@i0G*&N|P!dHCafn5uj z^hK|Rl|G{#hq}pza@k<;S&+rKEC*cj!3}esZ5U3Z7^L4^Yb;5iCQ_|MJYaBzab6p@ zaZaTpmcggTo30@Kd+W9-v$po%IelF`lj$-^DF@Osq48E!*5Ci>P0KE}ZiEKn@>WQI zdNajZ+-`;9fE9_u#H)P}@sP=A2&eyZiosJ62{ca+%uM@$?KO!{U6a%(ZRf`Rm>3ys z0>$q`Z@j!iEH9jg8eh44e-$&_tZ6nyjUt6ueAzA&+GcdB-D5uU(DIsIJ@}o`#D>vN za*u1VVCoH8b;9$XV9a>3Dk}rW*r0afrL`Fu%IAh76iQHA)0T#gZXDw@UdFJs=1gY|_?ma= zXi|~z<2ob;Ft_}W?;jfa{tE=oibZu+C(SsE#KfaxD1@k+Z2k<1Aa28kl$Z`Vh&DRy zR=%c7H%!O_1$rMpaL}ZBsF-GptWkWiSI4v)Qe}F;TP>MDo5Q}-QN@rF)=bAV8=?&& z?6=D4AK1hN85sATyk7Ll6euLQ?r~R45AC5*a!HUWd90`1Q*UgopIkp>F226nOA~?= zYM8+wrmt$%ifeED>hO=Hu^~SzloYB@|Y8w%Pybfs}G=t(a>FT8vom8gcnKsSE1#Ub#Fn*5Yb#<5?6T2M;c%ulVmOn;x%owS|3mXXIMh#<(hV zBm?W+cohcV!+wSo9~p!3jyv++93R3Onfc$$#Np17+lIJw=sznCc{CNmY%nyYVT3Ay zSn+mt6|%oB=aU@@U|z)@+9)yUoMv|>b789uh*d1nS%npR=W94SYV+SwwQ^lf zTmH|vaM(;4|EB!zx19{DdrLl;!JtDTEaarz(8@Ofm<%6LQZKwv6`6J%otAEE@+R(m z?Wg28vIMaY((lRaDq^BtccwF5k}W2sdWZ3FPX+;KKQl7Y_%&i~i}^66 zvhU&)!tk-fV$->TBBv1aUzZoH#--0E#lsel<@=i^+DhaM*-Jvo#x3piSEF6JtzY=>cC*xa+6%7 z<+UgpAs0TQJ;KZ%giue$aDp5e_x{5ZetQ5;$F$J=@W8q?%sa$wL`N}QBf;pF2Tw4? zcGJ-A=ugCIeDtU(NXK%0Fyj7Z);3YX zS50M-KDKZzbU(y;L)uzhnEdW!{2O(-1z@T-dDc0xpeQA zQlNMX#jP!+6mN02wzw8|m*VbH2<}o`3&mZE6Rb$F;10pv13{9Ill}ho-se5%PdMk| zLq70a$viV_*4*n}_geE;Na9eIg(+(CVBYo#c9z8O%0?YZz}L|tCy+$4YJ z8P-4n>w!V2-xf9`A`UeDk*LMiHr)^ksldBSY9P~s(d$3DH_V%9|G4@%~Hg+8R z@U0xVio3p;<{FB8+UCW-U=0GS+z}2*kLW;3?L-rcn=XsfroiU$R=k5%#aHx1Ua=eD{?AcQ3h;jH$ ztXj<#%-XRL2!-9?R5=2B%jYu>;)v{?LPHnt_{lO5X+dm$I~f$aM**_~s~0&3_9opL zBarLFq6EkTBzVY`;Kro+fX9lPZ<6zE6%}a9$`#o$WLuB4X5(RRNLqS@weFrQ>buUe z_#qx=y-e&=p-#w=CE;1;Duwr|Q2ij^GSRoig}o3Cp%Gy7=tzj~ns-o5O~r11-psUD zdGhJn5zwW=(@w}?_4?T=UZqhKKY3No+mqJa&65bMh}LXj>EGAe-e>j@+sn*ogrgJ( zi5O9nz}@qk)Sv-Dn-x`N7V@!U!53>SZ)llEY5Fw(?RyZRP${cd?%8cHA}>vk6~d;* z=H>V#T;`r%ds=)F@-S71iXx94Vp%(_jeZvjw8BlCDWwT8@aKHvF8o$m0~$G9RD@rt zalS(g-ccjRWm(59gqvB#g1(e$W`mHA_96(5`}a%tcINdCfY0x~+Bgg79i9e8DN=d`S?+JAOn-vt?^68<=Ndphh0)(cD%hI1qozS)LC^}ohtJ~cKf%e`ineI zXML|4GyUVATU~s0$n@trnF6-2NN&P0N|Tdh!X_R??U94J1OO*Um5ABLYYz>LGl&?3 z)#zhIWY7&VTHnXh#k{usNS!KolgQ5N;KmIiZOc37%pWjbfU(UTmS)wdv^BzUz5x#v zzH>s=ktV}AaJ?>|541NKm^OzX(-6<4D@oc2zPPPxm4+h9twl~vemm`AuM0ys5A0@U zlAIP+Z+?EB9huHJEx7?EP4eNq%AE#(8ENi}zgz*2nQ4||bojeF}(Y@BKxdBD|p6h;k1uPdtkj3cRa z9sFd=>R`_mLzc1I=t1F0*&oA7@4A}p0FV1POJWxT6?N6*IhO_iozYQ z0eREZekFo=P}HG{X(gE}Hjp?Ts=jSle1Y}rE&7}+D^rd#b3&W(tIyZr{Li`bS5R*p z&Ba^4DxhDz?jC?_C#O(vl3siWWPk0wEGCKCrHwx_8u~N|cT^!Agi634_|D)uR5|dYUhO3aVN+w$< zl0I~Y!@kf>I4%#E;BLV_H{;zKJZRV!&!gg9`6>?a_|1mjp{ff}hV6A&PokF5hD^+? zORl!kL$@M79qyR%bdrtAK(vR_3eqQqyPF8Q)x zz0)H!s6vZ;|DdLwmUo~E&XVcYWz>tt4^rH=?G=8CG^xG2vcUumvS zAolnbcQ#e-UX}gGP?k>|0_+=#cq^gC+FD6CQeQ_JJ|=xQuhEr!Nplu9e&ju!f01(1 z;Wy<++xn0yILy~E{=E4)m^#QPorbro1YK_hux_~G=pWCR>z_lHl@f(f`%|T3*Skq9 zHPOp*^81U+;oQC1lKRNh%Dqk-r|s*UV}X+qAPt_MVP|i5e}kJ_BjLlm%eMc@h7iAZ z#HC}k#Q_dDP+8qCz9#U<*Ux`di5cwj!Owk!(S5Y;8E>$u zbfs}LLuhaPHQZPc`_7~;wL0)9W)zs43A%K|>r&nV*TjG?WP1&pV)=4e-dO4W4)3e~ zX{A^+oYSAMo#DMYM+Pf?>6M}vGFyNm2GTSI@R_pnk z?ZghWJ7!(9qc@ar%`A^)X@IydDYN$~gEtBXrzLP4C0K}!VT#m==DVEB_BcfD_y-(7 zjc);vKL@;*q%SUR;k`YsV|TXsOxCV9*t)_HgoRAF_MYQU4-b~J&TCP&983h?V_0L7 zno4(H1A5QOg@CAdxf#W>5l0aiVyo2LH0d+YCyflSsAYSU`jtsRIWG>u5-4k8^2*zY z(nNOQuiY&ikATY(0Ix+$Kn5n=xC)AYX=!}ri?FXtY|j4{ewHV#)D}9#Cp|FK zXqRo{+yk1X zt~;RGmn((#tqJjM5xdVc7L!9q^+}4!}@0|p*H(dy7+#ZR{ zAg7fGGSy3Cw~cKL1iXoJOx|q`eIAQis%?E|reE=I`2YI#Wf|Wex$DPj5N~)QH&QIg z$svN%b9*nT1y;<5^3K0nva9-@D552u?AUQ|F(LUo6Rgs1ZTNPDwPj=qRJmGqs}?~>+5{) z%gTjKc4rE`%Ng+j?J$m`541YGz|#ExmfH=XGP5kRM`l?@A)P?%_F0 z9Z_hG{dv5lf^C*mVuos8iK|(%CJ*dtEN5T?jAncV=&htB<0|HSxY56IdY;*){4YC! z(lk#ye!*0d%^AEmxcgZwjh%^k3n&S^4dCH1ctmIAdB|=T?apo6sWrFj(#IxM@}ch>(ohRJ#G5|F1=(* zW5xSDbwW~hq?JuW&vrV!AWLOJb0ptY1>ix3Hekz<|h2?|YJ z{zeg~MTNJGQjG0?4fxY1QIfY{>JobAvCoPY=zmzW8ie^QwqdQ_p+REB34U4&mlcfs zUd&lLALNh(U5*^+^VNffpx@Sy69Cm7F55Z0k|p>#p$(Pq8ed%4_w_}#-Q2ymJ0JsI zrI{C(Bnk)tW)k0Y4bzCb{2QWjUeUnp(tS<1DSy*XhV6&yw}w zZKJ_I`<}kAyKKmQypzMrc#cn8hgekbpqj>GV#;su7pp;CY7tD|*x?5aFd5`ie z)Zr3Vo^0~c-031Kcm1xXW~*XbJ)ac|<|Btn5+>C}dSSoGFTjEHr#p}Sa#bG^Z-~fv zCYOk&iYKqNoX$tB%j32dx%AsNtzGqxVk9{dEL2>%*R1wWI5@j0r0LqIN(BhV6?YaC zwVWoG9*<9jY7e$_?hYI{;)>k>mk|OSe~-KHnyk4E?RB1%lp0UP;U=B-$bUTS+mBJF zy3Bf(DjF&yQzE=jO#w+!JzYmL$63i1FYJ1p7REJnC~t#zcwlXFQEF!Js(O077pDEz z=B+miVI_f0NqcIMP#7I|oQH$dv~rmMA&L0Q{CV<1>~TfsMy}_7z0#h^UChkj3`XKsf7TSB5}jn=LCe{?AV27Jg~q-8xA#>VlsIjLAc70Ag5a8TD!0W%n&*f2!z&u0AqjkEHjKUfIBkVRd&RF^8%3uN(I z=AMI%mpKpWCW9jYQT6h`9aYhqr6(zth$Ick*%e-9vj;YkMRq+*^=iG5i+VOYqbIQ` zvmXKrU!=kEZu&kvVli+REBe3@_pduSl}YAs5*+Q;acPT%acASlI&-@IBG{fVgL( z-}p%pq}&S>IUHP@EeBTYHgNk|HKAieQJ{4Qfd>KOIn~of&|fj7?W=*-w)p!d9kLH9 z*1YLBeYtv$TV*@+0;M-tN4(zJ8jI9K-#yOs^MAEW$V%<8iaQy6+=uf-QL$PUwGoytx5(cE`{DEUfd@WN(NvRr z9Wo}?z^_zAO%w4VXMXWK*RmHFA0HQB3b6jP3`jKH+Y;uSm%5Z0-`OQ;(+iM-b%MTR z3MJ9#54x5IA!6-YIP?c`wTp|KjCvmD`k9J06f*#&!6US9=A=C%N;&EqXX?3ao-y-# zk-7zP`Y)Qk@>ZO!6x4Wj33EY>o#97MdP4X79ZH0ATKJI9j+w$TC)H@vk-GzZjMdmU zIoa+c2@JGtL${iBu!GIH)czswD52nzTM)V_sa&$!IUnv`0$Rx`N(uNv;PQe?`*PbB zKYq{?2FBi?c8!7FP=S|WNV!gPDrE!V>tJU~kUY}0d%K+{vs}mBW*-bqX$Rc*!zm$- z2fh#Eu@4B6W&6};0AYbMkgTN)!-^13de5j z?FsSi6|cT%sw%4Q??4jLy+6Y$EMwbtWTJk8x_`~IhH{M{GDG{pE`g-T+1f6OXWb;=T={-(Y=CBwI+p-c2*pRjnk@>}zGW^sHYr5LLH zQdjW=)Ru482$^NA0%X?{aZ1m;BjaINV&cY^iZ@1xt9+2-js4IU)=-pMBy#cO-totk z-DMR%wOd{hvJUSHK$LR-KF>|3d$Us#hU9+t3nQc~LnVAt+@Y=lWu67vqEjiu3UM~xRC zF`jp@&&ndZ-|-qsbt7^|FtI$^L+a#!(>Csd&;BTbYYd1yKYLjlpD$kO-+YDv&K0@@njhK}!>WcI5xV~t&76`a^EqYyMem)z z3?@_FV&{d!$(IisybD>=o^N}_jmCNq&|ZowVb}P3zM9Jqy0xlqf^5aQb3b%o@5#rT zMg!A?rcb<13u&AHsutPz_59T88WLkszf_K&(!3$~-Z4^tC%-SLrA^ThF_n-KH2N(0 zTM^18+A|kB9N6R)m+ZNDZi8Dkg7`ey);Y&waGql0U|}LhQ08`n-*UE@)oh(G`JMy3 zN9gzX;cPO1v~4ev5Ry#W(6^x2iVF4xk6xO(z)7d2!<6;jbY_InnWxN9Dji;bi@y z*&N-1X6Z29?@2>FHxsD6!@o4QDz8@WHSLO5c4Y;WnBvnUYKa4CK~{VKO|d^x3t z+HD(*|4E0m2k9y475e1Jc!DasLY^O39WaQGb-Oi*GgCuPApcoHI|HtZirjfdRIvxDtbF2O>4R*l;c$$Y@tgD-6YZ! zOBMUBx+8X)3?ex{>cn?jseNDJ##6&S9^vTA6`9@6CnsivlUKpg*!gOt=6a%~CJxYb zX!ZzKAbMmmlh{MQ;Y%kUY~QOS4#6f8nFD^h!qpH`j*i<}QntibvoP$!tQl6dU2XAI z#E&|i5M;Fb!EeH;mfIYa)~^Ud1$=3d?kGS}PJ;hYhq!a>xI9Z@HpqH;K(Bm0-&xtI zxQs()Lc~(bM!ri?m&DB>`^8v+EN0xDss(o zvX`q-t~;drWySUN-V5Tp#@|+dBGLEEDBs2FhBXCgun0HXTWTmd@KTG6gwwtoz2xXv zjD%?=G#m#+?Qa_!FrHF<{unfS+K`P&dn*T>h;x8WI+v!33<_U?AIX=;Vj)kRffvS7 zenp-oKNGYx2a>oPoqj&}w?(BrZwbZI=N||ZxeBoUbJ2lOY1lfU)&H{eti5*^Kcx@Vj;1{#5nyyC@X0KVthh+^b^#1gcjoIT$ zt8{ooaN#jX(m{&bRKsrWe}1ub+|}(o?EJQ{bh+0DAEz7Kn6AF(exVq3#;v z5tZOne!1*c5a8FBipiHO^X%)JVEHELz{Non1~<^YxZ+IzOdHsGfA0DeH-I47o?3^k zCyEWdO{w)gDTb8;LFY@ic1-oE=+}VN$&m*sGEjC!ABO1`vq+9pnc?45V&bIgI=3Va z;W%h#@KkAqEPn`1-_~MJjHZBx2OvE>+~Sx?RtS0G$k%jf%3udZW$(Wdq&l`pA}Sbf zy&ekHw{`9|8~K}aPz_lVx$r4L*~Px6h0k4Q7HO9UHU@i_eL|Z(Pt9NcN{GT=blUJI z0ICgU;`(<${j6(?c77SSZIfQc@Izn`Go;VtD|S0}eQwl-hsq#Kb&lCQKe`1xHMQ(l+5fj=2^{Ps6>T z*%vtSX{y2qoT}Jg9SZ^?10I;M;F{uM7HpVV{H3`ik<=jUIM6B`LiM@K@TeeE+gVl3 zDnSjZ2zi-`@~j?!fniKzsqMWU23^7@!EUn)qnJPhpr7z~DR^2eJQD?mQ>!2CfrVZk zefgwW=BifUnshIRz`#rWso)h?yRr8X|9fmqAbWTBqt29URzP)IetjYUf}a`TskCTv zH_njc{$9^YE4k0@e3j4GzQ|PTDxc}oA1^lcz4IWKY0}o4s#vb&Yto@?MOyYYRIWC) zOSw%*;8bxVv8&OPfsAF)DG$)wP3_%vV);$~xB&rcnf&vh=;*Xvp0e4cCuJfC1Yc$e zeQh^R>Zcg{t{+8KgtBgG1I%r0G*G+U!`g=!1uSLJoo>Nv95SWc^%FIGJ4%_&*u5y3 zPERyFB$`dY=4S2`C+*!A${V7+rbjp9y>ZdgjCwjrdgLD9I+fc>9jSR8sCwJ&%JE(0 z+IxUlBTqxusr$;nv`GpH9zlmnwEdc-rlZVOe2(G_H*f6$*H^f3LQkd&vUQ<>C3dr( zleTM8+C_6};X1H@sD%#p$&v_FBdEg^x`mD#_F_iY%p@I{J(5cH%ckfB?!-Ncf%YXdG z**9ZjC@E@BeUZTwZ8QJYCl?rwd-H-tIlvR4(#=%!%=ZwtQeb8*bR;3!p+A=|OH=8* z#Mku?gfRU&FUCsGSdKluhU0f9f}9HI9%HVDd4oI)R5UrYJ8rPkRsh7!Q^*i9J7%SU z5H~=HJ6n8eyDZRsaK2=$5!((Hi1Z%wC*(4tAN3Pgwt_LzbvixEP!hxVf!t)~KKl@lHF(A7*yf<3?P0ugl3oIQv8(adl&5vTuQZ^3?B3u6(|k^GtG5&UkH68 zVvbt&15A?ZcMqd;MNmJ2f{ZM6tFMy6*)3~@t=})766QZX&+BP?vR3O_Lr~b9Vc@P( zH$wL^jvm1MQd9hDD;g-i7nZGdi|!*DFJo?lo`IownWFX*zfFAGPZ-ty8N zf+*6a&V^fWp#ddM_ZN*`fenI>Sw@_p-0L4$5WW?P zBX7lUZN@#f49xoC$ zfuq@Id&~R#2K!xU`n|5A;{pwUtQRbh+Lr9TX#4HoJ|j#&JNRcROBr0JN$sv@Sy#2j z*D~x?G?n_xbcF#LkNhBhR;0fnCsItaRQd%p??KhEqwjz1k|e0jiyy5cro@mon%LgO zJthq}XpvU50+zRv?KL! zu>GmzTpC-<&;V-yEBEw=*8Buhc}BLJz5JJ+PImwZ&c}K$zd=uYg4=c>!Hcz&u~kG@ zaUuQfQ)Ca>H{w&JIWjzarJWt~CpF*Cp&L>zr;(7$4M$<)ocL)`?gY>amho`cMWn9L z_mk>%(XC~NNP4F2d+Jxh!8QJs&&{RD^hmRdPIDsKDe`6D!%lj|9`dE8~%= zdpNfTb_;a_UHCLmQS%d{M^o1Im?xmLjO13PrCfuVO6$I+iYE;{HzC8XmPQ2ZC_CI# zp8s;Yv=%5Oul@;Pv*>@AXPTH9!@&8|(~Sr;>fvOZH)7_?f(tlpYvp*QT9~yjj)mtW zG_WoQBDwbYXR&T9yIVaZ9W>@y6-wf#9RLhmTkT6pVyKRafhZwnY~E*e%-Z)X(>RQs zcq@;J!vb?}oBm>tVJWmq)Q$x^2-gm+d0CNf{gO%-oO7SQ+csa`ZcZpDEq6$|98&SG zE)FJTe0?bT`T~RxY{rTU#NOge$hAi5)PV?qR&n-7Woo003-*^C?;Dk<0GN)SMp0u};hI3D=ji14V59~2x z^1oT7_e|ZlBbG6O`!usP^ztuD+*sFop>9q_A(^~nBp%^iA@#`6S6pOSiyeJ^mj=AA z(bFQw)NDAM#N}1;1y<$W_HZ2DJ_ZR`n28ZqKPUQ0Xz3wx_xVZ4*yHAhR^MoviN_=1 zOr1tt`bDAI86}g$FA0I$BoyMjnUoIBWour$zwt@#_~QTO16IDi;OCk4jl>nVyuGB- zI`&TTA>2FI;WVLH=a4YUryDo08lC{Y*P$WGFV6);)7583gAD;@K#i671 zk=+Ka=vyEBUWL7D67!heP~7;@g_k|a5CcYQY=F#qOe2hV?;||NR|ERsxf`8x;Uy(l zAnDbX!0A6V%hHf?ac^o>25X!3gmmeETlqkT4fhlg&xIGYCyv zG0$G&W?HTGMqEJC^F&2+OJ=M#5y0~9_UNcxwG3K|uk z8~LR~;80Wa5KQ)M`|8DMt0yTT2!>10bcNT|Fli^$FL^m?7bV}oG+woJ1a{n8FB5Gd zE5Yxg>3(smfBZ`_me-myRU&ON8z!TmxOu92_C^l6pU;oQ>6;~xt~w44hUWLUHN4cG z__l^eCBXJeoyb3qb8C}fC>X#pmqejS^j>9cj#b{(dVQ)=-Eo52!oz5HY9inErF>~- zW(LsSZwF4TZXZ1CJVfN&-0H_bbV4v>lfPSvYc+$HJ|u2ot+Se+FW#1-;I~75*1ABN zIZO53K%=fCbIVme7*j{_v8F11o(8q`S!n$&XW?U)O?|PBH|AHz#lOuT9Fe$W4>d^7 z85o6d{HPty*S%&D!w$D83Cttc@L_X37uP?9xr7{Et;j-oknM%w&$F$s^oL zd|aixZq}l)`x;?RN*T4am?`O8_GV_wm zE@pOE+Qpxkeu!pILc!$M$PkKbWkKEbnY@EsllzUQ@j8;9HQi%;7qp+UiNP*D1F~Cz zcCzRNV)KO-gaj>n5WGE|8Jw!rU&)iI5i<-zPGhS!ncG#r)NVR*Ee(`z?Y|kK~@tjnC#R+x zRS{nGfd~W>%M6dGzukTw)HSv{uqb>pUBbjYB9rOOk&U}iv!nqP_EVlO4O~bq@0_ zrO{)fX;jAt$x2zdS+I`Jz(4X!kSm83txjuC+4}g?TWvxtqYW=7QY^M;r|+JA#7Z|C zTlQhmCac`Da_uYxPrktY9^VsCe1Ddw=E~&Mom=fHYC0DwNo&X|}_NC45}UQ2R6qG$BO!bqfw&qW8>=Mq)<5lt2(#2$y& z-r&`IQfM)V3%}jE>wxx2D=z2x)Wn(#J8^j(bWI16JUwMZW)DI~Klzw6BKX1(d8HBF zL}s#Yy1DATCCq5Rt!*J&M@!B%ZpL)Qrrp+e!yunqeoKnWNgRAmDQbql(hB@=29u9@ zIY2U@;NaW`E5or|8<+9$&iCBuq5B0q);9zF@(GEAinFZvflP0H{;ZOHdt%I6ccwEz z?nZDk+8B0a)X3QxG)$l>zbu_)#69A7-R+*HBN%lyvMN62jinKEd3=DY!`Gat0jmTc z9JvuQX^Cwt1JTZA50al6neh_4b}qca?hScaWcVl8{|=x$MKP2C1R<*kb!Qn zF7Vj1+X;-AH-F@JGxF6;EX`4v1ztF2d4ug(V{JBn?4lCh(|UBT3{;Nh!?rT?c)Vx-Do}|%RV}B(b2NW~!VRx5XbkBV6NJh`+dDV9 zWlq|Q)w>cVfB(cefAD}Hd3trN2-sp2#={5c)*=;oQ`M@do!K@sy8Vjy@O3i=Bc>P^Fg`e-B4X+;zpG3AoCUb_VT6HqI!dqh^Qm zMc8P*lLRFeVFo*#E-%}8#8Rn zTr0t)0{Jn7-o~O%*HWbP>qMAs!Q%Iz%gV{!1?sY^P&>LB&YwM&3qwEf<9*E`S#MvP z#;H90^XwN)zIS&N|5SlY`monfyXP=aVBoWsCic;$HDr(s-^KF&hRXA86-NbEiwIEs zU_t;-)52-~i-1Cgq0w&nqO)STz>_#yP3)JARhAZ8#2WhvHfkTdCVvZf9Xz?$6Z3lIPkD< zbq=t{tnDJV@ZcHLU6?WoOIo+)Lc%lCb|9w=cQ$-o{7X@=dJNp240T!UVhJsIbhd-g z1y|RtwYe`U19O|q%z6ZMhYBLRzU`Zy^!32ZY+1d_O2}C7hzn%tkSRC zGQ2t*q$6PA;beiF8F)vg#@=p&-&!Ypa$0K3H^)ucQ{|WOEoDgIqUeQd{IS(hr5|nP z+Hj(O`|U++=nJKGNn0~6dsJhx`~am~wc%v8*_q?Y-OEi3;cV=#fRZ5k$+y)I`5Y~& zeyrJ<4*k%Jh1axy6ngi)@(_b~Lrfb~u95)4(?XyNzyPoV5Bser$fIs;`Nw#7xJ_RD zc&T>~HaDfMFZo#+Jq4z3f}VsK>q{w#nTAR>sqr+Bvhy@ljGw0+G)RuJj^+Dn@*1}jGi}&Qf*Z1&7_unuhCJ}v z^SUfVY~*i8Qz0nz-fe%E%K24zq4_!4<71#$9&}Y+~{)wD6TYz4p5{+BvH7 z$QF>Sr>^2#Sm6s!^CX(v#qTGMHp$LfTGsJd!i9Ju&DXuQ+E?}vw#VKVj<&9%il3!< zc&=+8*M+hR5SKbdTzf4g9g2Pv2CTm{sZ;@73DS@+x7+6ESmXM91{|rMV2)SIu!eDm z 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 z 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

A%*ncq%fq?#;k0KS5_q1g)M7h@ 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 literal 0 HcmV?d00001 diff --git a/images/zh_CN/chapter3/tests/udf-3.png b/images/zh_CN/chapter3/tests/udf-3.png new file mode 100644 index 0000000000000000000000000000000000000000..64bad9b7c486eff3de0e2f859b0b614b3ac76222 GIT binary patch literal 9506 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 OLQs%VkuH-o2>c%y!}v=8 literal 0 HcmV?d00001 diff --git a/images/zh_CN/chapter3/tests/udf1.png b/images/zh_CN/chapter3/tests/udf1.png new file mode 100644 index 0000000000000000000000000000000000000000..0866f38457f1ec3fe393a56c0b1b1fd45b4ecc6d GIT binary patch literal 12946 zcmeIZWl$Vz^zMs$V35IGLx2!SaDr>lKyVB0GU#9l4q?#XI)soA+}+(F!3K92+zAe6 zvUm3X)Tz3k?}vMCRoB#X&D&l5u3p{mv!36YPwJ}jPjD!4kdTm`C@RQkAR!^c5Z_0! zFc6;(&lFgZkm!*VWhCE$kq@$P!K6J6earNp(Xg;#NZ77g006K=g5pu5&bI63n&<9L{bVt3ZrMx&Bgt? z*`rp5<;xQ&9J@(Gf_xtwfgmI`_zdgOmM>43Gt zKnWD)e>O4VocbHQ#Gd%S!+Vm<1JD%y+5A`~Ko=BGAxwXdi{$A0pK~e)tnI#3Czbzu z780G9zk`U5(~x?mtaCVH{+?x*SaKij83)0@(%QXid9&1&v`&Saa(AY!t?l@Wm(uB* zuj0?oF&K*aK>#8(4d{lT!tUW&&FQZwbVI>t@sH$GA4S#cjuu$B(l-^f*X1)}{}Sk} z9B>*J9L!YCRz`dCo9;#SC;kR5(V`L1$|sghMj?ESQYCXI_4~+P~qzH_xu^vL(O5-@m5Nyb7Om5{cMLCQ*ow% z=Uv)5J%$Z?I?ICYPb*EsB(%DJL(RNGj2u~{Mz4qW_s%>;?0#NJ{x95&h;U;wLm2)> zl4T{M{zIc(Rut_^y-1}uH4X(oM41z4Z@;c&>VSWL6WEl8Ejm7wwjD^a&*Z|yzcuFp%nE3XIc?|Uv^17>kWC{osf$W1X zN9QgwHiBc5GsIt~Ec3%Anb<^>zKYh>Z;ilW<6ukaTy@LfZ`PD@pZ`r62~IRWVjV;3 zpx@hNM-|0mATP{Gcs59L-yEnW!Z?i2Imxc3maxeIOHFj!;!Y-%#_S&l7WJ@yFIT7o z>YL$l_}s>sIm9MNXO8uTDrtwh2d;o)sz8hP&ow#?w zZlUd^^+?Ju0TZq>(z`z0Y?^uaKpCx1FV@ZqvcDsT`>r{GPjZChb;sJKYZqVF>#ZSTSAB=-7S;UZIg1e8tn!oL8B*(OK5sb#<(++#G>)afc%9wGrU4@LbfDxxd zDK>@@HzkP0UF!7KgN}}iC@VZBq+eL1vKJUTnpDVw!||?b*bBZ_D#$eiESeseX_6Zt zvlp0idhae~IN~LCT>fgnj?+5pmyveaqRp0HS3}4FWO6NLNx|jyx+N;A&-6aJs~t>r zi>2$DcTMZb1qwLJ-0&2zBB+qvS~!v(Mul19eV{PddqzB_OU{c07Bg*$dO4cK`q?!W z{%W-cIQ= zd@mf+UOQKao^1=xbLFDe!wZa}fCnTtlSPW!ObwSY@muhHdQagv#sar$+uuq1DXKK5 z(W#8wr5-)s$m9+1CfI}!abrG`fEGd>){!uXvd4}AayN#T*jj@m#KwkSZJrroDkYbE z?m)dA3>nb0{Ain&Wx(|gPR;(H#H|aB50O>U?q@fe8w!gyP(HPPPG@FVDzLyKMlZ5d zI*DGAyYH?f{qAjFWaOYe5cYjm#bRRXAV^lH+>q~wk{mpC`D)%U?R>??JgIECUUm>a zS?O2l>#gV$0`3-5Zu~BZzQ^{e-$N)bFQdrNH@Z4`&@y#;Q)7**OcSzn%0><<*xErZ z`)O=zz~E@qk|IisMpc=`%GBO*>w?>CSo4hVV(qAP@k^EJ+ZTRTBSueAxvxG{>!lgX zbV7>siw;XL#UeK(i90U&RGt(kh+vS76DGM?Mnl}qe2p9`}DBW-l&gN&%ppZgy&1J5}RwmVJg0LA(FYg6%g#sr*FvP>_^&cXG1thQCD^>| zxXZWQkvcrmp(*wYgQ@wG-&VfC3%xt9Jhesu3Q$u88$C zbqO;NqB*J=pP*70+EN)&$>)e)CCW7rG_HKufD0ann^&d~*-^L8V@gZHtlNv~tnOK7 zo62THIY1`T)GZ-EL;Aek3n^pH^X^<#G_LuE7udI0PX%-XR*^X<_H@Y2m=H^r@cnH^ zE6+t?ZsVH;__>IlwdexfGi`82r$PEl!Lg<>p$Stu+ph)rA|LC`t8vfzTqbPVAwl{j zE_-X}QpXUR>2-?J%f_)i9=ZHNS zP@@0*fZvwG?mho;VUqee+nsHDWGDW?9LBKqo{*Df3R0is?r$!GWIwd0r2{Z)K0CY= z;w`V$pk6xo8#{X8=Zu2*F%Ty!ri73HXSY(t@ukEP)-8EK`OlS$RG=>t&NPb!EX6t5T!jtQRJmKWD2+|m7Me?pd?D1&Ek7j}Y>dRzIu2&Kn^q`boEa@qMT z6ufqsA&t;c>h7O!srw{dFQL$ySS!wzMiL$Iohr`1;uJvG7%GJKul!VKw?-k+fd*Cz z{{1nh-WBh!stp)J1X>K$67*MDNq{!V|C6^+Y;{9_jKQ_PXF-Tvp8wax?$c6g)c?fZ zON6=`lhC97EB4e4g)shao7fL1Cswxqj!N3gj}=CXPWkSyZuj^}W4sucb}zrc0NZ5yH}9JLlo_a3PeH;y1*F-O-geOONl5=X;wgjV?uAf#*B zx|&W&RgWeEFeP!fv_*Dd-y33i8^h@R;YL~H!*M{X=d7m%*M9w;QF)Czt8(_UTcx4l zDONF;rp532^>;k%L{ZR(36srIs1b+ItX@!S8bY51k!4qSMSqSu$7r2G<$g1d1Mxd* ziX4>Y-Q2OQ^xLGYxV8AD5MO3ovAeWE5-)iKdF4RW$mJ^zOcOWU*k@;?DZ|ds`Bu4`&j$;(6UUubsef!A+*;XWoNseLLOe2{i3&#AN zL_o@&V*FY)o@Gcot##JlCU&9Lr`Umu`;{%XEuX{#e1oU-a~Ivi%}}3muDW;2_?`DH zRi(|chWBbUn}z?Z4zJIJAiGfWa_h>DichK=WgzcEgMBM4&Zzi@aT)J}lG)R)56cN3 z@AjlA{LiKs`c7Xf$!6=@13^A7<3E~kj&m+P=grN!^o&rxQQpYH4TfL5InyfW-^7(! zYLv*cMUBT@CcbuXzF=9r@LpAlHxR=SeRQAqs9agb^>4E-D*JrntH@Lewh_PEfN1FJ zv!)nMjzs{RZ1NR$#b_gF<_!c|s&L7;^cWEDX!eGZ^m&4h@N4si*hcAXsJDA2A%mgs z1123V?S2IgAVitYrlOi<>F&@zm+SGtr9kxhSofA;UzKu<5(GLtw&MEzs{J!xmQvt z_RxTZMs}h9TGpanyt#*tkuLnFv@-OgU9PhKsz=k4dI6ncee1&lf0n7-Z`i#hP|nv? zjROWPCa>OV@~Z%`oQ5z)_y%|ut)Qtan!aM3MpPdBu$Jqy+l^D8z<}H9{233|Hl&>B zc#MdtAjbIDItICd=2iWbuNle0y~!ZecQzAzrQE!ixx0JPS51#b7AJuCQ9W(j;JL`* zhJHO)f$Oy@t=_$Sxu`SF%PwMtbRivG$@Rkq#mY)b#aPXz8LlSF4Xo?iBDL9%g1>S0 z1e^%(o-`hdQp~i)F1Yl8&5?b-l^h8Aliz#ZW!09irK66D3s{+!90=3FHdBf#LX^3t zO6&Sq)In7t5wy>V2dFfRCL7u=NhfwmYHD@Lzp49N?vlPpzAyv)Iz4)}(VTf?n;3QQ zYL1jgq!Qoj{V)F4Jn|0}_SxJux-DuOK?`>FXOZ|*om)fbYn&ScZZf5Z^rypbhlF)O z$M|cOSq%Irilz<1i|#gCuh+jTe3&;h59N1G<^pikJG^KsL^dmSvS{`eT5i>c*S;{r z+aoO1SIPHgnr+<6JCyba&W$=76B#1mGn)xO8hS$THF+e%M=a`mZdAxBUkT{(oVzTs z#)Oo-?ptWvv z#@H;{5JaJw%KMCfhWF64UR(UireV7VM0Af11Kr;7^E$5*X~GaTfuj!R_)|4DIICW? z#nlS#Mn+4|_c0eEwCaHY8s$GSRrLG{8Z|@%gPktytQ401_<{Fh?CSQT)nLtIU<6mI zB6CwyzinG}ZkE$5K`BsAKr3(FX2?z^veJpnyc^#lYKL-2dDHRnY|H+C+3yC zY1QQ#SFLlKhsfeP)Sh}bI5C{6s1aXZsmAX+O&uE5`@J1I8kDu#_;mh3HxG2%E__k1 zW^tC0Y+0mTs*{y@AZ>Jp0eQDiL{Zt_n=1lFT9=GM8qzlE@fq{5os^`VKgZnpS)S#{ zWw+GOMAq-j|DgITmiqJljY^d4HPnB|VmH~ARneyf<8;~RFiDb&`zNOru8wp4D`bjJ z>T`Ra7!b|ltH)kGJZsJP3^jaZbb;riNi?JbBh|%ymu;n< zL;Qu@yl3HjJ>;cJtyQv-gC(bjVp?d76!sD{tFB816wPShM?`&ObEs1dWe`SDWGHn> zP$hRO0;Q=UDohIAa_De&odTtmRft2$D8WwVcM%>m%4u^>WHXGwkf~y1nD2)hgIWHLMx6TbW6HAn^(x5}ViC~4nl0GRvo(;(|h&Xi7qqE{AS`qQWCVOen2e8lveNxvAc&-an!rGuwDvYh6uD8+(S=D%0B;)G=+P2mv zXGV+`nCT+rkDZRWxxZ93R%^xg&`FnReu_^uY2tL>!)*T6PA{D`ovYOU?1E`O zgTSNb&Y(WP+c{4*V6)!#%yT{dr(d}S#Pf)Uz{y{zLy2_vz*CEXmRmno{H)Sj59c?% zgi*!XLc=aKWEPNl@k&#obhCnX9=sbT18{K1h=67Ac} zNCr||QxNf%fa#aof&LPP%tLf_fJL{EG_!5y4%6(|kc}f7L|gqJO5W=oo@s&co`l%cb85d_vgZ$K}_6`@dgDPQm5v%Io7HL4!pGP||6Fi`blP;) zVQ);yP}&OLwbDI7;o&De8&gEs`>vp{3|OpsgTcnJIW1hL%0JsqR@3X`AJzFhh+*2=u_g|d85Xo0%q`&5a(o7JIU^CnO1rg zPrXJSBj5SFe3cSfbNdjndk&Ok1TJ6ce9g>GRwBQUXunVwkIh-fGo~s-TBWRV`t0a^ zcweg<*~Z1ASkZ6$Yv~&b@>IYXa9Qh3hWlRV!PhmlyfuZ;Z2oz5+qklo740VF`s_!I ztK|2pQyf21%_S2W(^|%5i7)q(7y*h;0J3PqZmrq?Fn%t0#UMT*rWGy~!jOCz!21rb z;`D0hE2Q$I;7O1hXndQ6vE*f;4ocGyB9W=I<%S>fCK%Uy}laIxD)i90rht7KDatU zzDYVP!MSqFpuz?Fi`Me4^BbP*JcoVJECPfPi)FmFk0js- zaVwlyMtM(s1^6QlAakPOoto{oHtq_FYb0zAQ!G&uQW-NT*>V zVQ)Y4>wIjbQHKZz#NsYYei-`PMpy*yE^?SCm&Nkccx4V}cmP8wI8<$v7xcCsoYkp! z>R6EWIEB-*i}HJ)ijZPf$mN94u(a`NyRJnR<9?{I^0^IVx(N-eE(uF43l#3_tBd>P z_<*x`ivLLo$(1MRa+O&{!flg27phqaOon>5$~86nNo%yls^#&5XoB`1?1V>7pINSY z@dbh|w!0Sk!?ry@XXp)ldJ?$(0n47&|9H2;#K4eyCWyAJ6x5vbRTCN6Z2e`3@R5M- zfIJz?h)J!Aut$F#e8%6&ZllN4nCuI5a}yL}4@SuprzZ0LGLS{I{Eba!d6Gy@)NM8G z)W^2)o6`4p6|_eRpJv5$eXb@}7GQ!7JOK9>^%LzGxZAPy*a9=+OLoNmhZ+BeIV*|MmAw72AsuR@4{}giza+v zYdt3@wWjOIjYk>!c1%$uoDto*%3(8z!gQ0;;B1#)C(A&>W8TlC6kkcpsOM?9YWHYL za>!G(?L{&M{k0V?ydxO8T#~Flo8dU+-KdB_uwB6%MD7El$LL-qQ7}N)uR`AA26cV*x^$HS@f(g)= zx~|@_0uEb$)*_JSpAlHwI59+&32Z>*s3Y|%xn|7Ig(7--P^^$9?sHxQm+j#C4^Yb> zl7U!(RQhjPz6n6MkM;j05)_d+{wM=xf74I``|5#-=nv@}q!s?rHmm)P_OoqSD;LaA zOvbgc>b%hkQaz>yr2xRi`kga4+GsxJ4;UC~JS%JAGmta#DnKAkK;r9*P?%+RIr8{P zo~W1h*dH$`p)*VNGmKTo7;O37sMgx-f50UknjcUnV(|vSmiV%vAG{aFU9@;e=@-4BY5+7!hQ73Ew;e;E=Ik;-ezz@5e}{T?Z68!#6w(h?w&KDxZ#1AmO7|8b4is`ja8; ze1^{QdXSG5H^is=CvqjC4gp27bFMmu%Ce4Z^CVc_;@dCp2|GcAexcPC7b~|u+}PVr z7pJ{)oSQ7dj$#T-WL4MIeY*VNw#0q=C&Rb-f!=Sd|3T7~HYhG(7N6Ib^TR2XmDc+y z=`pm34E<7-O3HyeO!;{y!-!0SZL3z1qiSeL(adBQ2rp#!qJH27W=X#f?wlhXS|4@bvh2 zr!9q8E1nFSg-(;=MVqF;cy2Z}r9;0JQ`^r|x+`|ZEuLQqJueqZ&wTpqOhWnC*!r;S zEG@t7&($cE_jFmFZH?p-P?ZVu*-a`4dmZk3M1q*(NYLnu$&boKdA7Wcmbh*&j|48e zTK#V=j+R=+8$IkhbT4rLW{3w%8|8nK(lwF~+qb0#Wl5)}I0+S?G)B)SSGP!ps+YuoPC6^i-vl)$vlJrnyGyA(p@pCZrT6ZS7>of^qu<7o%>RDaOF#HOkeV zva4URX4-4XI^-3ab;WL@Q$wy<2uG8zbj1^wsUw$#VT(6EzZ&i#Sy&27;ET$j3!k%oYJgjsC zqe%9u4fr9Q`U9GCZuD5OY@ZCTqTt z9%)S3*0#XA!@V)cw4>8bcBa+8iO?jGMMub?8OhkvW%7^Rpe0{qHx)J4^tGQZlCpG}8Xh4%_ zf?67vhX%eutYm&eQ5iZ9>3|$@9*;&4arh9~f%n2T7_j0<<-85<55WN|{9xHl!VfBe zSHy-Bl0sGj*WKGBCrvjI?`R{UpJW4fcYfy4ol2;0@krl;tgNjuMI3uy9kQb>Xp*lV zq?$gUO8A_X8ZT%PF4SM zf_NUBxZ^erfkq#9Gr6?+yBfoey$;5g1Xevws1O!p-~6iuV{rWs37>D4)Yy5H$PtSJ zY*2?{-HX~heX3bnA{XKaL&HU(VCwZp@T9ZG)Fy;3G$0f_v`G91@arXp>~~>YT$1qR zWxen&RD=kyFwG_XSdY3DbxtKtvT--6Mdq>H$(-e;#iOmHL&nnaEh;>8)PO-8O)D0} zH9X7cBB}Y)Y5mhvY`+#?sQb=#%i!yU*8x2HccTV<+zUMb6PhZ)uqN33S9TxTOEgij zQ6c@2*d4&e)GhYNdeHZ$B54C(SpmDPKRciPVRVl5m`aH~*XaxQ^rtm0q@IR^SQh}r z4d3>AULQjbN-BdrG^s^0pOa(U^j9o(*h)yw2UimT-dvo=?S^Ei*m=Upx)q3gt`e8+ z8e(Y{G@MM_eGQ#CIP)LntH{VmuL(B5bKbo<$Z1^GsH$-QVxtiS7*IfO9A+zf{NRyQ z!dXPApXHfd_7UrDEX|&N%jeOl>0Mb}L2Txy$eihg2ceqSbMD$4lGs1FGIMCU?EclB z%-jeGclw*g{$F?*mxIuj*mFF^r2j1P5~m23**oKPC6)xm>cfhi{TzhUE70p*-tJ3J zPSKms8|ZQwTATF`b+oejp7ChKJ?MZ?B8t*TkI~Hk&*S*V29go7Mo8CK5kV(Cm9uBi zj;&%q(I?R$TFzryEV;0g0tNcKgrTOD*mgFB19oS7TQRiZIj%qLYk35N!LQIT(GR*f6d>Ea z=NtK|HYe#ontYKz-B?cdJF%8q#n-&MjY^gWH!2$SRSIGFyWD@Y>St4E;NRNDE?8nb zV(&n}nEgsR;OC##s?6D<450`2DPaRqpaw{>;Bd~MdnCI~xAy4iXL$Zt^*ScOwtb4D zyjtVvsOA3_Xl_}?%_6(POElIOL;rZ z;ZYzE%jblwP2nNwKMzhs6k?i1Vqhhup^eXw8w%4<;4X>cBJ`^LV7$WL_z4Omxj4?v z=Q43Yd*ly=rCRPHCOGlXlnpB>r(F|VYU!Q}2X7Gog$`2qcHc9Gah}G+GLV{GtlSKo zCNvL4KV1XQ{f3!89cbgs7uaFo&ioz1t{&Q!<5wi%N65Qt*)N@cr-4z^Ouv%54W&C5 z(iF~4WJ3w#8Ur>sv?Ohwwy78fM($d3Tq8GiaUp>1$9)`J;dJ^yY%wrAuhia!^ufh>B|MNu<+{CL5BOVDR*df&?x)Fw%m&4zk=8BcXc z?#%hVteUWgW`=RR-oM5p1k(pL&osDeo!hcZnz7cpeC|-?IGfY(2d9lGb!%zE;DJ$DhNCsJb-$jKDlMLVB_dVTy$;Ut0e!od?Nz8Y59^dm=g&CHJr ze9O#3rOVwBbb}y_dY`Uupzj1VWgd59t(K=IB^W-ei+a@t_y|NHC)cRpldLc?!Ra)+ zSZMNog+|veq2Fth@#U$Ek2t4BrCeUKg2k9CVcr3M<6NcDiBh~XK?KQ1(}t9cOh(>q zf2BNA^rHFe5asyh4n|-T-YtUKsnEP-Gne(9PL2QbY6fIVXhhh{`Jkq~*wQvvRQ^Ai z5}I>b#QO(_&W(b~w(8-RG-x+<>qqCJWc);KMO`|21luVS#h9-b+5vL;2H>OoWSh>O z>x5wK3KupJ)DYlV4c1vWL_!A83Rd2@YtuKw`Eu{@8F+L<_FOk&l?7_Zrkb+9u!w8X zJF0h@^74D6rs!(678%#+y+@z&tu7>nIr@9FrvWHWs@ECZefJG!Pye{MX>6;tFn7*& zGlw=T|8=Cw2lC@-VH0eJw0G!9h!(slDNDQ1CFVjZVSahHsO-DJ;Z3Mcq(yc0!sxSV z!LWJZmcRlf5U8MEQ6KP6|1m%)Fb|;P<<>gaJR)Oh^}R`LN|68gihUR?BE07I9QvTo zBvyzud~K=rweSoaUUe>qG2?rNZJhu+n*DNZT9A%Q_ZzHV614?rW zcG96;A}r*M{mcnOB+$1-e>@KeqDSB$+XZha8tdtyIR2dm)=#j^y?hba)G&VXRd7J( zV93-C@RYk?3of?2+Bb!F5`?NmW`OuU5%ZBun-gt(Ec~Sm5=Z1$JageihTB#yeiVJ( zlN$G7yjLys>6fL~HS~*Y{%|bq-A3sjue>Qr&>;!A*yT9_Gz*M0l(i661CP0-*oaAI z8!oHDm}vj9T!la2BAVKleOU3&+AoRC{H@;3zC7Ix!4OjP+{n_M-=8SruVtPUrIRM_ zA_&XH&n2l;XsYn*n;s4qy)`w|?w?};J)$DZb;V|hxL#HRzmlqA_9U?SN^hfSs;*b~ z3$9AXsn@I0+eli0<#AYW!gt%G2L^WVsVsF{`f14J2eTCHRl{npg3Oe&*CVv$J=e<) zcUgwNtaP8?&ZWIzV;dT7NSBo<=Uk>U)k{@C<0-!CO%rYPZ^r9DZ{GS?;_C8xIF|0o z57e!XZ`m;ZiD#&UMq_Br7vX%LDa+vDOioTstOG=gahmr_PPq;`(&sHFbq%hFa&*Ld zqc4bUcwH)v$BSxocglXwpx$=1aPr8|!x(^Fu8V!rm@_a+(u2Q6hHGu$7SkVwt}<(6 zPZH2DIZVvE;S0gca1##y1itGSyc>99e^LJ2#x5b=zR$ZMNlJsLiXwt7AY^ocIS5+h?UQuDJm2pY_m5QcmUNqDdG?Q*lV9cRmx>5=m)MV z#JgP)rS5md8;I(aC?;u%?^H!C)pC!IUXza)Lv1R|2wa0e@xf!dPRs+qIRvwXG?nD0PQIMUWsxiUg!c5$OWbdlyh@07ZJ2 zA`qmg6jABO`@O&6&HJ)*=g!XV+1+!_-rZQ7KK9yG_NyQe=$e)$#s~xg^8oP!7!+s+ zDgK0kKy4lkz8O4;2O1@TXqZ4Jt zCYe3c&6n=YUf(kvZyJ?QHp`VxN)zL5R&mgep}6eE8(Sx)s=DDTl(Alo%qeqS=4F;l z)8gz#FhuV1(g{A`d@oyPP3J@Ujosyo<-D`on?u2SqI>RfM0<&SbuxqsS%YrAWBLyV ze;`Eg!t;;!crL{76{O zS0vewBPQ`hVVe(Au6d5;Fg}$%l;UAFdvEnZ*Yy}Kv6`Xml)IW?ka&0o*RR;6@XM<9 zd(*89{>EP(kV~)9v#>byZltw}2k<;bmO#i`W8e>$qB@_*-{;nSyj0XU^tg^Hj&A<9 z{A~}TWZ`ItCaJu)`R&y~jydQ$41g81d;S~;^CqKYgPgEwTnii>`wLNvSXL!9;T2MpZc zp=eW~PqvQGrt+zi7*kqdwIY6r7YauKj9GlAG!3heFw7~d$7NewL$F!F z?!l!kRey}dTkTA=P@+~Cgql8s?bk<(Kr>2GSN*C`DdURX0WJIL<$3j{gZ!zhzfG{}(p?YnD>`!0e0jC0M1kdXPW zLt1$*&PJ~aPJJEb{w|CBv?z&xidIlgcox>NA=Nap5Jx}~tO zdTZVGHL6c#LEK$3i(xx+8IRuBQ`+OV#hDmJwYuoQ3yWT560uo#HGKA$&RSEqkDh+o znXC0&V(7^DeQi^a?KMDe90sy+4^Maw$x;KjUIF=R<()fS+#t!o3l;(-aPQsGTmVC@ zIGB(arI@HE@c&Q3Tc$Fou98~MojI(xK7<)ook~^)pVB3?a@896E?le9Cg;A~zs09~P~Ehk5+$ z2?);Y$-n@+BLpGX;2l?8dsREhmAJMusNeWrMsXHqtm8?^)5rSv?Is4MyWm?B0{a<& zDllY35p?E$JjmOzb%$%8Gl<6KqxUVVgEMUC)!ob71nNmm+d~-R-efgm^&_;1`kT;Q z+o)+PZIW2TD1 zI}UmX+goHr*#kkfRr(yahkx<~*NipLRn`!Rh+3JOkL({h;QxL}XoFIm(rS)rV9n0V zYTqNosUQR$Ji#OoBylB$H^)_lmrjLujNB!Cq)s;Aqfan46K-55{Hp^)MwP5Wuh(AC z>OB>+EaY^r1)U=}qwYJaJlo3}PQIg5G{{(9}MJY^`wBAQ&_~o3*Uq; zUogcSGtN*IzENIbskx-&i|wo#G{jwzL0@p@k~l`><$g(0eijA~#f`?VzT0}{*Kzfk zmEKCLQ$MO<<%(|p^BFv$h$V81lTJv1rja%fb^FeQh)4f9Usv+z`48h|ddhndDn3eX zEf7hWmjE58$ryR0Q1#S+uzGE zCKoQ!1;W>1-ZC{KhBFxYxv9LMk!zik~6)Y3nmt2hS6+$5D% z07+2Y8HauDfcIrg4X?}}c4Xs@@$XN!DOAg{zK*KGADOvE$!v5`LUo^kh%W5=2OrtL zC-eS|e5qDgKN&@lD8On&fKDZZJp!f-{+zo)tgg9onUf^0TnaT)(kluD#9fq3=PlX!_3wmU6_vyG zS4Na)NKOzGD0+kNuh$Cq77zZ0d3-m8R+`faGqX&SVn~~()IpqgO}goCzwrHHA`-cZ z7RVO0#r)iY9se^Y3!1o@96VoyamdkGx)#|+)X?dO`nfixQ^(Bw4$&PJ&;M+vob zf(TlCbWDY$JFXOR47BWhdsDi|@){_WcCH+C_a!mr~rudD+nq!r~mN49YBnJ8N9j@91z*+n<_I(XAO90|$FDWp~@b^y-HqOlV(; zBTSi(dcmC80a4?OVljWnSUp-)AuJM{AqIM-e&iOL=hA zOyBDDqsP_{dBt&2%`@VMZaX6;`i$xV;Rz}#%koBx1`U?cPcFx@B%NB`(A))(v`rGF|lyTDpEeQ~OdvRE~TMxX; zexQ@ZBc@Hir&oPKp}Z#fX3c)6wX1h(6v+xQIzd+#s}|hbny**X+&kb}H@10{FeQb> zQmnblZqKwDkxFtG#@D^nFv24`44I101b;Z5p5|{H-?0_~`+2{ISspH}4UuSvDnimjzFl+M0$oeRjH~z^~8DBO*JEmh7t}scv znSOkEfDBEJq~ouWe{K1JjToDpiLeWdYhzvZ?3*2oht|fw;{|4#Qr;o1{}T}Z^;4F< z{pUc@X3#gijjx`>b)JjoK>>WxEfOaeOV6FogyQ3sP#W^8kp?t{HXN%Udknx)Y8(Fo zRf`lu`}YF=v`b=#-5gT`TSE1PG=wy~4!TSCT#SapPN9)&lpEKJUcIx`j!&17_6p+ z3`6Hs)&E>&8WrF_UoP2z&lVUDpRXNNC}^NOGuq19VLDd7wcHv;Ah=kL2!qB7Pn0$J zC4YD&0CIaD@fu115v9EkM)8<(=j6p*)<)5zk*|_V&WbCkj=yBdpKissla$*rl+F|bKi09(hEb)5Ig|DGA zPnl4i(f8hY3!Cba>!8tuGrO*IZHdiyUlcCLJn=3*{>P*eLO| zih_Iov_CFzTHmmVeQ(Q~Xi+1S5`##34I*M|ll90uDHhgfB~BWeYA;q8kcY~Na}9g> zj_&gI^{y+1y8phn*QRx*zb+0J8rcm)il2JSb9=_)!72RD!ks zzIBr^VwPGglE0x=+H8bM{Gpx~`6#nASic=}G}`K#|4*?vu;qu|zrIwYs}+`~S}`FW z0-m*=c0)#@?Sw45u-tn5dRc1wWs~S2E3ERB)S*OPPE5~Ba~TQYe0%5XU@mY1-cQ{5 z2QK6IZ@gx#YvS#zAFYCiM*`&TFD0E~D&ad^H2F!%qnSuQ|CsAd+Bl@O{(P#qFID7^ zGV);x#GrLSbwHycC;=}CC#5YywyaeryW+nxNL*#0BKf#X#)o&PkX@l$X{-P}pyJbk z^@h+)JuJ|g@7da$@6^$6f54t`PzB%PfA?)Wt Date: Sun, 12 Apr 2020 20:30:47 +0800 Subject: [PATCH 098/238] DSS_User_Manual update --- docs/zh_CN/ch3/DSS_User_Manual.md | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/docs/zh_CN/ch3/DSS_User_Manual.md b/docs/zh_CN/ch3/DSS_User_Manual.md index f366e5de3..5d91c0d02 100644 --- a/docs/zh_CN/ch3/DSS_User_Manual.md +++ b/docs/zh_CN/ch3/DSS_User_Manual.md @@ -44,7 +44,17 @@ __注意:__ 如果要支持多用户登录,DSS的用户登录依赖Linkis, 3. 工程复制:以工程的最新版本为源工程,复制出新工程,初始版本工作流内容为源工程最新版本的工作流。注意:**工程名是唯一,不可重复** ## 3工作流——workflow -### 3.1 工作流编排 +### 3.1 工作流spark节点 +       spark节点分别支持sql、pyspark、scala三种方式执行spark任务,使用时只需将节点拖拽至工作台后编写代码即可。 +### 3.2 工作流hive节点 +       hive节点支持sql方式执行hive任务,使用时只需将节点拖拽至工作台后编写hivesql代码即可。 +### 3.3 工作流python节点 +       python节点支持执行python任务,使用时只需将节点拖拽至工作台后编写python代码即可。 +### 3.4 工作流shell节点 +       shell节点支持执行shell命令或者脚本运行,使用时只需将节点拖拽至工作台后编写shell命令即可。 +### 3.5 工作流jdbc节点 +       jdbc节点支持以jdbc方式运行sql命令,使用时只需将节点拖拽至工作台后编写sql即可,**注意需要提前在linkis console管理台配置jdbc连接信息。** +### 3.6 工作流编排        当点击一个对应的工程后,既可以进入工程首页,在工程首页可以做工作流的编排。 1. 首先需要创建工作流 ![workflow01](/images/zh_CN/chapter3/manual/workflow01.png) @@ -53,7 +63,7 @@ __注意:__ 如果要支持多用户登录,DSS的用户登录依赖Linkis, 3. 节点支持右键功能包括,删除、依赖选择、复制等基本功能,同时数据开发节点还支持脚本关联 ![workflow03](/images/zh_CN/chapter3/manual/workflow03.png) -### 3.2 工作流节点打开 +### 3.7 工作流节点打开 节点支持双击打开: 1. 数据开发节点:点开后即可进入Scriptis进行脚本编辑 ![workflow04](/images/zh_CN/chapter3/manual/workflow04.png) @@ -64,14 +74,14 @@ __注意:__ 如果要支持多用户登录,DSS的用户登录依赖Linkis, 4. 数据可视化节点:跳转到对应的可视化编辑页面 ![workflow07](/images/zh_CN/chapter3/manual/workflow07.png) -### 3.3 层级切换 +### 3.8 层级切换 1. 支持多层级切换:支持快速工程切换、支持在工作流页面切换工作流、支持在单个工作流中切换节点 ![workflow08](/images/zh_CN/chapter3/manual/workflow08.png) 2. 右上脚支持多组件快速切换,在切换后进入的组件的内容都只与该工程相关,让用户更加清晰的去定义工程和业务的内容: ![functions](/images/zh_CN/chapter3/manual/functions.png) -### 3.4 参数和资源设置 +### 3.9 参数和资源设置 1. 工作流上下文信息设置,支持工作流参数、变量、代理用户等 @@ -86,26 +96,26 @@ open("flow://test.txt", encoding="utf-8") #工作流级资源文件使用flow:/ open("node://test.txt", encoding="utf-8") #节点级资源文件使用node://开头 ``` -### 3.5 工作流实时执行 +### 3.10 工作流实时执行 1. 除了功能节点中的subflow会跳过执行,连接节点会作为空节点运行,其他都支持实时执行 ![workflow11](/images/zh_CN/chapter3/manual/workflow11.png) 2. 用户编辑好工作流后点击执行就可以将工作流进行运行,您将看到实时的工作流运行起来可以看到现在运行节点的时间,同时可以右键节点打开节点的管理台去展示该节点的进度,运行结果,运行日志等。支持任务停止等功能 ![workflow12](/images/zh_CN/chapter3/manual/workflow12.png) -### 3.6 工作流调度执行 +### 3.11 工作流调度执行 1. DSS的工程支持发布调度,默认支持发布到Azkaban,同样DSS的调度部分做了深层次的抽象可以做到对其他的调度系统快速支持。发布前会对工作流进行解析,以确保工作流是可以调度运行的: ![workflow13](/images/zh_CN/chapter3/manual/workflow13.png) 2. 发布后即可到调度系统中进行查看,比如去Azkaban页面上进行查看: ![workflow14](/images/zh_CN/chapter3/manual/workflow14.png) 3. DSS如何对接调度系统可以参考:[]() -### 3.7 工作流版本 +### 3.12 工作流版本 1. 工作流创建完成后,具有初始版本,版本号为v000001,直接点击工作流图标时,默认打开工作流的最新版本 2. 可以查看工作流的版本,方便您进行历史版本查看: ![workflow15](/images/zh_CN/chapter3/manual/workflow15.png) -### 3.8 工作流布局修改 +### 3.13 工作流布局修改 1. 工作流格式化:当工作流节点过多,界面太乱时。可以点击节点编辑页的右上方第四个“格式化”按钮。快速美化节点界面: ![workflow16](/images/zh_CN/chapter3/manual/workflow16.png) 如果格式化后不满意,可再次点击节点编辑页的右上方第五个“恢复”按钮,恢复到之前的状态: -- Gitee From ade076a8f338542f8d4ee035e4cc8e681e488fe6 Mon Sep 17 00:00:00 2001 From: Adamyuanyuan Date: Tue, 21 Apr 2020 12:45:23 +0800 Subject: [PATCH 099/238] add example files and some minor modification --- docs/zh_CN/ch3/DSS_User_Tests1_Scala.md | 2 +- docs/zh_CN/ch3/DSS_User_Tests2_Hive.md | 20 ++++++++++++++++++-- examples/ch3/WordCount.jar | Bin 0 -> 70307 bytes examples/ch3/dept.txt | 4 ++++ examples/ch3/emp.txt | 14 ++++++++++++++ examples/ch3/emp1.txt | 5 +++++ examples/ch3/emp2.txt | 5 +++++ examples/ch3/emp3.txt | 4 ++++ examples/ch3/rename.jar | Bin 0 -> 7021 bytes 9 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 examples/ch3/WordCount.jar create mode 100644 examples/ch3/dept.txt create mode 100644 examples/ch3/emp.txt create mode 100644 examples/ch3/emp1.txt create mode 100644 examples/ch3/emp2.txt create mode 100644 examples/ch3/emp3.txt create mode 100644 examples/ch3/rename.jar diff --git a/docs/zh_CN/ch3/DSS_User_Tests1_Scala.md b/docs/zh_CN/ch3/DSS_User_Tests1_Scala.md index 338390611..70c0b0331 100644 --- a/docs/zh_CN/ch3/DSS_User_Tests1_Scala.md +++ b/docs/zh_CN/ch3/DSS_User_Tests1_Scala.md @@ -6,7 +6,7 @@ DSS用户测试样例的目的是为平台新用户提供一组测试样例, ## 1.1 Spark Core(入口函数sc) -在script中,已经默认为您注册了SparkContext,所以直接使用sc即可: +在Scriptis中,已经默认为您注册了SparkContext,所以直接使用sc即可: ### 1.1.1 单Value算子(Map算子为例) diff --git a/docs/zh_CN/ch3/DSS_User_Tests2_Hive.md b/docs/zh_CN/ch3/DSS_User_Tests2_Hive.md index 859edd993..800277ca0 100644 --- a/docs/zh_CN/ch3/DSS_User_Tests2_Hive.md +++ b/docs/zh_CN/ch3/DSS_User_Tests2_Hive.md @@ -48,6 +48,20 @@ partitioned by (month string) row format delimited fields terminated by '\t'; ``` +**导入数据** + +目前需要通过后台手动批量导入数据,可以通过insert方法从页面插入数据 + +```sql +load data local inpath 'dept.txt' into table default.dept; +load data local inpath 'emp.txt' into table default.emp; +load data local inpath 'emp1.txt' into table default.emp_partition; +load data local inpath 'emp2.txt' into table default.emp_partition; +load data local inpath 'emp2.txt' into table default.emp_partition; +``` + +其它数据按照上述语句导入,样例数据文件路径在:`examples\ch3` + ## 2.2 基本SQL语法测试 ### 2.2.1 简单查询 @@ -102,9 +116,11 @@ select * from emp_partition where month='202003' ### 2.3.1 Jar包上传 -进入scripts页面后,右键目录路径上传jar包: +进入Scriptis页面后,右键目录路径上传jar包: + +​ ![img](../../../images/zh_CN/chapter3/tests/hive3.png) -​ ![img](../../../images/zh_CN/chapter3/tests/hive3.png) +测试样例jar包在`examples\ch3\rename.jar` ### 4.3.2 自定义函数 diff --git a/examples/ch3/WordCount.jar b/examples/ch3/WordCount.jar new file mode 100644 index 0000000000000000000000000000000000000000..cbcf5803c46d88dc21fb7c149da4bae1f9107f08 GIT binary patch literal 70307 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 F{U5D@kZS+{ literal 0 HcmV?d00001 diff --git a/examples/ch3/dept.txt b/examples/ch3/dept.txt new file mode 100644 index 000000000..fe587aa7d --- /dev/null +++ b/examples/ch3/dept.txt @@ -0,0 +1,4 @@ +10 ACCOUNTING 1700 +20 RESEARCH 1800 +30 SALES 1900 +40 OPERATIONS 1700 \ No newline at end of file diff --git a/examples/ch3/emp.txt b/examples/ch3/emp.txt new file mode 100644 index 000000000..f8c77cd40 --- /dev/null +++ b/examples/ch3/emp.txt @@ -0,0 +1,14 @@ +7369 SMITH CLERK 7902 1980-12-17 800.00 20 +7499 ALLEN SALESMAN 7698 1981-2-20 1600.00 300.00 30 +7521 WARD SALESMAN 7698 1981-2-22 1250.00 500.00 30 +7566 JONES MANAGER 7839 1981-4-2 2975.00 20 +7654 MARTIN SALESMAN 7698 1981-9-28 1250.00 1400.00 30 +7698 BLAKE MANAGER 7839 1981-5-1 2850.00 30 +7782 CLARK MANAGER 7839 1981-6-9 2450.00 10 +7788 SCOTT ANALYST 7566 1987-4-19 3000.00 20 +7839 KING PRESIDENT 1981-11-17 5000.00 10 +7844 TURNER SALESMAN 7698 1981-9-8 1500.00 0.00 30 +7876 ADAMS CLERK 7788 1987-5-23 1100.00 20 +7900 JAMES CLERK 7698 1981-12-3 950.00 30 +7902 FORD ANALYST 7566 1981-12-3 3000.00 20 +7934 MILLER CLERK 7782 1982-1-23 1300.00 10 \ No newline at end of file diff --git a/examples/ch3/emp1.txt b/examples/ch3/emp1.txt new file mode 100644 index 000000000..92d107a17 --- /dev/null +++ b/examples/ch3/emp1.txt @@ -0,0 +1,5 @@ +7369 SMITH CLERK 7902 2020-1-17 800.00 20 +7499 ALLEN SALESMAN 7698 2020-1-20 1600.00 300.00 30 +7521 WARD SALESMAN 7698 2020-1-22 1250.00 500.00 30 +7566 JONES MANAGER 7839 2020-1-2 2975.00 20 +7654 MARTIN SALESMAN 7698 2020-1-28 1250.00 1400.00 30 \ No newline at end of file diff --git a/examples/ch3/emp2.txt b/examples/ch3/emp2.txt new file mode 100644 index 000000000..d00a23876 --- /dev/null +++ b/examples/ch3/emp2.txt @@ -0,0 +1,5 @@ +7698 BLAKE MANAGER 7839 2020-2-1 2850.00 30 +7782 CLARK MANAGER 7839 2020-2-9 2450.00 10 +7788 SCOTT ANALYST 7566 2020-2-19 3000.00 20 +7839 KING PRESIDENT 2020-2-17 5000.00 10 +7844 TURNER SALESMAN 7698 2020-2-8 1500.00 0.00 30 \ No newline at end of file diff --git a/examples/ch3/emp3.txt b/examples/ch3/emp3.txt new file mode 100644 index 000000000..8f62853f2 --- /dev/null +++ b/examples/ch3/emp3.txt @@ -0,0 +1,4 @@ +7876 ADAMS CLERK 7788 2020-3-23 1100.00 20 +7900 JAMES CLERK 7698 2020-3-3 950.00 30 +7902 FORD ANALYST 7566 2020-3-3 3000.00 20 +7934 MILLER CLERK 7782 2020-3-23 1300.00 10 \ No newline at end of file diff --git a/examples/ch3/rename.jar b/examples/ch3/rename.jar new file mode 100644 index 0000000000000000000000000000000000000000..738483a21ba68d16c44311765b3bf3644d4ccc35 GIT binary patch literal 7021 zcmb7J1z1#Fw;n*cOQpNJTe`bbawuVFkVYIp>68Wm0YzdcDG3SbMg^q1LqG*Yxx=Rd ze$IdIfA>7+%$aA_diP#?uXEnD-=m?7a03l+(LNXJY5a5X>x2sZR+ZI}WK&d=?p4uKv7*UeNV)fDAqwRPB4Z>8L5S@tfl?NG6pfc zho}gxIo!I)2d&e$(>EE1jH$ttX_8Wz^$24z8Uw?p-n$;~dwc+ZWghPzVcdX@&&nBe z836zw;rM5uxW6o{?ChN^Jggn9|1|&XB>V>;F)VW{XD4@0khR;jZgxR``jNu&bFuKS z_po<%`oojX@lQ{fJ-WC#13j(&@Vi(VXeXELHuUNumOlb>vv#roSznG51#l7HgZ@!& zE<^x;9~}T-hUIk`pQ?}auTa^o94*}4v-Gyy@pTE#*%Yg$JaTyha1oa^x$OH22{aXO znM&=bm=r1sa@JMd64__AJ7+NCP6J!!u#bwLwF|c2B4f}=b3J=`9%A;LBvVuLeyzQ9 z26l8$e?X?#+Wn#LS?)tkL1*9kAb{O2eT!{LqfX#$5}6>SR(r(Q$VnnZZHvse_-KXg zsjWhYRcM1Obvg5ji0VvrFXruuhC)VA>1pug1V;0E&=kuM7sms)?QWC$P%(#aAva;B zaB>h!%T*B4mvDOJ5Oh|RhbGgsKhaFa5iZGS@RO0Ey!kX4hqTJgM9NP|-~?Eoy70v? znM(mr(a_LFg~#~TA)Uo=))*P8pO#^9YWLshXJNexfNM)OMymc3OjQ>osr7?3Fb`YKQe{k1WDv;$5Pl zuwm=DbkdJ=)%7%uR$jqTA|!$gR3??Bc(r%45|v^hnqHnXuD*t9MoO5bZOxv?E?SSb zPPja}o($hb7QZ)Dl0aP{G4uqqx_MJ`Vx_pwH=dz0C7-6PLL^Uz={>b)nY|nq#M+{C z8KqQcN_29oGuuA7!;_|q#C7_O(YjNno1xd80VVP@ZmeO=LK?;Anw{1}`aqL{8)=oj zUda^Wh%-AZ_7GGB!mm_vnhr_)cwryZDL?x(QRdQE8I~=5EXfy|Zte#?oaF6tOV<4; zz?&q>>tSagi-?ZrYdHCeS2$62=Do)l9mvK`mKiWqmCpx3< zM5B|&_PYbC@3hF>Y!boLx&lLo5y>=M)|t5+k2}N_UXPs3*v&eLs`S0Pr({}r?@r6o z{ZzT`SKMZy&j}ohO-4PK(Ww&6Tz4WuWD@PEj)T%-yuhi&-iVNw-k1<=PTj^}0o}&X zTBZ`_+1A$t#)Nwd0fZFu?S)b+YYkDcI{s1WI{pzuK>xBubpN8obcILFpOaJ|h6S z)I2}PJ5zsW%w|7r@6}(4G1&Ne(ZA^+Av5V&MW?L6G!0zxGsg|5^5A11)KWE}B_K$w zT|YO<5Gk~kr2t;G;=q1}vjcOSL-{Ob z_&I57l`L&ii@PDO7pKnPc{X+WS-lobeTl;7kQDM{v`C&CKJ*PgP5zM)7r1}tt2W6& zNCuZg=_ZRgj$e^;=qgcs#SuQdhJx49P5%B_8A?7J`|yyLakfa*O7im%+3M3o7js$3jY2A( zNOugc(Wzh~iUZrZ%;9XjHA+He@2sZyntwj1b$_k0)x`^ef z-=dt$=i9)9S__nKcGVIpm{#H)W1oM`K(x_$N0$+KLZWj;lW^vdZ(DJ>hOp+{m~)sq_)Laps(CR1+5Vvy%~9<8BT zm)3w{mNA1K*kjnS6!*DA({*A{w)u!7zkFwGP~7TcNECw!1}(|KA(idB`}tO0I0aV9 zrC#DxNhNAYF59sv1&2#HC9bxAn)hf`O)bi|8 zj)l%o@hwNl2WHyv^qXvuanfWW5wK;z^_Kqi@ZtV4{`rY(&=4 zneLIdL^F@d6(OYi;Gm~)U{aScgsrjVD7LnnqSPmX`X1=nasHd=Vl>4IrE5WOS4nkI zJ9sWlz}%gI$>4pb*W!VJ z->~L|vRC5Yf<-^M83&^dmAT}h&v;Uw$PaAanS4YM$o z+w&Ho?9&=UA$#q6!APSLx|g96-;p7 z#rEh8DoO2dQ&Y>6Uf2p_W!LR%xW>0Pf?r00L_N!wEN?Y~(<8;Uc^vP8N-!eF5@M#- zv<$*F&yAh;Dec@xY#Ghya6#hB5y>^1P3QNKdf@MklL<%VeH8a~xZ9x@ zcC?b7`@Me!i6M?im z?;++-<#$OuY~(xn>O2~(0BDQ}`FXDHc>Z$hyghAS=vHHzDPOsVA0+|dn1sifJirS4 z^1%15Z$en>*(`jLavl&SF>*`4FI~L(w$R0|!xQF;=dX-?m(o5G^drFSr$4zj7AoT;v;r!u3OsZA9J~eGTOQo^8 z0#B~s4yL5S+Ek?=k-+ubSK<86Y#E=ewu78<1 zQz%>#0c){$zByfJUw5&=ld}q1by}w9oR6QQH7i&U_!L#p_cT1@AavxklkLI{Y+Wr) zw&S8*W9ve@c^hw|hc9gRp)nyw09_w$Y@3bjvAWM&dKr#-`r7e2=bn>06J+n$D!DYd zX9_JousuR5=r>dfj4*~LDjom)tb7-Kad z_|-9%cZJImQaaU_8+XW-n*vR(4tK(_ zsmL=L7PfWU_V%U@O4#cdgh8t^ct^Y zUSTf#*S2FrofoX~aHTrg=sY=kzEmTA8>1Tq{vzCySeiqz<$3sz(~q9Xte8zEF|>G_ zIG8gfxJ$809_mj(uWptkB)B&_`Le$N-Fg))?8n z#6SB?cxDo!8r7)Y?YLaK#g|Mlt?Lr|9Upa2*19S7e)w|*3*JreDa92dUF=F{i>Wm7 z-~fPXC@ayzVx(WYQmubBr@xAucvbZ&37oJw*GzR4CMLExcvVR$xR1M`B!tK>1QD@r z#0ly~Rz=hbnl4RfeuJzd=Ibp+bi}?C-a3}i48=a&?cct0xbR54Wf$ORRT@lu^QD2~ zo7RVXrNpyFcVAl8M-WP_RK<8SC^LHU52EZgZ?Lqf=*w?1l9;|&mN5+>wfBnVXy-|@ z+qxwwfO+(Ic=yzX@k~OVTQ|2-Est7AXHhVPOiDG{I@LA3e0C!+(TYim2vdeb)q{6p z@>oD7C!Xz_Ok21h&x~?GkPqWhUW(ihFdTwa?O8}4Dn8jozG;WEN&)`DP4-21ae?e( z$mw`I1yK6Cw4ZmZZd>oUEpu|h_xz}tPB_r4~gznlrFal7f$*nqI(Au z>9r~M-;BkaW3ONb%{)^XZ&}Ek%d7T8s5P{42lp;Kau`f;v%z;#b5Ap}(2G<|p3CM$ zYZl}C6v0xRdZ&v48RCvKSvb4QHh7MBwZ<$!VU71TQ-~PQwZ(xR7mCHDcH{}PVRvx$ zaI|+a13@(lsJ>!uZf*lTLM%-$iREwo3Hv$*$imCo=~A@#+nDliW2o}M{)h7Md$@ml zU!>&aaDR67mp3$u%l=US%rEpbV&zF<9zc`&6O;*A{!0WG=%Bnoj-lFpPHmhxjcY7< z(^iM;a8&s3l;109#O3Hh%BpVYhm%cW4Yxol@Y8SDxgQJ;Zd+}~ofLJqBQOpWq{>S3 zK9<5!DKr6At%JT1sOS0M#cB0$nA2A~=Guuo9Sd()}sHQ0MxYQmq* zx4pYNH5b$4r3&L({21_3=<2|T*(pqhPdMz`fWZ^l==Ug*NpPltqOr{F_mhawbv9z= z^|n!8ZH4oR%{JaC6BsIHYsK6YdP+Ft&>Y#<*ju95qJX~hFw1afGa7w1p+U`gHKv9S za=(Aq;DA(T`|UW1=dwx!*%0$e*|zYWppjmLBsW#votZ+Sm)xATMga}GVdr-8E^|+j ziUMfsta%i3Z^VCm`T$(E*BBY}wReuwX9(M+YpMofYlOjI{reph`Ft9BXv77s&;|5>9^C(rg@jf)F4k@y_SWv&Ug`tNY)Y(( zs+tNfb@o+Rl?Rqqw6K^|b@!F}wK=(UIJwKY`CoDK>$_lK!MR0Yc-Qx8MMm%(9y(%v z#_#}tCq;NDb|&pzKN@+Uj4rC}n0V;^Ie~}!@PW;0KD{0R~{R`JpOgpUb(}PVz1n9L+{1E ex_l7+AHY|HprMS2bb)~n{p3Jjtke=-{Q4i6Ti&t& literal 0 HcmV?d00001 -- Gitee From f9f6f110e3d72329326d95ffb76e88765e93c0a4 Mon Sep 17 00:00:00 2001 From: yangzhiyue <904666286@qq.com> Date: Wed, 13 May 2020 21:29:11 +0800 Subject: [PATCH 100/238] modify appjoint implement doc --- ...345\205\245DSS\346\214\207\345\215\227.md" | 142 ++++++++++++++++-- 1 file changed, 131 insertions(+), 11 deletions(-) diff --git "a/docs/zh_CN/ch4/\347\254\254\344\270\211\346\226\271\347\263\273\347\273\237\346\216\245\345\205\245DSS\346\214\207\345\215\227.md" "b/docs/zh_CN/ch4/\347\254\254\344\270\211\346\226\271\347\263\273\347\273\237\346\216\245\345\205\245DSS\346\214\207\345\215\227.md" index 73173626e..690682aab 100644 --- "a/docs/zh_CN/ch4/\347\254\254\344\270\211\346\226\271\347\263\273\347\273\237\346\216\245\345\205\245DSS\346\214\207\345\215\227.md" +++ "b/docs/zh_CN/ch4/\347\254\254\344\270\211\346\226\271\347\263\273\347\273\237\346\216\245\345\205\245DSS\346\214\207\345\215\227.md" @@ -31,28 +31,142 @@         NodeService是用来解决用户在DSS提交的任务在第三方系统生成相应的任务的问题。用户如果在DSS系统的工作流中新建了一个工作流节点并进行任务的编辑,第三方系统需要同步感知到 - 4.getNodeExecution -        NodeExecution接口是用来将任务提交到第三方系统进行执行的接口,NodeExecution接口有支持短时间任务的NodeExecution和支持长时间任务的LongTermNodeExecution。一般短时间任务,如邮件发送等,可以直接实现NodeExecution接口,并重写execute方法,DSS系统同步等待任务结束。另外的长时间任务,如数据质量检测等,可以实现LongTermNodeExecution接口,并重写submit方法,返回一个NodeExecutionAction,DSS系统通过这个NodeExecutionAction可以向第三方系统获取任务的日志、状态等。 +        NodeExecution接口是用来将任务提交到第三方系统进行执行的接口,NodeExecution +接口有支持短时间任务的NodeExecution和支持长时间任务的LongTermNodeExecution。一般短时间任务,如邮件发送等,可以直接实现NodeExecution接口,并重写execute方法,DSS系统同步等待任务结束。另外的长时间任务,如数据质量检测等,可以实现LongTermNodeExecution接口,并重写submit方法,返回一个NodeExecutionAction,DSS系统通过这个NodeExecutionAction可以向第三方系统获取任务的日志、状态等。 #### 3.第三方系统接入DSS的实现(以Visualis为例) -        Visualis是微众银行WeDataSphere开源的一款商业BI工具,DSS集成Visualis系统之后可以获得数据可视化的能力。Visualis接入DSS系统的代码在DSS项目中已经同步开源,下面将以开源代码为例,对步骤进行罗列分析。 +        Visualis是微众银行WeDataSphere开源的一款商业BI工具,DSS集成Visualis系统之后可以获得数据可视化的能力。 +Visualis接入DSS系统的代码在DSS项目中已经同步开源,下面将以开源代码为例,对步骤进行罗列分析。 Visualis接入的DSS系统的步骤如下: **3.1.Visualis实现AppJoint接口** -        Visualis实现的 AppJoint接口的实现类是VisualisAppjoint。查看VisualisAppjoint的代码可知,它在init方法时候,初始化了自己实现的SecurityService、 NodeService以及NodeExecution。 +        Visualis实现的 AppJoint接口的实现类是VisualisAppjoint。查看VisualisAppjoint的代码可知,它在init方法时候, +初始化了自己实现的SecurityService、 NodeService以及NodeExecution。 +```java + public void init(String baseUrl, Map params) { + securityService = new VisualisSecurityService(); + securityService.setBaseUrl(baseUrl); + nodeExecution = new VisualisNodeExecution(); + nodeExecution.setBaseUrl(baseUrl); + nodeService = new VisualisNodeService(); + nodeService.setBaseUrl(baseUrl); + } +``` **3.2.Visualis实现SecurtyService接口** -        Visualis实现的SecurityService接口的类名是VisualisSecurityService,并重写了login方法,为了能够进行授权登陆,Visualis采用了提供token的方式,DSS的网关对该token进行授权,这样就能够做到用户鉴权。 +        Visualis实现的SecurityService接口的类名是VisualisSecurityService, +并重写了login方法,为了能够进行授权登陆,Visualis采用了提供token的方式,DSS的网关对该token进行授权,这样就能够做到用户鉴权。 + +```java +public class VisualisSecurityService extends AppJointUrlImpl implements SecurityService { + @Override + public Session login(String user) throws AppJointErrorException { + VisualisSession visualisSession = new VisualisSession(); + visualisSession.setUser(user); + visualisSession.getParameters().put("Token-User",user); + visualisSession.getParameters().put("Token-Code","WS-AUTH"); + return visualisSession; + } + + @Override + public void logout(String user) { + + } +} +``` **3.3.Visualis实现的NodeService接口** -        Visualis实现的NodeService接口的类是VisualisNodeService,并重写了createNode,deleteNode和updateNode三个方法,这三个方法是进行在第三方系统同步生成任务元数据。例如createNode方法是通过调用visualis的HTTP接口在Visualis系统生成同一工程下面的Visualis任务。 +        Visualis实现的NodeService接口的类是VisualisNodeService,并重写了createNode, +deleteNode和updateNode三个方法,这三个方法是进行在第三方系统同步生成任务元数据。例如createNode方法是通过调用visualis的HTTP接口在Visualis系统生成同一工程下面的Visualis任务。 + +```java + @Override + public Map createNode(Session session, AppJointNode node, + Map requestBody) throws AppJointErrorException { + if (DisplayNodeService.getNodeType().equals(node.getNodeType())) { + return DisplayNodeService.createNode(session, getBaseUrl(), String.valueOf(node.getProjectId()), node.getNodeType(), requestBody); + } else if (DashboardNodeService.getNodeType().equals(node.getNodeType())) { + return DashboardNodeService.createNode(session, getBaseUrl(), String.valueOf(node.getProjectId()), node.getNodeType(), requestBody); + } else { + throw new AppJointErrorException(42002, "cannot recognize the nodeType " + node.getNodeType()); + } + } + + @Override + public void deleteNode(Session session, AppJointNode node) throws AppJointErrorException { + if (DisplayNodeService.getNodeType().equals(node.getNodeType())) { + DisplayNodeService.deleteNode(session, getBaseUrl(), String.valueOf(node.getProjectId()), node.getNodeType(), node.getJobContent()); + } else if (DashboardNodeService.getNodeType().equals(node.getNodeType())) { + DashboardNodeService.deleteNode(session, getBaseUrl(), String.valueOf(node.getProjectId()), node.getNodeType(), node.getJobContent()); + } else { + throw new AppJointErrorException(42002, "cannot recognize the nodeType " + node.getNodeType()); + } + } + + @Override + public Map updateNode(Session session, AppJointNode node, + Map requestBody) throws AppJointErrorException { + if (DisplayNodeService.getNodeType().equals(node.getNodeType())) { + return DisplayNodeService.updateNode(session, getBaseUrl(), node.getProjectId(), node.getNodeType(), requestBody); + } else if (DashboardNodeService.getNodeType().equals(node.getNodeType())) { + return DashboardNodeService.updateNode(session, getBaseUrl(), node.getProjectId(), node.getNodeType(), requestBody); + } else { + throw new AppJointErrorException(42002, "cannot recognize the nodeType " + node.getNodeType()); + } + } +``` **3.4.Visualis实现NodeExecution接口** -        Visualis实现的NodeExecution接口的类是VisualisNodeExecution,并重写了execute方法,该方法传入的两个参数为Node和NodeContext,从NodeContext中我们可以拿到用户、DSS的网关地址,还有网关验证的Token。通过这些,我们可以封装成一个HTTP的请求发送到第三方系统Visualis并从Visualis获取响应结果,NodeContext提供写入结果集的方法,如Visualis的结果集一般是以图片的形式展示,在execute方法的最后,Visualis通过nodeContext获取到一个支持图片写入的PictureResultSetWriter方法,并将结果集进行写入。 +        Visualis实现的NodeExecution接口的类是VisualisNodeExecution,并重写了execute方法, +该方法传入的两个参数为Node和NodeContext,从NodeContext中我们可以拿到用户、DSS的网关地址,还有网关验证的Token。 +通过这些,我们可以封装成一个HTTP的请求发送到第三方系统Visualis并从Visualis获取响应结果,NodeContext提供写入结果集的方法, +如Visualis的结果集一般是以图片的形式展示,在execute方法的最后,Visualis通过nodeContext获取到一个支持图片写入的PictureResultSetWriter方法,并将结果集进行写入。 +```scala + override def execute(node: AppJointNode, nodeContext: NodeContext, session: Session): NodeExecutionResponse = node match { + case commonAppJointNode: CommonAppJointNode => + val appJointResponse = new CompletedNodeExecutionResponse() + val idMap = commonAppJointNode.getJobContent + val id = idMap.values().iterator().next().toString + val url = if(commonAppJointNode.getNodeType.toLowerCase.contains(DISPLAY)) getDisplayPreviewUrl(nodeContext.getGatewayUrl, id) + else if(commonAppJointNode.getNodeType.toLowerCase.contains(DASHBOARD)) getDashboardPreviewUrl(nodeContext.getGatewayUrl, id) + else { + appJointResponse.setIsSucceed(false) + appJointResponse.setErrorMsg("不支持的appJoint类型:" + node.getNodeType) + return appJointResponse + } + var response = "" + val headers = nodeContext.getTokenHeader(nodeContext.getUser) + nodeContext.appendLog(LogUtils.generateInfo(s"Ready to download preview picture from $url.")) + Utils.tryCatch(download(url, null, headers.toMap, + input => Utils.tryFinally{ + val os = new ByteArrayOutputStream() + IOUtils.copy(input, os) + response = new String(Base64.getEncoder.encode(os.toByteArray)) + //response = IOUtils.toString(input, ServerConfiguration.BDP_SERVER_ENCODING.getValue) + }(IOUtils.closeQuietly(input)))){ t => + val errException = new ErrorException(70063, "failed to do visualis request") + errException.initCause(t) + appJointResponse.setException(errException) + appJointResponse.setIsSucceed(false) + appJointResponse.setErrorMsg(s"用户${nodeContext.getUser}请求Visualis失败!URL为: " + url) + return appJointResponse + } + nodeContext.appendLog(LogUtils.generateInfo("Preview picture downloaded, now ready to write results.")) + val imagesBytes = response + val resultSetWriter = nodeContext.createPictureResultSetWriter() + Utils.tryFinally{ + resultSetWriter.addMetaData(new LineMetaData()) + resultSetWriter.addRecord(new LineRecord(imagesBytes)) + }(IOUtils.closeQuietly(resultSetWriter)) + appJointResponse.setIsSucceed(true) + appJointResponse + } +``` **3.5.数据库内容的更新(dss-application模块)** @@ -66,7 +180,7 @@ Visualis接入的DSS系统的步骤如下: | url | 10 | 如 http://127.0.0.1:8080 | | is_user_need_init | 是否需要用户初始化 | 默认否 | | user_init_url | 用户初始化url | 默认空 | -| exists_project_service | 是否存在自己的projectService服务, 存在的话要自己写appjoint实现projectService0 | | +| exists_project_service | 是否存在自己的projectService服务, 存在的话要自己写appjoint实现projectService | | | enhance_json | 加强json,在appjoint初始化的时候会作为map进行传入 | | | homepage_url | 接入的系统主页url | | | direct_url | 接入的系统重定向url | | @@ -97,11 +211,11 @@ Visualis接入的DSS系统的步骤如下: **3.6.前端的修改** - 3.6.1 增加节点类型 -修改src/js/service/nodeType.js文件,增加Qualitis节点类型 +修改src/js/service/nodeType.js文件,增加Visualis节点类型 - 3.6.2 增加节点图标 将节点图标复制到src/js/module/process/images/路径下,目前只支持SVG格式。 - 3.6.3 新增节点配置 -修改src/js/module/process/shape.js文件,增加Qualitis的节点配置信息。 +修改src/js/module/process/shape.js文件,增加Visualis的节点配置信息。 - 3.6.4 修改首页单击节点事件 修改src/js/module/process/index.vue文件,增加节点单击事件以及单击事件的处理逻辑。 - 3.6.5 修改工作流节点双击事件 @@ -109,7 +223,13 @@ Visualis接入的DSS系统的步骤如下: **3.7.编译打包成jar包放置到指定位置** -        实现了上述的接口之后,一个AppJoint就已经实现了。打包之后,需要放置到指定的位置。jar包需要放置到dss-server和linkis-appjoint-entrance两个微服务中,以linkis-appjoint-entrance 为例(dss-server与linkis-appjoint-entrance一致),在linkis-appjont-entrance下面的lib的同级目录有一个appjoints目录,目录下面层次如图3-3所示。 +        实现了上述的接口之后,一个AppJoint就已经实现了。打包之后,需要放置到指定的位置。 +jar包需要放置到dss-server和linkis-appjoint-entrance两个微服务中,以linkis-appjoint-entrance 为例(dss-server与linkis-appjoint-entrance一致), +在linkis-appjont-entrance下面的lib的同级目录有一个appjoints目录,目录下面层次如图3-3所示。 ![appjoints目录示例](/images/zh_CN/chapter4/appjoints.png)
图3-3 appjoints目录示例 -        在appjoints目录下面新建一个visualis目录。visualis目录下面要求有lib目录,lib目录存放的是visualis在实现VisualisAppJoint的编译的jar包,当然如果有引入dss系统没有带入的jar包,也需要放置到lib目录中,如sendemail Appjoint需要发送邮件功能的依赖包,所以需要将这些依赖包和已经实现的jar包统一放置到lib目录中。另外可以将本AppJoint所需要的一些配置参数放置到appjoints.properties,DSS系统提供的AppJointLoader会将这些配置的参数读取,放置到一个Map中,在AppJoint调用init方法的时候传入。 +        在appjoints目录下面新建一个visualis目录。 +visualis目录下面要求有lib目录,lib目录存放的是visualis在实现VisualisAppJoint的编译的jar包, +当然如果有引入dss系统没有带入的jar包,也需要放置到lib目录中,如sendemail Appjoint需要发送邮件功能的依赖包, +所以需要将这些依赖包和已经实现的jar包统一放置到lib目录中。 +另外可以将本AppJoint所需要的一些配置参数放置到appjoints.properties,DSS系统提供的AppJointLoader会将这些配置的参数读取,放置到一个Map中,在AppJoint调用init方法的时候传入。 -- Gitee From ca6bcd3ceb0769df24c84e21b7a7480a031dc576 Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Wed, 3 Jun 2020 15:59:26 +0800 Subject: [PATCH 101/238] sql and pyspark associate script --- web/src/js/module/process/component/associateScript.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/js/module/process/component/associateScript.vue b/web/src/js/module/process/component/associateScript.vue index 26b4ea969..545c63339 100644 --- a/web/src/js/module/process/component/associateScript.vue +++ b/web/src/js/module/process/component/associateScript.vue @@ -38,7 +38,7 @@ import { isEmpty, cloneDeep } from 'lodash'; import storage from '@/js/helper/storage'; import directoryDialog from '@js/component/directoryDialog/index.vue'; - +import { ext } from '@/js/service/nodeType'; export default { components: { directoryDialog, @@ -82,8 +82,8 @@ export default { this.setFileTree(); }); this.filterNode = (node) => { - const type = this.nodeData.type.slice(this.nodeData.type.lastIndexOf('.') + 1, this.nodeData.type.length); - const match = this.supportModes.find((item) => item.rule.test(node.label) && item.flowType === type); + const model = ext[this.nodeData.type]; + const match = this.supportModes.find((item) => item.rule.test(node.label) && item.flowType === model); return !node.isLeaf || (node.isLeaf && match); }; }, -- Gitee From f410d3b679fcf8f6ab6c0cdad2a77b04bc13c4a0 Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Wed, 3 Jun 2020 15:59:26 +0800 Subject: [PATCH 102/238] sql and pyspark associate script --- web/src/js/module/process/component/associateScript.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/js/module/process/component/associateScript.vue b/web/src/js/module/process/component/associateScript.vue index 26b4ea969..545c63339 100644 --- a/web/src/js/module/process/component/associateScript.vue +++ b/web/src/js/module/process/component/associateScript.vue @@ -38,7 +38,7 @@ import { isEmpty, cloneDeep } from 'lodash'; import storage from '@/js/helper/storage'; import directoryDialog from '@js/component/directoryDialog/index.vue'; - +import { ext } from '@/js/service/nodeType'; export default { components: { directoryDialog, @@ -82,8 +82,8 @@ export default { this.setFileTree(); }); this.filterNode = (node) => { - const type = this.nodeData.type.slice(this.nodeData.type.lastIndexOf('.') + 1, this.nodeData.type.length); - const match = this.supportModes.find((item) => item.rule.test(node.label) && item.flowType === type); + const model = ext[this.nodeData.type]; + const match = this.supportModes.find((item) => item.rule.test(node.label) && item.flowType === model); return !node.isLeaf || (node.isLeaf && match); }; }, -- Gitee From 1c6af9056bd3692ad4007a144327443352642184 Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Fri, 12 Jun 2020 09:37:32 +0800 Subject: [PATCH 103/238] OpenFile interface data modification --- web/src/js/module/process/module.vue | 2 +- web/src/js/module/workbench/container.vue | 4 ++-- web/src/js/module/workbench/script/result.vue | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/web/src/js/module/process/module.vue b/web/src/js/module/process/module.vue index 5b734c3bb..ef04ba41c 100644 --- a/web/src/js/module/process/module.vue +++ b/web/src/js/module/process/module.vue @@ -1635,7 +1635,7 @@ export default { const fileName = `${time.getTime()}${match.ext}`; const params = { fileName, - scriptContent: rst.fileContent, + scriptContent: rst.fileContent[0][0], metadata: rst.params, }; api.fetch('/filesystem/saveScriptToBML', params, 'post') diff --git a/web/src/js/module/workbench/container.vue b/web/src/js/module/workbench/container.vue index 64c7dd8e2..68773e006 100644 --- a/web/src/js/module/workbench/container.vue +++ b/web/src/js/module/workbench/container.vue @@ -441,13 +441,13 @@ export default { api.fetch('/filesystem/openFile', { path: option.path, }, 'get').then((rst) => { - const ismodifyByOldTab = option.code && !rst.fileContent; + const ismodifyByOldTab = option.code && !rst.fileContent[0][0]; const params = ismodifyByOldTab ? option.params : this.convertSettingParams(rst.params); this[methodName]({ id: md5Path, filename: option.filename, filepath: option.path, - code: rst.fileContent || option.code, + code: rst.fileContent[0][0] || option.code, params, type: option.type, saveAs: option.saveAs || false, diff --git a/web/src/js/module/workbench/script/result.vue b/web/src/js/module/workbench/script/result.vue index 30c0458a8..ad40b71dd 100644 --- a/web/src/js/module/workbench/script/result.vue +++ b/web/src/js/module/workbench/script/result.vue @@ -78,7 +78,7 @@ v-else-if="result.type === '5'" :style="{'height': resultHeight}" class="html-result-div" - v-html="result.bodyRows"/> + v-html="result.bodyRows[0][0]"/> {{ $t('message.workBench.body.script.result.emptyText') }} -- Gitee From 60362bea3f6e7a41730a4ef574a808a000843f4e Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Thu, 18 Jun 2020 10:27:24 +0800 Subject: [PATCH 104/238] Add default value for eventcheck parameter: msg.body --- web/src/js/module/process/module.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/js/module/process/module.vue b/web/src/js/module/process/module.vue index ef04ba41c..06846caa4 100644 --- a/web/src/js/module/process/module.vue +++ b/web/src/js/module/process/module.vue @@ -797,7 +797,7 @@ export default { 'msgName': '', 'queryFrequency': 10, 'maxReceiveHours': 12, - 'msgSavekey': '', + 'msgSavekey': 'msg.body', 'onlyReceiveToday': 'true', }, }); -- Gitee From 9105cac428d9d0bdfc212136125b254b25c53062 Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Thu, 18 Jun 2020 10:41:47 +0800 Subject: [PATCH 105/238] Result set sorting --- web/src/js/component/table/index.js | 2 +- .../js/component/table/resultTable/body.vue | 285 ++++++++++++++++++ .../js/component/table/resultTable/header.vue | 128 ++++++++ .../js/component/table/resultTable/list.vue | 102 +++++++ .../js/component/table/resultTable/table.vue | 188 ++++++++++++ web/src/js/module/workbench/script/result.vue | 153 +++++++++- 6 files changed, 851 insertions(+), 7 deletions(-) create mode 100644 web/src/js/component/table/resultTable/body.vue create mode 100644 web/src/js/component/table/resultTable/header.vue create mode 100644 web/src/js/component/table/resultTable/list.vue create mode 100644 web/src/js/component/table/resultTable/table.vue diff --git a/web/src/js/component/table/index.js b/web/src/js/component/table/index.js index 350c6b1a7..5def7449c 100644 --- a/web/src/js/component/table/index.js +++ b/web/src/js/component/table/index.js @@ -15,7 +15,7 @@ * */ -import WeTable from './table.vue'; +import WeTable from './resultTable/table.vue'; import historyTable from './historyTable/historyTable.vue'; export default { WeTable, diff --git a/web/src/js/component/table/resultTable/body.vue b/web/src/js/component/table/resultTable/body.vue new file mode 100644 index 000000000..502a4aa3f --- /dev/null +++ b/web/src/js/component/table/resultTable/body.vue @@ -0,0 +1,285 @@ + + + diff --git a/web/src/js/component/table/resultTable/header.vue b/web/src/js/component/table/resultTable/header.vue new file mode 100644 index 000000000..f8bfc2fec --- /dev/null +++ b/web/src/js/component/table/resultTable/header.vue @@ -0,0 +1,128 @@ + + diff --git a/web/src/js/component/table/resultTable/list.vue b/web/src/js/component/table/resultTable/list.vue new file mode 100644 index 000000000..aab7cf4e1 --- /dev/null +++ b/web/src/js/component/table/resultTable/list.vue @@ -0,0 +1,102 @@ + + diff --git a/web/src/js/component/table/resultTable/table.vue b/web/src/js/component/table/resultTable/table.vue new file mode 100644 index 000000000..faa5693b0 --- /dev/null +++ b/web/src/js/component/table/resultTable/table.vue @@ -0,0 +1,188 @@ + + + + diff --git a/web/src/js/module/workbench/script/result.vue b/web/src/js/module/workbench/script/result.vue index ad40b71dd..b0b6842d1 100644 --- a/web/src/js/module/workbench/script/result.vue +++ b/web/src/js/module/workbench/script/result.vue @@ -36,6 +36,7 @@ :height="tableData.height" :columns="data.headRows" :data="data.bodyRows" + @on-sort-change="sortChange" @on-current-change="onRowClick" class="result-normal-table"> @@ -58,7 +59,8 @@ @on-scroll="saveOffset" @dbl-click="copyLabel" @on-click="onWeTableRowClick" - @change-status="changeStatus"/> + @change-status="changeStatus" + @handleSortClick="handleSortClick"/> { + if (head.content === col.content) { + sortIndex = index + } + }) + // 大于50列排序现将要排序的列和原始index保持 + let sortColumnAll = this.originRows.map((row, index) => { + return { + originIndex: index, + value: row[sortIndex] + } + }) + // 将找出的列排序 + sortColumnAll = this.arraySortByName(sortColumnAll, col.columnType, 'value');// 从小到大 + let newRow = []; + if (order === 'asc') {// 升序 + sortColumnAll.map((item, index) => { + newRow[index] = this.originRows[item.originIndex]; + }) + this.originRows = newRow; + } else if (order === 'desc') {// 降序 + sortColumnAll.reverse(); + sortColumnAll.map((item, index) => { + newRow[index] = this.originRows[item.originIndex]; + }) + this.originRows = newRow; + } else if (order === 'normal') {// 恢复原来数据 + this.originRows = this.result.bodyRows || []; + this.data.originRows = this.originRows; + } + this.pageingData(); + }, + addCellClassName() { + // 需要将每一行中的NULL挑选出来 + if (this.tableData.type === 'normal') { + this.originRows = this.originRows.map((row) => { + row.cellClassName = {}; + Object.keys(row).forEach((key)=> { + if (row[key] === 'NULL') { + row.cellClassName[key] = 'is-null'; + } + }) + return row; + }) + } + }, + sortChange({column, key, order}) { + this.originRows = this.arraySortByName(this.originRows, column.columnType, key);// 从小到大 + if (order === 'asc') {// 升序 + this.addCellClassName(); + } else if (order === 'desc') {// 降序 + this.originRows.reverse(); + this.addCellClassName(); + } else if (order === 'normal') {// 恢复原来数据 + if (this.tableData.type === 'normal') { + this.originRows = this.result.bodyRows.map((row) => { + let newItem = {}; + const NullList = []; + row.forEach((item, index) => { + Object.assign(newItem, { + [this.result.headRows[index]]: item, + }); + if (item === 'NULL') { + NullList.push(this.result.headRows[index]); + } + }); + // 对于NULL值加上高亮样式 + if (NullList.length) { + newItem.cellClassName = {}; + NullList.forEach((item) => { + newItem.cellClassName[item] = 'is-null'; + }); + } + return newItem; + }); + } else { + this.originRows = this.result.bodyRows || []; + } + this.data.originRows = this.originRows; + } + this.pageingData(); + }, + arraySortByName(list, valueType, key) { + if (list === undefined || list === null) return []; + list.sort((a, b) => { + let strA = a[key]; + let strB = b[key]; + // 谁为非法值谁在前面 + if (strA === undefined || strA === null || strA === '' || strA === ' ' || strA === ' ' || strA === 'NULL') { + return -1; + } + if (strB === undefined || strB === null || strB === '' || strB === ' ' || strB === ' ' || strB === 'NULL') { + return 1; + } + // 如果为整数型大小 + if (['int', 'float', 'double', 'long', 'short', 'bigInt', 'decimal'].includes(valueType.toLowerCase())) { + + return strA - strB; + } + const charAry = strA.split(''); + for (const i in charAry) { + if ((this.charCompare(strA[i], strB[i]) !== 0)) { + return this.charCompare(strA[i], strB[i]); + } + } + // 如果通过上面的循环对比还比不出来,就无解了,直接返回-1 + return -1; + }); + return list; + }, + charCompare(charA, charB) { + // 谁为非法值谁在前面 + if (charA === undefined || charA === null || charA === '' || charA === ' ' || charA === ' ') { + return -1; + } + if (charB === undefined || charB === null || charB === '' || charB === ' ' || charB === ' ') { + return 1; + } + if (!this.notChinese(charA)) { + charA = pinyin(charA)[0][0]; + } + if (!this.notChinese(charB)) { + charB = pinyin(charB)[0][0]; + } + return charA.localeCompare(charB); + }, + notChinese(char) { + const charCode = char.charCodeAt(0); + return charCode >= 0 && charCode <= 128; + }, initOffset() { let cache = this.script.result.cache; let x = 0; @@ -279,6 +422,7 @@ export default { let headRows = this.result.headRows || []; this.data.headRows = []; this.data.bodyRows = []; + this.originRows = this.result.bodyRows || []; this.tableData.total = this.result.total; if (this.tableData.type === 'normal') { @@ -289,10 +433,7 @@ export default { this.data.headRows.push({ title, key: item, - sortable: 'true', - sortMethod: function(a, b, type) { - return util.sort(a, b, type); - }, + sortable: 'custom', columnType, renderHeader: (h, params) => { return h('span', { @@ -362,7 +503,7 @@ export default { this.data.bodyRows = newArr; } }, - change(page) { + change(page = 1) { this.hightLightRow = null; this.page.current = page; this.pageingData(); -- Gitee From 42cd5aea720a14d2200c11867ff9e90943167ef3 Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Thu, 18 Jun 2020 14:22:24 +0800 Subject: [PATCH 106/238] query tab name editfy --- web/src/js/module/hiveSidebar/hiveSidebar.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/js/module/hiveSidebar/hiveSidebar.vue b/web/src/js/module/hiveSidebar/hiveSidebar.vue index 4479c4d27..2edfe5269 100644 --- a/web/src/js/module/hiveSidebar/hiveSidebar.vue +++ b/web/src/js/module/hiveSidebar/hiveSidebar.vue @@ -307,8 +307,8 @@ export default { this.dispatch('Workbench:pasteInEditor', value, this.node); }, queryTable() { - const tabName = `${this.currentAcitved.dbName}.${this.currentAcitved.name}`; - const code = `select * from ${tabName} limit 100`; + const tabName = `${this.currentAcitved.dbName}_${this.currentAcitved.name}`; + const code = `select * from ${this.currentAcitved.dbName}.${this.currentAcitved.name} limit 100`; const filename = `${tabName}_select.hql`; const md5Path = util.md5(filename); this.dispatch('Workbench:add', { -- Gitee From 8a72240331d89dc774b20544a97f792cc0f0a0ae Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Fri, 19 Jun 2020 11:40:42 +0800 Subject: [PATCH 107/238] Fix the bug for check table error when dataObject is not well-formed #Fixes #160 --- .../schedulis/jobtype/connector/DataCheckerDao.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/datachecker-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/schedulis/jobtype/connector/DataCheckerDao.java b/datachecker-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/schedulis/jobtype/connector/DataCheckerDao.java index d3caeac01..d84a0d4bc 100644 --- a/datachecker-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/schedulis/jobtype/connector/DataCheckerDao.java +++ b/datachecker-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/schedulis/jobtype/connector/DataCheckerDao.java @@ -158,8 +158,9 @@ public class DataCheckerDao { private PreparedStatement getStatement(Connection conn, String dataObject) throws SQLException { String dataScape = dataObject.contains("{") ? "Partition" : "Table"; - String dbName = dataObject.split("\\.")[0]; - String tableName = dataObject.split("\\.")[1]; + String[] dataObjectArray = dataObject.split("\\."); + String dbName = dataObjectArray[0]; + String tableName = dataObjectArray[1]; if(dataScape.equals("Partition")) { Pattern pattern = Pattern.compile("\\{([^\\}]+)\\}"); Matcher matcher = pattern.matcher(dataObject); @@ -174,11 +175,13 @@ public class DataCheckerDao { pstmt.setString(2, tableName); pstmt.setString(3, partitionName); return pstmt; - } else { + } else if(dataObjectArray.length == 2){ PreparedStatement pstmt = conn.prepareCall(SQL_SOURCE_TYPE_JOB_TABLE); pstmt.setString(1, dbName); pstmt.setString(2, tableName); return pstmt; + }else { + throw new SQLException("Incorrect input format for dataObject "+ dataObject); } } -- Gitee From 9ad3cd4e4d5c424137524e643049b549d38791bf Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Fri, 19 Jun 2020 14:14:16 +0800 Subject: [PATCH 108/238] New workspace, case, quick start code --- web/src/js/view/newhome/images/111.png | Bin 0 -> 22281 bytes web/src/js/view/newhome/images/333.png | Bin 0 -> 28244 bytes web/src/js/view/newhome/images/QR.jpg | Bin 0 -> 37822 bytes web/src/js/view/newhome/images/desktop.ini | 11 + web/src/js/view/newhome/images/edit1.png | Bin 0 -> 30795 bytes web/src/js/view/newhome/images/u1191.png | Bin 0 -> 461 bytes web/src/js/view/newhome/images/u1225.png | Bin 0 -> 684 bytes web/src/js/view/newhome/images/u1226.png | Bin 0 -> 581 bytes web/src/js/view/newhome/images/u1229.png | Bin 0 -> 283 bytes web/src/js/view/newhome/images/u476.png | Bin 0 -> 384 bytes web/src/js/view/newhome/images/u501.png | Bin 0 -> 687 bytes web/src/js/view/newhome/images/u504.png | Bin 0 -> 1190 bytes web/src/js/view/newhome/images/u509.png | Bin 0 -> 833 bytes web/src/js/view/newhome/images/u513.png | Bin 0 -> 1009 bytes web/src/js/view/newhome/images/u517.png | Bin 0 -> 433 bytes web/src/js/view/newhome/images/u619.png | Bin 0 -> 1103 bytes web/src/js/view/newhome/images/u620.png | Bin 0 -> 1226 bytes web/src/js/view/newhome/images/u621.png | Bin 0 -> 415 bytes web/src/js/view/newhome/images/u82.svg | 1 + web/src/js/view/newhome/index.vue | 3 + .../module/caseAndIntroduction/index.js | 10 + .../module/caseAndIntroduction/index.vue | 227 ++++++++++++++++++ .../js/view/newhome/module/workspace/index.js | 10 + .../view/newhome/module/workspace/index.scss | 147 ++++++++++++ .../view/newhome/module/workspace/index.vue | 157 ++++++++++++ .../module/workspace/module/workspaceForm.vue | 168 +++++++++++++ web/src/js/view/newhome/tips.md | 12 + 27 files changed, 746 insertions(+) create mode 100644 web/src/js/view/newhome/images/111.png create mode 100644 web/src/js/view/newhome/images/333.png create mode 100644 web/src/js/view/newhome/images/QR.jpg create mode 100644 web/src/js/view/newhome/images/desktop.ini create mode 100644 web/src/js/view/newhome/images/edit1.png create mode 100644 web/src/js/view/newhome/images/u1191.png create mode 100644 web/src/js/view/newhome/images/u1225.png create mode 100644 web/src/js/view/newhome/images/u1226.png create mode 100644 web/src/js/view/newhome/images/u1229.png create mode 100644 web/src/js/view/newhome/images/u476.png create mode 100644 web/src/js/view/newhome/images/u501.png create mode 100644 web/src/js/view/newhome/images/u504.png create mode 100644 web/src/js/view/newhome/images/u509.png create mode 100644 web/src/js/view/newhome/images/u513.png create mode 100644 web/src/js/view/newhome/images/u517.png create mode 100644 web/src/js/view/newhome/images/u619.png create mode 100644 web/src/js/view/newhome/images/u620.png create mode 100644 web/src/js/view/newhome/images/u621.png create mode 100644 web/src/js/view/newhome/images/u82.svg create mode 100644 web/src/js/view/newhome/index.vue create mode 100644 web/src/js/view/newhome/module/caseAndIntroduction/index.js create mode 100644 web/src/js/view/newhome/module/caseAndIntroduction/index.vue create mode 100644 web/src/js/view/newhome/module/workspace/index.js create mode 100644 web/src/js/view/newhome/module/workspace/index.scss create mode 100644 web/src/js/view/newhome/module/workspace/index.vue create mode 100644 web/src/js/view/newhome/module/workspace/module/workspaceForm.vue create mode 100644 web/src/js/view/newhome/tips.md diff --git a/web/src/js/view/newhome/images/111.png b/web/src/js/view/newhome/images/111.png new file mode 100644 index 0000000000000000000000000000000000000000..0d0dc410e3b1143178f08e9125bdaeb787753ea3 GIT binary patch literal 22281 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 literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/333.png b/web/src/js/view/newhome/images/333.png new file mode 100644 index 0000000000000000000000000000000000000000..5f696746e0434b59b66ac3d198893bcf1c5ca473 GIT binary patch literal 28244 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
)(5qUEv?c;OZjX#lpWQ4O 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 U@n-Pf;`q!C95H@j=p6ii0Eh`!cK`qY literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/QR.jpg b/web/src/js/view/newhome/images/QR.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f85da5edab90395d797154fde95c82226ac9747d GIT binary patch literal 37822 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 TG+_u)00000NkvXXu0mjfdj0cY literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/u1229.png b/web/src/js/view/newhome/images/u1229.png new file mode 100644 index 0000000000000000000000000000000000000000..11052cd14c1a0401a56c366ea39a6f12703bae21 GIT binary patch literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^MnKHN!3HE1{NLpODaPU;cPEB*=VV?2IV|apzK#qG z8~eHcB(eheoCO|{#S9F5he4R}c>anMpx_2i7sn6}@8lGTo&}AGrW39t{5WqQ?r}aL zBjpF9*l}jI)$Z?@Jy|*0AF^I>p6ejBzJ11mF9~cy2Ohj*fApK@D-Wx~8AefeM(2ad z1`XGpdk$pS@GkLHxTDA#FiGZw@_)rg&SDKVSFEN?64PVwO0rSt-@{nkF870>r_)U# zjAfFn^THpl>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0ToF^K~yMHm6APA z0znXlX9i;|_yO2k(EHWc@Ef$TAeyKYBqmZ)8F~^ahy|3E*jrFsA&rW$vGWhmYof`K zeVrXw%yL|UPc@4M+WLX)Y}XF=6Ji6&UTM^7`A$09M%6yIDeVpssb)gIkNXc)PoLqp%(6>Z+kn!;D7V;uYNGQmpv zg~1}Rw<8@N^4XKSkKRI6fPlD`|6c-X4&^e2zW{3L#WN<$4t eDpvDEBBF2OS$&L9INbyQ0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0z^qfK~z{r#g-vY z98na7cP0n~V#NwX1tcUztRU$otRMl?qym9JP=_dvx{7)v5>ZjnAJ94k0+I@v06|a` zB;5poC<%g1K#$bJ5uZ7= zjJ{Al5hm1$->%hv$bCnmuMMh)PK`e>{zxo5I9DaFD}DsIYh+Gy?)kR^;lvEF#V%sR zQjg%A7K3kuUNh}F^s4+J>YURG^^#a5KZ?d+j^@4%!%#h(G07p~grW%@4+=cmc#IS6 zXaOOyG-y+SM-{KtXsjRpgCmkfd=&bE@kMmim`*VGW%;srty|r2<5FqJxQGwF7u@b? z87F?M2S{DU{>xi_sxmHS=kEazb4|w2f{bt7usnFUZe`qZho#bz@qrtc%6`CQ4-;qn z;XS`9MWfrSB{Sql|M3cm#656P;Gs|Bdps{(23WJT3D_hu?<|v`=QXj-&^7~=%3mtx Vga(ro=XwAD002ovPDHLkV1k@bF=YS% literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/u504.png b/web/src/js/view/newhome/images/u504.png new file mode 100644 index 0000000000000000000000000000000000000000..59fd43ac276892b0a3870a09e67bd15e6404c7a5 GIT binary patch literal 1190 zcmV;X1X=ruP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1UpGYK~!i%?U-9^ z6jd0<=epgpS`u1lDA)=Ji6Egw5-}l0!AR6#hyfy`1PB;4kU;Rw2OoSep^*fhl;9i2 zs7;I{VuaEvu_PFvt(X!}Zqib0YZ036?%d8C|FiprOykaFXQtYR{biG#|Cuwp|2dcM zeCLRqb786?(f5?3VlFBbb5WVn<`N4f_UNzX^)^vbltnF4&3r12M*`+x%jjw4#)DMz zyMibiy$7Yt9Ch(dsct#dh)Q&GJUeI&bXaJu)O2;pTk`BxbVCr>-7d552<$44uag_s zN{=+sjWQ|69MkQw8_s9sqIKttn5t2lUQwD}6*CP~VIubUZ8p%s`cH9fRBm`)n)x)k zTdJ8SND9>mBETHp-n@L2-95{5gMysKPdk55+bqvrBdQsy6bRGV&^h$JJ$4h0F)mRC zuj=AA(dxx2rGYsgvfr#WZ+&a$hDaxeHTYA$y@iAaexZa7Uy$opIvrO%i;9xN8KY{3 z=Z8s`!Z*$_4Fij=Cjn7ZIMYa!qOw9nB{6dtJ=Py5tQ%h=)=*Jwk}zjm#)S{EUp%Fq z-m3kuE7!I{JM%U-vvfBG37Es$W&Cmo7D)?&b?qzt$6X|15Z4@{zj5gh2^ZGwlL)*d zq7v7fgApb;&yOl8AwyIiw8S7$f0}HPA^{1=#R;q%$OZ5f#7G#@F1mdY&I5;SFLh z@-`9$5Ri@TRubNDeH3j>q7=U7s%QCU4M@(6?gLuq4$>~nzK^x`&GuhCUUM06?^{Iz z#+;a*fmD&iM9kkm&wbf!^c?W|dxW~&@iltaKGGAxYX|Ow0?Z-lWqA8ZfQ|G>6Q|L? z2}skiid(;ZmRj*XX%|>MF=$A5gCSpXVCh|Z@w5J8E_j2JKe@4bZ5s&}=oc*WB)mz# z@M(!en(25p{o*l_9t3nNkn5IXZ$cs=teeN>$6g}gLt!W32X;64&YdI@BKQ3UZfPXE z32r%biu7n>{1oFMNT`&#s|C4=v=3y`7hAs{xQz=7Geb5T2yQumbxdw}4sn%q42<4` z>cY*Tnk~$PD1zO&{r8oaor|!{^?St`skq%9i^EoVB#?S9b_0Oma zw@{HcM(;;_yua$%){v9HP1p(HMpQFZs}A$*Aoiy|TWH+UI=73}^{5=d8Hmzy4{;7$ zyFV1GYSrfb?)=9ozjW9+@m#t)&iQaGb43te%)U=>p)T6WndThCPMecjwm1I4Spw#Y zpqI_7$IyN1lRE;=D?^i*xyc~Pg!s>>n2SoqTr>pXAL#-fg>$5C-T(jq07*qoM6N<$ Eg3LZKEC2ui literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/u509.png b/web/src/js/view/newhome/images/u509.png new file mode 100644 index 0000000000000000000000000000000000000000..986e39719427393967ecf944b43164db875a9042 GIT binary patch literal 833 zcmV-H1HSx;P)500001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0@g`HK~z{ry_YX+ z6hRb+?=BT5Dk=~a2uMyKAVDHdAP^Om6%`dtAfWYI+Nt+-_4!*bZ>(cJd-0YCs`;wP8e|~S?yWQEn*~b4e91hq2cwqdQ zB$I=rN6PPGTCyZs@<~ugr`c=<6H?3-HIoPyV+)dW2kU7lhe9r?8KNVf!#YdY>*PWS z=n{B<&#m&&~Of8wtiPB{UGXKhc2XE$n(SUDRoA1&-B?3GiuigdF-}7c0EV2m{;&0QwW9%blaaDPwJaMS}35$=! zE;DvjAsO`TY22112%7f_@q=a-(Hypl#oi;OxAIw#EIVZw)>y$^$Jz?Ze$5tE`Q3sx zzVX1;RY(-H``BjFI*P9Z@@uVD>yx@c(Afq(biHaM{cDrpxJn_0ZBX=;w5KE$17GB; zlB7>9rgSujkfcxEGjN$(@J;O?EZfG8&`xP6N{fJ}*l+ctpna(3NYJgP6oUTWEu~{8 zyLqffdn9NU6y^oVEi@-i?Z+Nv>>kaVSblITfhhWCiKdS`cMhiCW_$yS6*5pr9K?%? zi-L9+vs2vw8(G9D=vI{~4&oPzs|D8I!^IDA2-jRly^v=|Dg7X@Kgvp%dK}mfSL%%7 zOYe5d<2VNH%9o*7d%W}SrMe;4l2ZFY6Z&qlvHSQ+n;YE+tcQ7j9OKoVD73{d%3WOk zS!xTp89&T#NNQ`@q3x}k$>wZNE^E3P1lTS6jM)*i_;TxFL5NwAG=rfj#`>5YqUJR` z9$0)f%Nl@$bCOO55(bZ|%w3c$iPZDVS>DN?gIZp48vL$q0*%IB^zX7KjaOb000000 LNkvXXu0mjfjuv?x literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/u513.png b/web/src/js/view/newhome/images/u513.png new file mode 100644 index 0000000000000000000000000000000000000000..97905ddd3b40ad5b200571701bf1cd47412692be GIT binary patch literal 1009 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1BOXNK~z{ry_i2p z)ln43eJ=+GA&DRdA%`F-2Zx4+HwXziIM^6CI5@Nj4Gl&PZ4C|%jkY&5XcQD=ROGHw zkfD&FP|+KT0tG|+eD1ry*L%J9#6R!%`@;8~bMHO(ocsITd+xpOmuuMvySux+h^|~N z*NN=j+uJ*XR8J_rCdBR=aveK$xun5?K&Jr$-iM#ij|F^ez!^9g-PZ!UVGI^aU7C;R zdpL$Gfy(JpbNV3GBSh;7ekPcU$vB48L97eJJe6Yvs}#<~`b{WLy-zk+2G zfUhn147ERo2{4a`^7;JJSPsCb4N*W|MS4*5@p_U&VPDXvhPB?|lh=qXoN?yP*il?LPv4O94 ze2&0bV}xL!?#@M(qhEl&u8&Ga>C^l`ZwUHzKo?IRJP&E2Y)3x z>p5=(d=&kefSH1aoem>ViFK)iSm8Vlfdz$3Zy+_7JsJm~`8&wGxj2pt{Ft8e@G+@s z%9i2ca-SZDE3vK&I+}NvP+h4PVK+3NWhKmG^Vgf@GE!e=!aA}F`17`UPsP`;1HDaB!3zGwwrD+a zld?8m_}xa`?M_0cCD3|gT^M*4gX;Tk%3zR72EL5$0&6c-rwf8^6YF|X=wSe>$W#$y z6hhDhR5(wgG``cQnZV}<#3(G!xu=tdeAT}?3{9&ccm=vpJOmCj75Fo!Jw(>%^9DJG ztlA^=?;P)-KcMk8Y-2V2x1SFuZZ^k{|t=4UJh`u#fXJ7S3y@vmR zGw00#NjH|TfdKpZhTK3p4(My!iJn5q6vTXJboW#b=S)B>_w7=KpcvfEygd2MhQ5t~ zT6->7N#hvw-$eN;dQ|8GdS$*ru_|E0&rKS_0o3rh3H>a3@|nqePA>H2&rOp0&(Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0Y*tgK~z{r?UkWU z1TheXx2w*QAUFkr1OyU+L?U?v9sojjDH z$b`u}(Hv^pa7fY;HQLZN38lT!+bHH{u;7Je7`hNV$}a+b%MoZuF^f`GMZ#59gP3nh~Z!Ax?ams zx`|u@2jX=XMqukEPi1B-pM%@4Xc6+S(1nI^q_ipI6QNy`{J$fp7`Z7%ZiPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1LR3WK~z{ry_u~~ z96=a|xyuOz0)aq~Z~}p>KwMG;q5{DmfS|4dfkYrGnjnw}L`9n*sHsAYQXaWfh^!d%a$Fa=p-0t4Tle{;(@7L_j&dkls)kZ3EdwbhNTD4kD?7AMAc6cWJPnSE783=#T4{&NSqte3{!_>nl5Ab< z>lP9R2MvhaB-k{HADMe;h;5Q1cfes&OV68o77Ut7Qo$c6#?8Gl>Rk( zY9x=sQ%M_(bC@a#ZkjVMeMG=QosX9JWwIV>9Kg5Iig+kc*AE)%uif5fMh_UgVmTA^%Wj8-wh0e$ zEja40GyJnM3ZqUdnCQqemnsBx(nt+GVDKt2j8j+Y*W)ohu`kvOu{U`deL#UR+Bc0W zE0d6;(7r={Y81P@&q<9}^&I1-DefTXX}w;L&QI91+F0~=aqzh!?|UTH`7_|FCDwtz z>wx~X`qK&*0qBdZaQgstZCkY&)OdQzS$~@aqc${CmSbR0mDY#RMKXH-mbf@DT?X`9 z&S8L1$EsDA0lk)aev{9QcKiY8lZ(z?A-5I^d4~ZT=H?u=c+^rm0KK*W{hm@Bx4BBkx zZnCi*B9%urDb(kpueA;KWpj^%Lv&QN!LHLOEz`?vq%@VRB6$PCfqmOT(%`7Gk|g+C zBHB7WL4tiOx(Q@nl_FiwYw*zyuUHqtQJZ+Tzby*>>O05C5mM>^34c9YxLNN8fjYG8 zdhpW=;-bF#nS_#DCC^wlAU`tBZ*TFzC2{OX%)$g!`k zIK*fKZy=@4rfXJ~hKd#_ba1I%p??-bUNGq8$zZ2iqPK>+Gi)X5+Nfa{{gT$ Vp7osyv<3hG002ovPDHLkV1j#G23r6C literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/u620.png b/web/src/js/view/newhome/images/u620.png new file mode 100644 index 0000000000000000000000000000000000000000..05c87dec578e8d99c342cf438d99f7b33e18058d GIT binary patch literal 1226 zcmV;*1U37KP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1Yb!+K~!i%-I*^; z98nO);etRQ5C{ZgA`qCSBozpnASx;l6*Os^3eq4d zDiAb5K!T`1LenNRp$SdercG#|zwhnr-rnBs-tOJrLHZ>hH*em&*_plfXWr4(E?iz- z4qjYbJcbAGBV2_e)_wg!u;cJ0JSUktpx=VG&HQ?S_<9L$79M!vHU_qbZ~?L3+*}<9 zVwhl7;Hir)1a#-{4Pph3A+N*Vt}_I5Kj2fuo94E2;K60M3G1d0x)Z3iF=XZe=pKMe z^c^|l2++UhW75pq3m!HN;}Y0|Gl;!rnh0!q;FJYk1NnvvX4*dRkk9r^|Djsg5nEoY_~?b2a^Y`!!n%uxoO{oxLT?Z1jgFdGW-wfv zh0d2V&sz;Tn@AW0q&YtYdu&K7=%2(kcC!fK>JsrmfZCOo;D8O)*go|0@K82Upm!C3 zHHE8B#0P%!%+uRaT5yvvA;B>t)z$ zIgF!gSngy7&iYw|i!ip(%YkKcSp)p){;~n%D&yEqAs28^R|B<(AQ5EUUuNK**Odc|=wnL{ z+JjKVUQiJyK{hb1{6B>&h~f3&fG)9=LFZ39uX>;{0_(Czm-*&~O%Jwr;f@=e0obY} znMG{4ps^c*NjFiwpt6iMOy@vbcjqh@W<-q!XT z{YB&0_|vuWL#Op8_}#T?A)S1Gajl%NgVe=G{C}O&Lq%D}f-H~VB4Va*23y_ZGi?Ca z1Pj}Srvf|ea&s_t0}v7u@u9%rI%3^nh)xgC9e&ptN1(ALCITD%csGYwceO>Y^_x~X z2b(~{M8aU;4piV;d=0lzs4X`W7;^>{w1U3_x2&rM=z~L&&tR9$l}H+Jsz7vy54KU{ z%!xDtzIWj?VsHc$nh4Gkw^4L0C4yf~YpuJoxvT;D))O%&soN<1O(%l?H9k^ntZ*W& zl<~)GhaXHX9Qb|t8r|o&$nt2fX z9E9u=@YGeHQ{|u+SG``)NDL+p7F=oqd<1U|dBVnIg?>XzOaP{D&va%=h<;s&8YU10 zeVGz6KQ%ztIDsfI&if6eCJ+U-nZKc?5{QDqsR`vxAPUANCR9iQQQ*u^NcR*~xVqLh ooj?@$QbO;bf>(u`BZ022f9^L#hPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0W?WOK~z{r?U%7? z0znXl_rxNFjc|p9g}n)+wDbWiEG%sE4npu9gx~`N;v3j$X<=buZ>dEdAfUxT;MQ;4 zK`n$33^<1UV3~jCmb+nwo#7G>&M*bFW-${Wg|6TC%q%{i!!qhldkysFkhQMHlcFcV z>%FO4Oeh;ng$zCf&mFXx$iF9!x@$2LAcf3WA1wL(JRv0(ZanI~F*Q9dqwXy{u`}vs zG-qkj2hbyxW=i}_vX0XO-B4-jw{uM9hS*28ujs1yW1G1S=k|&Txr!Cv|9t=e002ov JPDHLkV1jk)u)_cV literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/u82.svg b/web/src/js/view/newhome/images/u82.svg new file mode 100644 index 000000000..e67551d38 --- /dev/null +++ b/web/src/js/view/newhome/images/u82.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/js/view/newhome/index.vue b/web/src/js/view/newhome/index.vue new file mode 100644 index 000000000..09d9d0d42 --- /dev/null +++ b/web/src/js/view/newhome/index.vue @@ -0,0 +1,3 @@ + diff --git a/web/src/js/view/newhome/module/caseAndIntroduction/index.js b/web/src/js/view/newhome/module/caseAndIntroduction/index.js new file mode 100644 index 000000000..9ea52ad7e --- /dev/null +++ b/web/src/js/view/newhome/module/caseAndIntroduction/index.js @@ -0,0 +1,10 @@ +export default { + name: 'CaseAndIntroduction', + events: [], + dispatchs: { + }, + data: { + API_PATH: process.env.VUE_APP_MN_CONFIG_PREFIX || `http://${window.location.host}/api/rest_j/v1/`, + }, + component: () => import('./index.vue'), +}; \ No newline at end of file diff --git a/web/src/js/view/newhome/module/caseAndIntroduction/index.vue b/web/src/js/view/newhome/module/caseAndIntroduction/index.vue new file mode 100644 index 000000000..6a84b0813 --- /dev/null +++ b/web/src/js/view/newhome/module/caseAndIntroduction/index.vue @@ -0,0 +1,227 @@ + + + + diff --git a/web/src/js/view/newhome/module/workspace/index.js b/web/src/js/view/newhome/module/workspace/index.js new file mode 100644 index 000000000..01be3f453 --- /dev/null +++ b/web/src/js/view/newhome/module/workspace/index.js @@ -0,0 +1,10 @@ +export default { + name: 'Workspace', + events: [], + dispatchs: { + }, + data: { + API_PATH: process.env.VUE_APP_MN_CONFIG_PREFIX || `http://${window.location.host}/api/rest_j/v1/`, + }, + component: () => import('./index.vue'), +}; \ No newline at end of file diff --git a/web/src/js/view/newhome/module/workspace/index.scss b/web/src/js/view/newhome/module/workspace/index.scss new file mode 100644 index 000000000..9987fbef0 --- /dev/null +++ b/web/src/js/view/newhome/module/workspace/index.scss @@ -0,0 +1,147 @@ +@import '../../../assets/styles/variables.scss'; + +.page-bgc { + background-color: #f7f7f7; + background: #fff; + + .page-bgc-header { + padding: 10px 25px 0; + } + + .header-info { + padding: 10px 0 10px 20px; + + p { + line-height: 24px; + } + } + + .workspace-main { + padding: 10px 25px; + display: flex; + justify-content: flex-start; + align-items: flex-start; + + .left { + flex: 1; + box-shadow: 0 1px 6px rgba(0, 0, 0, .2); + border-color: #eee; + min-height: 500px; + + .workspace-type-header { + padding: 10px 20px 0; + line-height: 30px; + display: flex; + justify-content: flex-start; + align-items: center; + + .workspace-type-header-label { + font-size: 14px; + display: inline-block; + margin: 0 5px; + font-weight: 900; + } + } + + .workspace-create-search { + padding: 0 35px; + display: flex; + justify-content: flex-start; + align-items: center; + margin: 10px 0 50px 0; + + .workspace-create { + flex-basis: 200px; + display: flex; + justify-content: flex-start; + align-items: center; + padding: 15px 10px; + &:hover { + box-shadow: 0 2px 12px 0 rgba(0,0,0,.2); + border-radius: 4px; + } + .workspace-create-text { + margin-left: 10px; + cursor: pointer; + } + } + + .header-search { + flex: 50%; + } + } + + .item-header { + font-size: 14px; + margin: 20px 25px 10px 25px; + font-weight: bold; + padding-left: 5px; + border-left: 3px solid $primary-color; + } + + .workspace-content { + .content-item { + .workspace-item { + cursor: pointer; + height: 180px; + margin: 15px; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.2); + background: #fff; + padding: 10px; + position: relative; + background: url("../../../assets/images/workspace.png") center center no-repeat; + background-size: cover; + min-width: 222px; + .name { + display: block; + font-size: 16px; + font-weight: 600; + color: white; + } + + .desc { + width: 100%; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + text-overflow: ellipsis; + word-break: break-all; + color: white; + } + + .lable-list { + position: absolute; + left: 10px; + bottom: 30px; + display: flex; + justify-content: flex-start; + align-items: flex-start; + width: 100%; + .item { + display: inline-block; + font-size: 10px; + padding: .3em .9em; + margin: 0 .5em .5em 0; + white-space: nowrap; + background-color: #f1f8ff; + border-radius: 3px; + color: #0366d6; + overflow: hidden; + text-overflow: ellipsis; + max-width: 31%; + } + } + + .editor { + position: absolute; + right: 10px; + bottom: 10px; + } + } + } + } + } + } + +} diff --git a/web/src/js/view/newhome/module/workspace/index.vue b/web/src/js/view/newhome/module/workspace/index.vue new file mode 100644 index 000000000..953c1f68a --- /dev/null +++ b/web/src/js/view/newhome/module/workspace/index.vue @@ -0,0 +1,157 @@ + + + diff --git a/web/src/js/view/newhome/module/workspace/module/workspaceForm.vue b/web/src/js/view/newhome/module/workspace/module/workspaceForm.vue new file mode 100644 index 000000000..e297a552a --- /dev/null +++ b/web/src/js/view/newhome/module/workspace/module/workspaceForm.vue @@ -0,0 +1,168 @@ + + diff --git a/web/src/js/view/newhome/tips.md b/web/src/js/view/newhome/tips.md new file mode 100644 index 000000000..99a8d9821 --- /dev/null +++ b/web/src/js/view/newhome/tips.md @@ -0,0 +1,12 @@ +#### 开发注意 + +1. 自定义首页就在idnex.vue文件下开发,需要的工作空间和案例、快速入门在./module下,需要自行调试哦!!! + +2. 新增其他页面在view下面新建文件夹,页面对应的路由在:src\js\service\router.js下自行配置 + +3. 开发过程中可以使用:src\js\component下的公共组件,尽量不要修改,造成不通用,也可以新增组件 + +4. 目前开源的还没工作空间概念,所以对应的接口服务还没有,需要后台上传对应服务代码 + +5. 开发过程有问题随时联系 ![扫码加入](images/QR.png) + -- Gitee From 07c1aeb40713161dc3027e40877fce0f3d96d336 Mon Sep 17 00:00:00 2001 From: luxiaolong Date: Fri, 19 Jun 2020 14:26:45 +0800 Subject: [PATCH 109/238] add workspace router --- web/src/assets/styles/workspace.scss | 207 +++++++++++++++++++++++++++ web/src/js/service/router.js | 9 ++ web/src/js/view/workspace/index.vue | 78 ++++++++++ web/vue.config.js | 26 ++++ 4 files changed, 320 insertions(+) create mode 100644 web/src/assets/styles/workspace.scss create mode 100644 web/src/js/view/workspace/index.vue diff --git a/web/src/assets/styles/workspace.scss b/web/src/assets/styles/workspace.scss new file mode 100644 index 000000000..0a0b2739c --- /dev/null +++ b/web/src/assets/styles/workspace.scss @@ -0,0 +1,207 @@ +/*! + * Copyright 2019 WeBank + * + * 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. + * + */ +@import './variables.scss'; + +.entry { + font-size: 16px; + height: 120px; + line-height: 120px; + background: #515a6e; + margin: 10px 30px 10px 10px; + color: #FFF; + text-align: center; + cursor: pointer; + + &:hover { + font-weight: 600; + + .icon-blod { + font-weight: 600; + } + } +} + +.no-data-bgc { + font-size: 14px; + position: absolute; + top: 0; + bottom: 40px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + + .no-data-img { + width: 200px; + margin-top: 150px; + } + + .bg-text { + width: 60%; + text-align: left; + display: block; + line-height: 40px; + + &.weight { + margin-top: 10px; + font-weight: bold; + } + + &.indent { + text-indent: 2em; + } + } +} + +.icon-blod { + margin-right: 2px; +} + +.sort-icon { + margin-top: 10px; + margin-right: 8%; + float: right; + color: #2d8cf0; + cursor: pointer; +} + +.icon { + margin-left: 5px; + color: #2d8cf0; +} + +.header-search { + padding: 0 35px; + overflow: hidden; + + .search-input { + width: 200px; + } +} + +.page-bgc { + background-color: #f7f7f7; + background: #fff; + + .page-bgc-header { + padding: 10px 25px 0; + } + + .header-title { + font-size: 14px; + font-weight: bold; + padding-left: 5px; + border-left: 3px solid $primary-color; + } + + .header-info { + padding: 10px 0 10px 20px; + + p { + line-height: 24px; + } + } + +} + +.workspace-main { + padding: 10px 25px; + display: -webkit-box; + display: flex; + -webkit-box-pack: start; + justify-content: flex-start; + -webkit-box-align: start; + align-items: flex-start; + + .item-header { + font-size: 14px; + font-weight: bold; + padding-left: 5px; + border-left: 3px solid $primary-color; + } + + .left { + flex: 1; + box-shadow: 0 1px 6px rgba(0,0,0,.2); + border-color: #eee; + padding: 0; + } + + .right { + margin-left: 25px; + width: 500px; + box-shadow: 0 1px 6px rgba(0,0,0,.2); + border-color: #eee; + padding: 0; + } + + .app-list { + display: flex; + + .app-item-wrap { + display: flex; + margin: 20px 10px 10px 50px; + padding: 10px; + cursor: pointer; + + &:hover { + box-shadow: 0 2px 12px 0 rgba(0,0,0,.2); + border-radius: 4px; + } + + .label { + margin-left: 10px; + width: 110px; + font-weight: 700; + font-size: 14px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + line-height: 30px; + height: 30px; + } + } + } +} + +.app-list-tabs { + flex: 1; + // border: 1px solid #eee; + padding: 20px; + border-radius: 6px; + margin-bottom: 20px; + position: relative; + -webkit-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; + + &:hover { + box-shadow: 0 2px 7px rgba(0,0,0,.15); + border-color: transparent; + position: relative; + } +} + +.input-wrap { + position: absolute; + right: 20px; + top: 20px; + width: 200px; +} + +.radio-box .ivu-radio .ivu-radio-inner { + border: 1px solid #2d8cf0; +} diff --git a/web/src/js/service/router.js b/web/src/js/service/router.js index 7e6b57b55..194890ba6 100644 --- a/web/src/js/service/router.js +++ b/web/src/js/service/router.js @@ -65,6 +65,15 @@ const router = new VueRouter({ }, component: () => import('../view/workflow/index.vue'), }, + { + path: 'workspace', + name: 'workspace', + meta: { + title: 'Workspace', + publicPage: true, + }, + component: () => import('../view/workspace/index.vue'), + }, { path: 'commonIframe', name: 'commonIframe', diff --git a/web/src/js/view/workspace/index.vue b/web/src/js/view/workspace/index.vue new file mode 100644 index 000000000..1fdf70ddf --- /dev/null +++ b/web/src/js/view/workspace/index.vue @@ -0,0 +1,78 @@ + + + + \ No newline at end of file diff --git a/web/vue.config.js b/web/vue.config.js index d95110227..78edce85e 100644 --- a/web/vue.config.js +++ b/web/vue.config.js @@ -32,6 +32,32 @@ const getVersion = () => { module.exports = { publicPath: './', outputDir: 'dist/dist', + devServer: { + port: 8091, + open: true, + disableHostCheck: true, + overlay: { + warnings: false, + errors: true + }, + proxy: { //代理转发 + '^/api/rest_j/v1': { + target: 'http://127.0.0.1:8089', //后端服务地址 + ws: true, + changeOrigin: true, + pathRewrite: { + '^/api/rest_j/v1': '/api/rest_j/v1' + } + }, + '^/ws/api': { //websocket + target: 'ws://127.0.0.1:8089', + ws: true, + secure: false, + // logLevel: 'debug', + }, + } + // after: require('./mock/mock-server.js') + }, chainWebpack: (config) => { if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'sandbox') { config.plugin('compress').use(FileManagerPlugin, [{ -- Gitee From 2ee72d9fa5e1e9dbb98b3bd76f1985b7889c8f2c Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Fri, 19 Jun 2020 16:03:51 +0800 Subject: [PATCH 110/238] flow runtime execute cost time is not correct #Fixes #162 --- .../execution/entrance/restful/FlowExecutionRestfulApi.java | 6 ++++++ .../flow/execution/entrance/node/DefaultNodeRunner.scala | 5 +++++ .../dss/flow/execution/entrance/node/NodeRunner.scala | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/dss-flow-execution-entrance/src/main/java/com/webank/wedatasphere/dss/flow/execution/entrance/restful/FlowExecutionRestfulApi.java b/dss-flow-execution-entrance/src/main/java/com/webank/wedatasphere/dss/flow/execution/entrance/restful/FlowExecutionRestfulApi.java index 807de6029..8ad6dcb51 100644 --- a/dss-flow-execution-entrance/src/main/java/com/webank/wedatasphere/dss/flow/execution/entrance/restful/FlowExecutionRestfulApi.java +++ b/dss-flow-execution-entrance/src/main/java/com/webank/wedatasphere/dss/flow/execution/entrance/restful/FlowExecutionRestfulApi.java @@ -70,6 +70,12 @@ public class FlowExecutionRestfulApi { message = Message.ok("Successfully get job execution info"); message.setMethod("/api/entrance/" + id + "/execution"); message.setStatus(0); + long nowTime = System.currentTimeMillis(); + flowEntranceJob.getFlowContext().getRunningNodes().forEach((k, v) -> { + if (v != null) { + v.setNowTime(nowTime); + } + }); message.data("runningJobs", FlowContext$.MODULE$.convertView(flowEntranceJob.getFlowContext().getRunningNodes())); List> pendingList = FlowContext$.MODULE$.convertView(flowEntranceJob.getFlowContext().getPendingNodes()); pendingList.addAll(FlowContext$.MODULE$.convertView(flowEntranceJob.getFlowContext().getSkippedNodes())); diff --git a/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/DefaultNodeRunner.scala b/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/DefaultNodeRunner.scala index 89ddc910a..ad2526f03 100644 --- a/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/DefaultNodeRunner.scala +++ b/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/DefaultNodeRunner.scala @@ -49,6 +49,8 @@ class DefaultNodeRunner extends NodeRunner with Logging { private var startTime: Long = _ + private var nowTime:Long = _ + private var lastGetStatusTime: Long = 0 override def getNode: SchedulerNode = this.node @@ -156,4 +158,7 @@ class DefaultNodeRunner extends NodeRunner with Logging { override def setStartTime(startTime: Long): Unit = this.startTime = startTime + override def getNowTime(): Long = this.nowTime + + override def setNowTime(nowTime: Long): Unit = this.nowTime = nowTime } diff --git a/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/NodeRunner.scala b/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/NodeRunner.scala index 5e090fe29..f0a40fd57 100644 --- a/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/NodeRunner.scala +++ b/dss-flow-execution-entrance/src/main/scala/com/webank/wedatasphere/dss/flow/execution/entrance/node/NodeRunner.scala @@ -75,6 +75,10 @@ abstract class NodeRunner extends Runnable with Logging{ def setStartTime(startTime: Long): Unit + def getNowTime():Long + + def setNowTime(nowTime: Long):Unit + protected def transitionState(toState: NodeExecutionState): Unit = Utils.tryAndWarn{ if (getStatus == toState) return info(s"from state $getStatus to $toState") -- Gitee From 041c414594b608e16787df715909d7ad0aaa8129 Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Fri, 19 Jun 2020 16:30:13 +0800 Subject: [PATCH 111/238] The script in the workflow has been executed, but the execution time has been increasing, and the process does not go down #Fixes #165 --- .../node/execution/parser/JobParamsParser.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/parser/JobParamsParser.java b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/parser/JobParamsParser.java index 5c9e013c6..27174fbcc 100644 --- a/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/parser/JobParamsParser.java +++ b/dss-linkis-node-execution/src/main/java/com/webank/wedatasphere/dss/linkis/node/execution/parser/JobParamsParser.java @@ -24,8 +24,10 @@ import com.webank.wedatasphere.dss.linkis.node.execution.job.LinkisJob; import com.webank.wedatasphere.dss.linkis.node.execution.job.Job; import com.webank.wedatasphere.dss.linkis.node.execution.job.SignalSharedJob; import com.webank.wedatasphere.dss.linkis.node.execution.utils.LinkisJobExecutionUtils; - +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -33,7 +35,7 @@ import java.util.Map; * Created by johnnwang on 2019/11/3. */ public class JobParamsParser implements JobParser { - + private static final Logger LOGGER = LoggerFactory.getLogger(JobParamsParser.class); private JobSignalKeyCreator signalKeyCreator; public JobSignalKeyCreator getSignalKeyCreator() { @@ -61,8 +63,12 @@ public class JobParamsParser implements JobParser { if (sharedValue != null) { Collection values = sharedValue.values(); for(Object value : values){ - Map variableMap = LinkisJobExecutionUtils.gson.fromJson(value.toString(), new TypeToken>() {}.getType()); - putParamsMap(job.getParams(), "variable", variableMap); + List> list = LinkisJobExecutionUtils.gson.fromJson(value.toString(), List.class); + Map totalMap = new HashMap<>(); + for (Map kv : list) { + totalMap.putAll(kv); + } + putParamsMap(job.getParams(), "variable", totalMap); } } // put configuration -- Gitee From cf84655162bbadf2ea5c0cd85ec3a151c3d37720 Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Fri, 19 Jun 2020 21:17:23 +0800 Subject: [PATCH 112/238] run_date variable can not be shown correctly #Fixes #161 --- .../entrance/execute/AppJointEntranceEngine.scala | 15 +++++++++++++++ pom.xml | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/plugins/linkis/linkis-appjoint-entrance/src/main/scala/com/webank/wedatasphere/dss/linkis/appjoint/entrance/execute/AppJointEntranceEngine.scala b/plugins/linkis/linkis-appjoint-entrance/src/main/scala/com/webank/wedatasphere/dss/linkis/appjoint/entrance/execute/AppJointEntranceEngine.scala index 26e4305d4..e16c9b93e 100644 --- a/plugins/linkis/linkis-appjoint-entrance/src/main/scala/com/webank/wedatasphere/dss/linkis/appjoint/entrance/execute/AppJointEntranceEngine.scala +++ b/plugins/linkis/linkis-appjoint-entrance/src/main/scala/com/webank/wedatasphere/dss/linkis/appjoint/entrance/execute/AppJointEntranceEngine.scala @@ -31,6 +31,7 @@ import com.webank.wedatasphere.dss.linkis.appjoint.entrance.job.AppJointExecuteR import com.webank.wedatasphere.linkis.common.exception.ErrorException import com.webank.wedatasphere.linkis.common.utils.{Logging, Utils} import com.webank.wedatasphere.linkis.entrance.execute.{EngineExecuteAsynReturn, EntranceEngine, EntranceJob} +import com.webank.wedatasphere.linkis.entrance.interceptor.impl.CustomVariableUtils import com.webank.wedatasphere.linkis.protocol.engine.{JobProgressInfo, RequestTask} import com.webank.wedatasphere.linkis.protocol.query.RequestPersistTask import com.webank.wedatasphere.linkis.scheduler.executer._ @@ -156,6 +157,9 @@ class AppJointEntranceEngine(properties: util.Map[String, Any]) val nodeType = nodeContext.getAppJointNode.getNodeType val realAppJointType = if (nodeType.contains(".")) nodeType.substring(0, nodeType.indexOf(".")) else nodeType val appJoint = AppJointManager.getAppJoint(realAppJointType) + if((realAppJointType.toLowerCase()).contains("datacheck")){ + replaceCustomVariables(nodeContext.getRuntimeMap) + } val user = if (null != runTimeMap.get("user")) runTimeMap.get("user").toString else null val session = if (StringUtils.isNotEmpty(user)){ if (appJoint.getSecurityService != null) appJoint.getSecurityService.login(user) else null @@ -189,8 +193,19 @@ class AppJointEntranceEngine(properties: util.Map[String, Any]) ErrorExecuteResponse(s"cannot do this executeRequest $executeRequest", new ErrorException(80056, s"cannot do this executeRequest $executeRequest")) } + private def replaceCustomVariables(runTimeMap:java.util.Map[String, Object]):Unit = { + val key = "check.object" + val value:String = if (null != runTimeMap.get(key)) runTimeMap.get(key).toString else "" + val task = new RequestPersistTask + task.setExecutionCode(value) + task.setParams(new util.HashMap[String, Object]()) + val (result, code) = CustomVariableUtils.replaceCustomVar(task, "sql") + logger.info(s"after code replace code is $code") + if (result) runTimeMap(key) = code + } } + case class AppJointEntranceExecuteException(errMsg:String) extends ErrorException(70046, errMsg) class AppJointEntranceAsyncExecuteResponse extends AsynReturnExecuteResponse with Logging{ diff --git a/pom.xml b/pom.xml index 76737321d..ff14d65f7 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ 0.7.0 - 0.9.3 + 0.9.4 2.11.8 1.8 3.3.3 -- Gitee From e7e6ffeb5d89e2e0a22160624cf21f66421f996f Mon Sep 17 00:00:00 2001 From: "xing.huang" Date: Mon, 22 Jun 2020 11:28:33 +0800 Subject: [PATCH 113/238] 'utf-8' is not a valid value for the Content-Encoding header --- .../scheduler/azkaban/service/AzkabanProjectService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/service/AzkabanProjectService.java b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/service/AzkabanProjectService.java index 2f2f98e4d..eb536b14b 100644 --- a/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/service/AzkabanProjectService.java +++ b/dss-azkaban-scheduler-appjoint/src/main/java/com/webank/wedatasphere/dss/appjoint/scheduler/azkaban/service/AzkabanProjectService.java @@ -80,11 +80,11 @@ public final class AzkabanProjectService extends AppJointUrlImpl implements Sche params.add(new BasicNameValuePair("name", project.getName())); params.add(new BasicNameValuePair("description", project.getDescription())); HttpPost httpPost = new HttpPost(projectUrl); - httpPost.addHeader(HTTP.CONTENT_ENCODING, "UTF-8"); + httpPost.addHeader(HTTP.CONTENT_ENCODING, HTTP.IDENTITY_CODING); CookieStore cookieStore = new BasicCookieStore(); cookieStore.addCookie(session.getCookies()[0]); - HttpEntity entity = EntityBuilder.create().setContentEncoding("UTF-8"). - setContentType(ContentType.create("application/x-www-form-urlencoded", Consts.UTF_8)) + HttpEntity entity = EntityBuilder.create() + .setContentType(ContentType.create("application/x-www-form-urlencoded", Consts.UTF_8)) .setParameters(params).build(); httpPost.setEntity(entity); CloseableHttpClient httpClient = null; -- Gitee From 223856f8b45a7174df6ef6aea9097ed0fee59165 Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Mon, 22 Jun 2020 14:47:54 +0800 Subject: [PATCH 114/238] Update DSS with linkis version 0.9.4 and solves some compilation errors #Fixes #168 --- assembly/pom.xml | 2 +- conf/config.sh | 2 +- datachecker-appjoint/pom.xml | 2 +- docs/en_US/ch1/DataSphereStudio_Compile_Manual.md | 2 +- docs/en_US/ch2/Azkaban_LinkisJobType_Deployment_Manual.md | 2 +- ...SS\347\274\226\350\257\221\346\226\207\346\241\243.md" | 2 +- dss-appjoint-auth/pom.xml | 7 ++++++- .../dss/appjoint/auth/impl/AppJointAuthImpl.scala | 5 +++-- dss-appjoint-core/pom.xml | 8 +++++++- dss-appjoint-loader/pom.xml | 4 ++-- dss-application/pom.xml | 2 +- dss-azkaban-scheduler-appjoint/pom.xml | 2 +- dss-common/pom.xml | 2 +- dss-flow-execution-entrance/pom.xml | 2 +- dss-linkis-node-execution/pom.xml | 2 +- dss-scheduler-appjoint-core/pom.xml | 2 +- dss-server/pom.xml | 4 ++-- dss-server/src/main/assembly/distribution.xml | 3 --- eventchecker-appjoint/pom.xml | 2 +- plugins/azkaban/linkis-jobtype/pom.xml | 2 +- plugins/linkis/linkis-appjoint-entrance/pom.xml | 2 +- pom.xml | 4 ++-- qualitis-appjoint/appjoint/pom.xml | 2 +- sendemail-appjoint/sendemail-core/pom.xml | 2 +- visualis-appjoint/appjoint/pom.xml | 8 +++++++- 25 files changed, 46 insertions(+), 31 deletions(-) diff --git a/assembly/pom.xml b/assembly/pom.xml index 29934071c..8a81a449d 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 4.0.0 diff --git a/conf/config.sh b/conf/config.sh index dea8a60d7..7fc8e9e4e 100644 --- a/conf/config.sh +++ b/conf/config.sh @@ -77,4 +77,4 @@ AZKABAN_ADRESS_PORT=8081 QUALITIS_ADRESS_IP=127.0.0.1 QUALITIS_ADRESS_PORT=8090 -DSS_VERSION=0.7.0 +DSS_VERSION=0.8.0 diff --git a/datachecker-appjoint/pom.xml b/datachecker-appjoint/pom.xml index c2d804486..706f88359 100644 --- a/datachecker-appjoint/pom.xml +++ b/datachecker-appjoint/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 4.0.0 diff --git a/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md b/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md index 6a24df612..106ebcbb9 100644 --- a/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md +++ b/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md @@ -6,7 +6,7 @@ ```xml - 0.7.0 + 0.8.0 0.9.3 2.11.8 1.8 diff --git a/docs/en_US/ch2/Azkaban_LinkisJobType_Deployment_Manual.md b/docs/en_US/ch2/Azkaban_LinkisJobType_Deployment_Manual.md index d70a87eed..33cb3808c 100644 --- a/docs/en_US/ch2/Azkaban_LinkisJobType_Deployment_Manual.md +++ b/docs/en_US/ch2/Azkaban_LinkisJobType_Deployment_Manual.md @@ -2,7 +2,7 @@ ## 1. Ready work -1.Click [release](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.7.0/linkis-jobtype-0.7.0.zip) to select the corresponding installation package to download: +1.Click [release](https://github.com/WeBankFinTech/DataSphereStudio/releases/download/0.8.0/linkis-jobtype-0.8.0.zip) to select the corresponding installation package to download: - linkis-jobtype-$version.zip diff --git "a/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" "b/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" index 0b4d82f0b..8f078c512 100644 --- "a/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" @@ -6,7 +6,7 @@ ```xml - 0.7.0 + 0.8.0 0.9.3 2.11.8 1.8 diff --git a/dss-appjoint-auth/pom.xml b/dss-appjoint-auth/pom.xml index 595ad36f0..fc09399d0 100644 --- a/dss-appjoint-auth/pom.xml +++ b/dss-appjoint-auth/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 4.0.0 @@ -38,6 +38,11 @@ linkis-common ${linkis.version} + + javax.servlet + javax.servlet-api + 3.1.0 + diff --git a/dss-appjoint-auth/src/main/scala/com/webank/wedatasphere/dss/appjoint/auth/impl/AppJointAuthImpl.scala b/dss-appjoint-auth/src/main/scala/com/webank/wedatasphere/dss/appjoint/auth/impl/AppJointAuthImpl.scala index 7413baf5f..15dd7e307 100644 --- a/dss-appjoint-auth/src/main/scala/com/webank/wedatasphere/dss/appjoint/auth/impl/AppJointAuthImpl.scala +++ b/dss-appjoint-auth/src/main/scala/com/webank/wedatasphere/dss/appjoint/auth/impl/AppJointAuthImpl.scala @@ -24,8 +24,9 @@ import com.webank.wedatasphere.dss.appjoint.auth.{AppJointAuth, RedirectMsg} import com.webank.wedatasphere.linkis.common.utils.Logging import com.webank.wedatasphere.linkis.httpclient.dws.DWSHttpClient import com.webank.wedatasphere.linkis.httpclient.dws.config.DWSClientConfigBuilder -import javax.servlet.http.{Cookie, HttpServletRequest} +import javax.servlet.http.HttpServletRequest import org.apache.commons.io.IOUtils +import org.apache.http.impl.cookie.BasicClientCookie import scala.collection.JavaConversions._ @@ -68,7 +69,7 @@ class AppJointAuthImpl private() extends AppJointAuth with Logging { val index = cookie.indexOf("=") val key = cookie.substring(0, index).trim val value = cookie.substring(index + 1).trim - userInfoAction.addCookie(new Cookie(key, value)) + userInfoAction.addCookie(new BasicClientCookie(key, value)) } val redirectMsg = new RedirectMsgImpl redirectMsg.setRedirectUrl(request.getParameter(AppJointAuthImpl.REDIRECT_KEY)) diff --git a/dss-appjoint-core/pom.xml b/dss-appjoint-core/pom.xml index 0c00f2cd7..b27a98f70 100644 --- a/dss-appjoint-core/pom.xml +++ b/dss-appjoint-core/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 4.0.0 @@ -50,6 +50,12 @@ dss-common ${dss.version} + + + com.webank.wedatasphere.linkis + linkis-httpclient + ${linkis.version} + diff --git a/dss-appjoint-loader/pom.xml b/dss-appjoint-loader/pom.xml index 7dc9097f3..3134933be 100644 --- a/dss-appjoint-loader/pom.xml +++ b/dss-appjoint-loader/pom.xml @@ -22,12 +22,12 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 4.0.0 dss-appjoint-loader - 0.7.0 + 0.8.0 diff --git a/dss-application/pom.xml b/dss-application/pom.xml index 1a55a8035..2c9fdc039 100644 --- a/dss-application/pom.xml +++ b/dss-application/pom.xml @@ -23,7 +23,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 dss-application diff --git a/dss-azkaban-scheduler-appjoint/pom.xml b/dss-azkaban-scheduler-appjoint/pom.xml index a6d894534..b9110cd5a 100644 --- a/dss-azkaban-scheduler-appjoint/pom.xml +++ b/dss-azkaban-scheduler-appjoint/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 4.0.0 diff --git a/dss-common/pom.xml b/dss-common/pom.xml index bbf896bfa..778700584 100644 --- a/dss-common/pom.xml +++ b/dss-common/pom.xml @@ -23,7 +23,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 dss-common diff --git a/dss-flow-execution-entrance/pom.xml b/dss-flow-execution-entrance/pom.xml index 97d12b24b..abeccba5c 100644 --- a/dss-flow-execution-entrance/pom.xml +++ b/dss-flow-execution-entrance/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 4.0.0 diff --git a/dss-linkis-node-execution/pom.xml b/dss-linkis-node-execution/pom.xml index b98c33987..5a0993e4f 100644 --- a/dss-linkis-node-execution/pom.xml +++ b/dss-linkis-node-execution/pom.xml @@ -24,7 +24,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 dss-linkis-node-execution diff --git a/dss-scheduler-appjoint-core/pom.xml b/dss-scheduler-appjoint-core/pom.xml index b09213fc8..42a5bc856 100644 --- a/dss-scheduler-appjoint-core/pom.xml +++ b/dss-scheduler-appjoint-core/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 4.0.0 diff --git a/dss-server/pom.xml b/dss-server/pom.xml index b0627677b..55d281253 100644 --- a/dss-server/pom.xml +++ b/dss-server/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 4.0.0 @@ -145,7 +145,7 @@ com.webank.wedatasphere.dss dss-scheduler-appjoint-core - 0.7.0 + 0.8.0 diff --git a/dss-server/src/main/assembly/distribution.xml b/dss-server/src/main/assembly/distribution.xml index 560fc34e3..cba104e83 100644 --- a/dss-server/src/main/assembly/distribution.xml +++ b/dss-server/src/main/assembly/distribution.xml @@ -82,7 +82,6 @@ com.netflix.ribbon:ribbon-loadbalancer:jar com.netflix.ribbon:ribbon-transport:jar com.netflix.servo:servo-core:jar - com.ning:async-http-client:jar com.sun.jersey.contribs:jersey-apache-client4:jar com.sun.jersey:jersey-client:jar com.sun.jersey:jersey-core:jar @@ -137,8 +136,6 @@ joda-time:joda-time:jar log4j:log4j:jar mysql:mysql-connector-java:jar - net.databinder.dispatch:dispatch-core_2.11:jar - net.databinder.dispatch:dispatch-json4s-jackson_2.11:jar org.antlr:antlr-runtime:jar org.antlr:stringtemplate:jar org.apache.commons:commons-compress:jar diff --git a/eventchecker-appjoint/pom.xml b/eventchecker-appjoint/pom.xml index 8c38e4747..80243766f 100644 --- a/eventchecker-appjoint/pom.xml +++ b/eventchecker-appjoint/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 4.0.0 diff --git a/plugins/azkaban/linkis-jobtype/pom.xml b/plugins/azkaban/linkis-jobtype/pom.xml index 56225d510..54497a7f3 100644 --- a/plugins/azkaban/linkis-jobtype/pom.xml +++ b/plugins/azkaban/linkis-jobtype/pom.xml @@ -23,7 +23,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 com.webank.wedatasphere.dss linkis-jobtype diff --git a/plugins/linkis/linkis-appjoint-entrance/pom.xml b/plugins/linkis/linkis-appjoint-entrance/pom.xml index 0651c396e..6e0d82a24 100644 --- a/plugins/linkis/linkis-appjoint-entrance/pom.xml +++ b/plugins/linkis/linkis-appjoint-entrance/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 4.0.0 diff --git a/pom.xml b/pom.xml index ff14d65f7..4040e500d 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ pom com.webank.wedatasphere.dss dss - 0.7.0 + 0.8.0 dss-common @@ -47,7 +47,7 @@ - 0.7.0 + 0.8.0 0.9.4 2.11.8 1.8 diff --git a/qualitis-appjoint/appjoint/pom.xml b/qualitis-appjoint/appjoint/pom.xml index d32ad4bb8..579263865 100644 --- a/qualitis-appjoint/appjoint/pom.xml +++ b/qualitis-appjoint/appjoint/pom.xml @@ -5,7 +5,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 4.0.0 diff --git a/sendemail-appjoint/sendemail-core/pom.xml b/sendemail-appjoint/sendemail-core/pom.xml index 97c3c167d..ebff3d1ea 100644 --- a/sendemail-appjoint/sendemail-core/pom.xml +++ b/sendemail-appjoint/sendemail-core/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 4.0.0 diff --git a/visualis-appjoint/appjoint/pom.xml b/visualis-appjoint/appjoint/pom.xml index ab48a6148..afe7b4e61 100644 --- a/visualis-appjoint/appjoint/pom.xml +++ b/visualis-appjoint/appjoint/pom.xml @@ -22,7 +22,7 @@ dss com.webank.wedatasphere.dss - 0.7.0 + 0.8.0 4.0.0 @@ -52,6 +52,12 @@ provided true + + + net.databinder.dispatch + dispatch-core_2.11 + 0.12.3 + -- Gitee From 53db7a9bc4b2c92874f0d8e7f49631cc67e84d08 Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Mon, 22 Jun 2020 16:55:22 +0800 Subject: [PATCH 115/238] Update DSS with linkis version 0.9.4 and solves some compilation errors #Fixes #168 --- docs/en_US/ch1/DataSphereStudio_Compile_Manual.md | 2 +- docs/en_US/ch2/DSS Quick Installation Guide.md | 4 ++-- .../DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" | 2 +- ...\205\344\275\277\347\224\250\346\226\207\346\241\243.md" | 6 +++--- dss-linkis-node-execution/pom.xml | 4 ++-- dss-server/pom.xml | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md b/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md index 106ebcbb9..46b95c406 100644 --- a/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md +++ b/docs/en_US/ch1/DataSphereStudio_Compile_Manual.md @@ -7,7 +7,7 @@ ```xml 0.8.0 - 0.9.3 + 0.9.4 2.11.8 1.8 3.3.3 diff --git a/docs/en_US/ch2/DSS Quick Installation Guide.md b/docs/en_US/ch2/DSS Quick Installation Guide.md index f4b8cd159..a7e7a5a5f 100644 --- a/docs/en_US/ch2/DSS Quick Installation Guide.md +++ b/docs/en_US/ch2/DSS Quick Installation Guide.md @@ -17,7 +17,7 @@ DSS also implements the integration of many external systems, such as [Qualitis] DSS environment configuration can be divided into three steps, including basic software installation, backend environment configuration, and frontend environment configuration. The details are as below: ### 2.1 Frontend and backend basic software installation -Linkis standard version (above 0.9.3). How to install [Linkis](https://github.com/WeBankFinTech/Linkis/blob/master/docs/en_US/ch1/deploy.md) +Linkis standard version (above 0.9.4). How to install [Linkis](https://github.com/WeBankFinTech/Linkis/blob/master/docs/en_US/ch1/deploy.md) JDK (above 1.8.0_141). How to install [JDK](https://www.runoob.com/java/java-environment-setup.html) @@ -111,7 +111,7 @@ The environment is ready, click me to enter ****[4. Installation and use](https: ## Three Standard DSS environment configuration preparation The standard DSS environment preparation is also divided into three parts, the frontEnd-end and back-end basic software installation, back-end environment preparation, and frontEnd-end environment preparation. The details are as follows: ### 3.1 frontEnd and BackEnd basic software installation -Linkis standard version (above 0.9.3), [How to install Linkis](https://github.com/WeBankFinTech/Linkis/blob/master/docs/en_US/ch1/deploy.md) +Linkis standard version (above 0.9.4), [How to install Linkis](https://github.com/WeBankFinTech/Linkis/blob/master/docs/en_US/ch1/deploy.md) JDK (above 1.8.0_141), How to install [JDK](https://www.runoob.com/java/java-environment-setup.html) diff --git "a/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" "b/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" index 8f078c512..fe0b0b000 100644 --- "a/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch1/DSS\347\274\226\350\257\221\346\226\207\346\241\243.md" @@ -7,7 +7,7 @@ ```xml 0.8.0 - 0.9.3 + 0.9.4 2.11.8 1.8 3.3.3 diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index e775e8380..2b9035504 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -32,7 +32,7 @@ ## 二、精简版DSS环境配置准备 DSS环境配置准备分为三部分,前后端基础软件安装、后端环境配置准备和前端环配置境准备,详细介绍如下: ### 2.1 前后端基础软件安装 -Linkis精简版(0.9.3及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) +Linkis精简版(0.9.4及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) @@ -143,7 +143,7 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/ ## 三、简单版DSS环境配置准备 DSS环境配置准备分为三部分,前后端基础软件安装、后端环境配置准备和前端环配置境准备,详细介绍如下: ### 3.1 前后端基础软件安装 -Linkis简单版(0.9.3及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) +Linkis简单版(0.9.4及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) @@ -251,7 +251,7 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/ ## 四、标准版DSS环境配置准备 标准版DSS环境准备也分为三部分,前后端基础软件安装、后端环境准备和前端环境准备,详细介绍如下: ### 4.1 前后端基础软件安装 -Linkis标准版(0.9.3及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) +Linkis标准版(0.9.4及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) diff --git a/dss-linkis-node-execution/pom.xml b/dss-linkis-node-execution/pom.xml index 5a0993e4f..29fd8ae27 100644 --- a/dss-linkis-node-execution/pom.xml +++ b/dss-linkis-node-execution/pom.xml @@ -33,13 +33,13 @@ com.webank.wedatasphere.linkis linkis-ujes-client - 0.9.3 + ${linkis.version} com.webank.wedatasphere.linkis linkis-workspace-httpclient - 0.9.3 + ${linkis.version} diff --git a/dss-server/pom.xml b/dss-server/pom.xml index 55d281253..4408aa02d 100644 --- a/dss-server/pom.xml +++ b/dss-server/pom.xml @@ -117,7 +117,7 @@ com.webank.wedatasphere.linkis - 0.9.3 + ${linkis.version} -- Gitee From 8216821814933f96e8b6df2a1c457cc8a81e8507 Mon Sep 17 00:00:00 2001 From: liuyou2 <405240259@qq.com> Date: Wed, 24 Jun 2020 12:33:09 +0800 Subject: [PATCH 116/238] Update DSS with linkis version 0.9.4 and solves some compilation errors #Fixes #168 --- assembly/pom.xml | 2 +- ...stenerEventBusNodeExecutionScheduler.scala | 22 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/assembly/pom.xml b/assembly/pom.xml index 8a81a449d..2b930b76b 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -103,7 +103,7 @@ com.fasterxml.jackson.core jackson-core - 2.9.6 + 2.10.0 net.databinder.dispatch diff --git a/dss-appjoint-core/src/main/scala/com/webank/wedatasphere/dss/appjoint/execution/scheduler/ListenerEventBusNodeExecutionScheduler.scala b/dss-appjoint-core/src/main/scala/com/webank/wedatasphere/dss/appjoint/execution/scheduler/ListenerEventBusNodeExecutionScheduler.scala index a355270cc..51d167eaf 100644 --- a/dss-appjoint-core/src/main/scala/com/webank/wedatasphere/dss/appjoint/execution/scheduler/ListenerEventBusNodeExecutionScheduler.scala +++ b/dss-appjoint-core/src/main/scala/com/webank/wedatasphere/dss/appjoint/execution/scheduler/ListenerEventBusNodeExecutionScheduler.scala @@ -17,6 +17,8 @@ package com.webank.wedatasphere.dss.appjoint.execution.scheduler +import java.util.concurrent.ArrayBlockingQueue + import com.webank.wedatasphere.dss.appjoint.exception.AppJointErrorException import com.webank.wedatasphere.dss.appjoint.execution.common.{AsyncNodeExecutionResponse, CompletedNodeExecutionResponse, LongTermNodeExecutionAction} import com.webank.wedatasphere.dss.appjoint.execution.conf.NodeExecutionConfiguration._ @@ -55,7 +57,7 @@ class ListenerEventBusNodeExecutionScheduler(eventQueueCapacity: Int, name: Stri val field1 = ru.typeOf[ListenerEventBus[_, _]].decl(ru.TermName("eventQueue")).asMethod val result = listenerEventBusClass.reflectMethod(field1) result() match { - case queue: BlockingLoopArray[AsyncNodeExecutionResponseEvent] => queue + case queue: ArrayBlockingQueue[AsyncNodeExecutionResponseEvent] => queue } } @@ -104,18 +106,18 @@ class ListenerEventBusNodeExecutionScheduler(eventQueueCapacity: Int, name: Stri protected def addEvent(event: AsyncNodeExecutionResponseEvent): Unit = synchronized { listenerEventBus.post(event) - event.getResponse.getAction match { - case longTermAction: LongTermNodeExecutionAction => - longTermAction.setSchedulerId(eventQueue.max) - case _ => - } +// event.getResponse.getAction match { +// case longTermAction: LongTermNodeExecutionAction => +// longTermAction.setSchedulerId(eventQueue.max) +// case _ => +// } } - override def removeAsyncResponse(action: LongTermNodeExecutionAction): Unit = - getAsyncResponse(action).setCompleted(true) + override def removeAsyncResponse(action: LongTermNodeExecutionAction): Unit = { + + } - override def getAsyncResponse(action: LongTermNodeExecutionAction): AsyncNodeExecutionResponse = - eventQueue.get(action.getSchedulerId).getResponse + override def getAsyncResponse(action: LongTermNodeExecutionAction): AsyncNodeExecutionResponse = null override def start(): Unit = listenerEventBus.start() -- Gitee From e197816ad9ab1baeea40b3da3f1b0b3a5f740e68 Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Fri, 19 Jun 2020 14:14:16 +0800 Subject: [PATCH 117/238] New workspace, case, quick start code --- web/src/js/view/newhome/images/111.png | Bin 0 -> 22281 bytes web/src/js/view/newhome/images/333.png | Bin 0 -> 28244 bytes web/src/js/view/newhome/images/QR.jpg | Bin 0 -> 37822 bytes web/src/js/view/newhome/images/desktop.ini | 11 + web/src/js/view/newhome/images/edit1.png | Bin 0 -> 30795 bytes web/src/js/view/newhome/images/u1191.png | Bin 0 -> 461 bytes web/src/js/view/newhome/images/u1225.png | Bin 0 -> 684 bytes web/src/js/view/newhome/images/u1226.png | Bin 0 -> 581 bytes web/src/js/view/newhome/images/u1229.png | Bin 0 -> 283 bytes web/src/js/view/newhome/images/u476.png | Bin 0 -> 384 bytes web/src/js/view/newhome/images/u501.png | Bin 0 -> 687 bytes web/src/js/view/newhome/images/u504.png | Bin 0 -> 1190 bytes web/src/js/view/newhome/images/u509.png | Bin 0 -> 833 bytes web/src/js/view/newhome/images/u513.png | Bin 0 -> 1009 bytes web/src/js/view/newhome/images/u517.png | Bin 0 -> 433 bytes web/src/js/view/newhome/images/u619.png | Bin 0 -> 1103 bytes web/src/js/view/newhome/images/u620.png | Bin 0 -> 1226 bytes web/src/js/view/newhome/images/u621.png | Bin 0 -> 415 bytes web/src/js/view/newhome/images/u82.svg | 1 + web/src/js/view/newhome/index.vue | 3 + .../module/caseAndIntroduction/index.js | 10 + .../module/caseAndIntroduction/index.vue | 227 ++++++++++++++++++ .../js/view/newhome/module/workspace/index.js | 10 + .../view/newhome/module/workspace/index.scss | 147 ++++++++++++ .../view/newhome/module/workspace/index.vue | 157 ++++++++++++ .../module/workspace/module/workspaceForm.vue | 168 +++++++++++++ web/src/js/view/newhome/tips.md | 12 + 27 files changed, 746 insertions(+) create mode 100644 web/src/js/view/newhome/images/111.png create mode 100644 web/src/js/view/newhome/images/333.png create mode 100644 web/src/js/view/newhome/images/QR.jpg create mode 100644 web/src/js/view/newhome/images/desktop.ini create mode 100644 web/src/js/view/newhome/images/edit1.png create mode 100644 web/src/js/view/newhome/images/u1191.png create mode 100644 web/src/js/view/newhome/images/u1225.png create mode 100644 web/src/js/view/newhome/images/u1226.png create mode 100644 web/src/js/view/newhome/images/u1229.png create mode 100644 web/src/js/view/newhome/images/u476.png create mode 100644 web/src/js/view/newhome/images/u501.png create mode 100644 web/src/js/view/newhome/images/u504.png create mode 100644 web/src/js/view/newhome/images/u509.png create mode 100644 web/src/js/view/newhome/images/u513.png create mode 100644 web/src/js/view/newhome/images/u517.png create mode 100644 web/src/js/view/newhome/images/u619.png create mode 100644 web/src/js/view/newhome/images/u620.png create mode 100644 web/src/js/view/newhome/images/u621.png create mode 100644 web/src/js/view/newhome/images/u82.svg create mode 100644 web/src/js/view/newhome/index.vue create mode 100644 web/src/js/view/newhome/module/caseAndIntroduction/index.js create mode 100644 web/src/js/view/newhome/module/caseAndIntroduction/index.vue create mode 100644 web/src/js/view/newhome/module/workspace/index.js create mode 100644 web/src/js/view/newhome/module/workspace/index.scss create mode 100644 web/src/js/view/newhome/module/workspace/index.vue create mode 100644 web/src/js/view/newhome/module/workspace/module/workspaceForm.vue create mode 100644 web/src/js/view/newhome/tips.md diff --git a/web/src/js/view/newhome/images/111.png b/web/src/js/view/newhome/images/111.png new file mode 100644 index 0000000000000000000000000000000000000000..0d0dc410e3b1143178f08e9125bdaeb787753ea3 GIT binary patch literal 22281 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 literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/333.png b/web/src/js/view/newhome/images/333.png new file mode 100644 index 0000000000000000000000000000000000000000..5f696746e0434b59b66ac3d198893bcf1c5ca473 GIT binary patch literal 28244 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 U@n-Pf;`q!C95H@j=p6ii0Eh`!cK`qY literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/QR.jpg b/web/src/js/view/newhome/images/QR.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f85da5edab90395d797154fde95c82226ac9747d GIT binary patch literal 37822 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 TG+_u)00000NkvXXu0mjfdj0cY literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/u1229.png b/web/src/js/view/newhome/images/u1229.png new file mode 100644 index 0000000000000000000000000000000000000000..11052cd14c1a0401a56c366ea39a6f12703bae21 GIT binary patch literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^MnKHN!3HE1{NLpODaPU;cPEB*=VV?2IV|apzK#qG z8~eHcB(eheoCO|{#S9F5he4R}c>anMpx_2i7sn6}@8lGTo&}AGrW39t{5WqQ?r}aL zBjpF9*l}jI)$Z?@Jy|*0AF^I>p6ejBzJ11mF9~cy2Ohj*fApK@D-Wx~8AefeM(2ad z1`XGpdk$pS@GkLHxTDA#FiGZw@_)rg&SDKVSFEN?64PVwO0rSt-@{nkF870>r_)U# zjAfFn^THpl>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0ToF^K~yMHm6APA z0znXlX9i;|_yO2k(EHWc@Ef$TAeyKYBqmZ)8F~^ahy|3E*jrFsA&rW$vGWhmYof`K zeVrXw%yL|UPc@4M+WLX)Y}XF=6Ji6&UTM^7`A$09M%6yIDeVpssb)gIkNXc)PoLqp%(6>Z+kn!;D7V;uYNGQmpv zg~1}Rw<8@N^4XKSkKRI6fPlD`|6c-X4&^e2zW{3L#WN<$4t eDpvDEBBF2OS$&L9INbyQ0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0z^qfK~z{r#g-vY z98na7cP0n~V#NwX1tcUztRU$otRMl?qym9JP=_dvx{7)v5>ZjnAJ94k0+I@v06|a` zB;5poC<%g1K#$bJ5uZ7= zjJ{Al5hm1$->%hv$bCnmuMMh)PK`e>{zxo5I9DaFD}DsIYh+Gy?)kR^;lvEF#V%sR zQjg%A7K3kuUNh}F^s4+J>YURG^^#a5KZ?d+j^@4%!%#h(G07p~grW%@4+=cmc#IS6 zXaOOyG-y+SM-{KtXsjRpgCmkfd=&bE@kMmim`*VGW%;srty|r2<5FqJxQGwF7u@b? z87F?M2S{DU{>xi_sxmHS=kEazb4|w2f{bt7usnFUZe`qZho#bz@qrtc%6`CQ4-;qn z;XS`9MWfrSB{Sql|M3cm#656P;Gs|Bdps{(23WJT3D_hu?<|v`=QXj-&^7~=%3mtx Vga(ro=XwAD002ovPDHLkV1k@bF=YS% literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/u504.png b/web/src/js/view/newhome/images/u504.png new file mode 100644 index 0000000000000000000000000000000000000000..59fd43ac276892b0a3870a09e67bd15e6404c7a5 GIT binary patch literal 1190 zcmV;X1X=ruP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1UpGYK~!i%?U-9^ z6jd0<=epgpS`u1lDA)=Ji6Egw5-}l0!AR6#hyfy`1PB;4kU;Rw2OoSep^*fhl;9i2 zs7;I{VuaEvu_PFvt(X!}Zqib0YZ036?%d8C|FiprOykaFXQtYR{biG#|Cuwp|2dcM zeCLRqb786?(f5?3VlFBbb5WVn<`N4f_UNzX^)^vbltnF4&3r12M*`+x%jjw4#)DMz zyMibiy$7Yt9Ch(dsct#dh)Q&GJUeI&bXaJu)O2;pTk`BxbVCr>-7d552<$44uag_s zN{=+sjWQ|69MkQw8_s9sqIKttn5t2lUQwD}6*CP~VIubUZ8p%s`cH9fRBm`)n)x)k zTdJ8SND9>mBETHp-n@L2-95{5gMysKPdk55+bqvrBdQsy6bRGV&^h$JJ$4h0F)mRC zuj=AA(dxx2rGYsgvfr#WZ+&a$hDaxeHTYA$y@iAaexZa7Uy$opIvrO%i;9xN8KY{3 z=Z8s`!Z*$_4Fij=Cjn7ZIMYa!qOw9nB{6dtJ=Py5tQ%h=)=*Jwk}zjm#)S{EUp%Fq z-m3kuE7!I{JM%U-vvfBG37Es$W&Cmo7D)?&b?qzt$6X|15Z4@{zj5gh2^ZGwlL)*d zq7v7fgApb;&yOl8AwyIiw8S7$f0}HPA^{1=#R;q%$OZ5f#7G#@F1mdY&I5;SFLh z@-`9$5Ri@TRubNDeH3j>q7=U7s%QCU4M@(6?gLuq4$>~nzK^x`&GuhCUUM06?^{Iz z#+;a*fmD&iM9kkm&wbf!^c?W|dxW~&@iltaKGGAxYX|Ow0?Z-lWqA8ZfQ|G>6Q|L? z2}skiid(;ZmRj*XX%|>MF=$A5gCSpXVCh|Z@w5J8E_j2JKe@4bZ5s&}=oc*WB)mz# z@M(!en(25p{o*l_9t3nNkn5IXZ$cs=teeN>$6g}gLt!W32X;64&YdI@BKQ3UZfPXE z32r%biu7n>{1oFMNT`&#s|C4=v=3y`7hAs{xQz=7Geb5T2yQumbxdw}4sn%q42<4` z>cY*Tnk~$PD1zO&{r8oaor|!{^?St`skq%9i^EoVB#?S9b_0Oma zw@{HcM(;;_yua$%){v9HP1p(HMpQFZs}A$*Aoiy|TWH+UI=73}^{5=d8Hmzy4{;7$ zyFV1GYSrfb?)=9ozjW9+@m#t)&iQaGb43te%)U=>p)T6WndThCPMecjwm1I4Spw#Y zpqI_7$IyN1lRE;=D?^i*xyc~Pg!s>>n2SoqTr>pXAL#-fg>$5C-T(jq07*qoM6N<$ Eg3LZKEC2ui literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/u509.png b/web/src/js/view/newhome/images/u509.png new file mode 100644 index 0000000000000000000000000000000000000000..986e39719427393967ecf944b43164db875a9042 GIT binary patch literal 833 zcmV-H1HSx;P)500001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0@g`HK~z{ry_YX+ z6hRb+?=BT5Dk=~a2uMyKAVDHdAP^Om6%`dtAfWYI+Nt+-_4!*bZ>(cJd-0YCs`;wP8e|~S?yWQEn*~b4e91hq2cwqdQ zB$I=rN6PPGTCyZs@<~ugr`c=<6H?3-HIoPyV+)dW2kU7lhe9r?8KNVf!#YdY>*PWS z=n{B<&#m&&~Of8wtiPB{UGXKhc2XE$n(SUDRoA1&-B?3GiuigdF-}7c0EV2m{;&0QwW9%blaaDPwJaMS}35$=! zE;DvjAsO`TY22112%7f_@q=a-(Hypl#oi;OxAIw#EIVZw)>y$^$Jz?Ze$5tE`Q3sx zzVX1;RY(-H``BjFI*P9Z@@uVD>yx@c(Afq(biHaM{cDrpxJn_0ZBX=;w5KE$17GB; zlB7>9rgSujkfcxEGjN$(@J;O?EZfG8&`xP6N{fJ}*l+ctpna(3NYJgP6oUTWEu~{8 zyLqffdn9NU6y^oVEi@-i?Z+Nv>>kaVSblITfhhWCiKdS`cMhiCW_$yS6*5pr9K?%? zi-L9+vs2vw8(G9D=vI{~4&oPzs|D8I!^IDA2-jRly^v=|Dg7X@Kgvp%dK}mfSL%%7 zOYe5d<2VNH%9o*7d%W}SrMe;4l2ZFY6Z&qlvHSQ+n;YE+tcQ7j9OKoVD73{d%3WOk zS!xTp89&T#NNQ`@q3x}k$>wZNE^E3P1lTS6jM)*i_;TxFL5NwAG=rfj#`>5YqUJR` z9$0)f%Nl@$bCOO55(bZ|%w3c$iPZDVS>DN?gIZp48vL$q0*%IB^zX7KjaOb000000 LNkvXXu0mjfjuv?x literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/u513.png b/web/src/js/view/newhome/images/u513.png new file mode 100644 index 0000000000000000000000000000000000000000..97905ddd3b40ad5b200571701bf1cd47412692be GIT binary patch literal 1009 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1BOXNK~z{ry_i2p z)ln43eJ=+GA&DRdA%`F-2Zx4+HwXziIM^6CI5@Nj4Gl&PZ4C|%jkY&5XcQD=ROGHw zkfD&FP|+KT0tG|+eD1ry*L%J9#6R!%`@;8~bMHO(ocsITd+xpOmuuMvySux+h^|~N z*NN=j+uJ*XR8J_rCdBR=aveK$xun5?K&Jr$-iM#ij|F^ez!^9g-PZ!UVGI^aU7C;R zdpL$Gfy(JpbNV3GBSh;7ekPcU$vB48L97eJJe6Yvs}#<~`b{WLy-zk+2G zfUhn147ERo2{4a`^7;JJSPsCb4N*W|MS4*5@p_U&VPDXvhPB?|lh=qXoN?yP*il?LPv4O94 ze2&0bV}xL!?#@M(qhEl&u8&Ga>C^l`ZwUHzKo?IRJP&E2Y)3x z>p5=(d=&kefSH1aoem>ViFK)iSm8Vlfdz$3Zy+_7JsJm~`8&wGxj2pt{Ft8e@G+@s z%9i2ca-SZDE3vK&I+}NvP+h4PVK+3NWhKmG^Vgf@GE!e=!aA}F`17`UPsP`;1HDaB!3zGwwrD+a zld?8m_}xa`?M_0cCD3|gT^M*4gX;Tk%3zR72EL5$0&6c-rwf8^6YF|X=wSe>$W#$y z6hhDhR5(wgG``cQnZV}<#3(G!xu=tdeAT}?3{9&ccm=vpJOmCj75Fo!Jw(>%^9DJG ztlA^=?;P)-KcMk8Y-2V2x1SFuZZ^k{|t=4UJh`u#fXJ7S3y@vmR zGw00#NjH|TfdKpZhTK3p4(My!iJn5q6vTXJboW#b=S)B>_w7=KpcvfEygd2MhQ5t~ zT6->7N#hvw-$eN;dQ|8GdS$*ru_|E0&rKS_0o3rh3H>a3@|nqePA>H2&rOp0&(Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0Y*tgK~z{r?UkWU z1TheXx2w*QAUFkr1OyU+L?U?v9sojjDH z$b`u}(Hv^pa7fY;HQLZN38lT!+bHH{u;7Je7`hNV$}a+b%MoZuF^f`GMZ#59gP3nh~Z!Ax?ams zx`|u@2jX=XMqukEPi1B-pM%@4Xc6+S(1nI^q_ipI6QNy`{J$fp7`Z7%ZiPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1LR3WK~z{ry_u~~ z96=a|xyuOz0)aq~Z~}p>KwMG;q5{DmfS|4dfkYrGnjnw}L`9n*sHsAYQXaWfh^!d%a$Fa=p-0t4Tle{;(@7L_j&dkls)kZ3EdwbhNTD4kD?7AMAc6cWJPnSE783=#T4{&NSqte3{!_>nl5Ab< z>lP9R2MvhaB-k{HADMe;h;5Q1cfes&OV68o77Ut7Qo$c6#?8Gl>Rk( zY9x=sQ%M_(bC@a#ZkjVMeMG=QosX9JWwIV>9Kg5Iig+kc*AE)%uif5fMh_UgVmTA^%Wj8-wh0e$ zEja40GyJnM3ZqUdnCQqemnsBx(nt+GVDKt2j8j+Y*W)ohu`kvOu{U`deL#UR+Bc0W zE0d6;(7r={Y81P@&q<9}^&I1-DefTXX}w;L&QI91+F0~=aqzh!?|UTH`7_|FCDwtz z>wx~X`qK&*0qBdZaQgstZCkY&)OdQzS$~@aqc${CmSbR0mDY#RMKXH-mbf@DT?X`9 z&S8L1$EsDA0lk)aev{9QcKiY8lZ(z?A-5I^d4~ZT=H?u=c+^rm0KK*W{hm@Bx4BBkx zZnCi*B9%urDb(kpueA;KWpj^%Lv&QN!LHLOEz`?vq%@VRB6$PCfqmOT(%`7Gk|g+C zBHB7WL4tiOx(Q@nl_FiwYw*zyuUHqtQJZ+Tzby*>>O05C5mM>^34c9YxLNN8fjYG8 zdhpW=;-bF#nS_#DCC^wlAU`tBZ*TFzC2{OX%)$g!`k zIK*fKZy=@4rfXJ~hKd#_ba1I%p??-bUNGq8$zZ2iqPK>+Gi)X5+Nfa{{gT$ Vp7osyv<3hG002ovPDHLkV1j#G23r6C literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/u620.png b/web/src/js/view/newhome/images/u620.png new file mode 100644 index 0000000000000000000000000000000000000000..05c87dec578e8d99c342cf438d99f7b33e18058d GIT binary patch literal 1226 zcmV;*1U37KP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1Yb!+K~!i%-I*^; z98nO);etRQ5C{ZgA`qCSBozpnASx;l6*Os^3eq4d zDiAb5K!T`1LenNRp$SdercG#|zwhnr-rnBs-tOJrLHZ>hH*em&*_plfXWr4(E?iz- z4qjYbJcbAGBV2_e)_wg!u;cJ0JSUktpx=VG&HQ?S_<9L$79M!vHU_qbZ~?L3+*}<9 zVwhl7;Hir)1a#-{4Pph3A+N*Vt}_I5Kj2fuo94E2;K60M3G1d0x)Z3iF=XZe=pKMe z^c^|l2++UhW75pq3m!HN;}Y0|Gl;!rnh0!q;FJYk1NnvvX4*dRkk9r^|Djsg5nEoY_~?b2a^Y`!!n%uxoO{oxLT?Z1jgFdGW-wfv zh0d2V&sz;Tn@AW0q&YtYdu&K7=%2(kcC!fK>JsrmfZCOo;D8O)*go|0@K82Upm!C3 zHHE8B#0P%!%+uRaT5yvvA;B>t)z$ zIgF!gSngy7&iYw|i!ip(%YkKcSp)p){;~n%D&yEqAs28^R|B<(AQ5EUUuNK**Odc|=wnL{ z+JjKVUQiJyK{hb1{6B>&h~f3&fG)9=LFZ39uX>;{0_(Czm-*&~O%Jwr;f@=e0obY} znMG{4ps^c*NjFiwpt6iMOy@vbcjqh@W<-q!XT z{YB&0_|vuWL#Op8_}#T?A)S1Gajl%NgVe=G{C}O&Lq%D}f-H~VB4Va*23y_ZGi?Ca z1Pj}Srvf|ea&s_t0}v7u@u9%rI%3^nh)xgC9e&ptN1(ALCITD%csGYwceO>Y^_x~X z2b(~{M8aU;4piV;d=0lzs4X`W7;^>{w1U3_x2&rM=z~L&&tR9$l}H+Jsz7vy54KU{ z%!xDtzIWj?VsHc$nh4Gkw^4L0C4yf~YpuJoxvT;D))O%&soN<1O(%l?H9k^ntZ*W& zl<~)GhaXHX9Qb|t8r|o&$nt2fX z9E9u=@YGeHQ{|u+SG``)NDL+p7F=oqd<1U|dBVnIg?>XzOaP{D&va%=h<;s&8YU10 zeVGz6KQ%ztIDsfI&if6eCJ+U-nZKc?5{QDqsR`vxAPUANCR9iQQQ*u^NcR*~xVqLh ooj?@$QbO;bf>(u`BZ022f9^L#hPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0W?WOK~z{r?U%7? z0znXl_rxNFjc|p9g}n)+wDbWiEG%sE4npu9gx~`N;v3j$X<=buZ>dEdAfUxT;MQ;4 zK`n$33^<1UV3~jCmb+nwo#7G>&M*bFW-${Wg|6TC%q%{i!!qhldkysFkhQMHlcFcV z>%FO4Oeh;ng$zCf&mFXx$iF9!x@$2LAcf3WA1wL(JRv0(ZanI~F*Q9dqwXy{u`}vs zG-qkj2hbyxW=i}_vX0XO-B4-jw{uM9hS*28ujs1yW1G1S=k|&Txr!Cv|9t=e002ov JPDHLkV1jk)u)_cV literal 0 HcmV?d00001 diff --git a/web/src/js/view/newhome/images/u82.svg b/web/src/js/view/newhome/images/u82.svg new file mode 100644 index 000000000..e67551d38 --- /dev/null +++ b/web/src/js/view/newhome/images/u82.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/js/view/newhome/index.vue b/web/src/js/view/newhome/index.vue new file mode 100644 index 000000000..09d9d0d42 --- /dev/null +++ b/web/src/js/view/newhome/index.vue @@ -0,0 +1,3 @@ + diff --git a/web/src/js/view/newhome/module/caseAndIntroduction/index.js b/web/src/js/view/newhome/module/caseAndIntroduction/index.js new file mode 100644 index 000000000..9ea52ad7e --- /dev/null +++ b/web/src/js/view/newhome/module/caseAndIntroduction/index.js @@ -0,0 +1,10 @@ +export default { + name: 'CaseAndIntroduction', + events: [], + dispatchs: { + }, + data: { + API_PATH: process.env.VUE_APP_MN_CONFIG_PREFIX || `http://${window.location.host}/api/rest_j/v1/`, + }, + component: () => import('./index.vue'), +}; \ No newline at end of file diff --git a/web/src/js/view/newhome/module/caseAndIntroduction/index.vue b/web/src/js/view/newhome/module/caseAndIntroduction/index.vue new file mode 100644 index 000000000..6a84b0813 --- /dev/null +++ b/web/src/js/view/newhome/module/caseAndIntroduction/index.vue @@ -0,0 +1,227 @@ + + + + diff --git a/web/src/js/view/newhome/module/workspace/index.js b/web/src/js/view/newhome/module/workspace/index.js new file mode 100644 index 000000000..01be3f453 --- /dev/null +++ b/web/src/js/view/newhome/module/workspace/index.js @@ -0,0 +1,10 @@ +export default { + name: 'Workspace', + events: [], + dispatchs: { + }, + data: { + API_PATH: process.env.VUE_APP_MN_CONFIG_PREFIX || `http://${window.location.host}/api/rest_j/v1/`, + }, + component: () => import('./index.vue'), +}; \ No newline at end of file diff --git a/web/src/js/view/newhome/module/workspace/index.scss b/web/src/js/view/newhome/module/workspace/index.scss new file mode 100644 index 000000000..9987fbef0 --- /dev/null +++ b/web/src/js/view/newhome/module/workspace/index.scss @@ -0,0 +1,147 @@ +@import '../../../assets/styles/variables.scss'; + +.page-bgc { + background-color: #f7f7f7; + background: #fff; + + .page-bgc-header { + padding: 10px 25px 0; + } + + .header-info { + padding: 10px 0 10px 20px; + + p { + line-height: 24px; + } + } + + .workspace-main { + padding: 10px 25px; + display: flex; + justify-content: flex-start; + align-items: flex-start; + + .left { + flex: 1; + box-shadow: 0 1px 6px rgba(0, 0, 0, .2); + border-color: #eee; + min-height: 500px; + + .workspace-type-header { + padding: 10px 20px 0; + line-height: 30px; + display: flex; + justify-content: flex-start; + align-items: center; + + .workspace-type-header-label { + font-size: 14px; + display: inline-block; + margin: 0 5px; + font-weight: 900; + } + } + + .workspace-create-search { + padding: 0 35px; + display: flex; + justify-content: flex-start; + align-items: center; + margin: 10px 0 50px 0; + + .workspace-create { + flex-basis: 200px; + display: flex; + justify-content: flex-start; + align-items: center; + padding: 15px 10px; + &:hover { + box-shadow: 0 2px 12px 0 rgba(0,0,0,.2); + border-radius: 4px; + } + .workspace-create-text { + margin-left: 10px; + cursor: pointer; + } + } + + .header-search { + flex: 50%; + } + } + + .item-header { + font-size: 14px; + margin: 20px 25px 10px 25px; + font-weight: bold; + padding-left: 5px; + border-left: 3px solid $primary-color; + } + + .workspace-content { + .content-item { + .workspace-item { + cursor: pointer; + height: 180px; + margin: 15px; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.2); + background: #fff; + padding: 10px; + position: relative; + background: url("../../../assets/images/workspace.png") center center no-repeat; + background-size: cover; + min-width: 222px; + .name { + display: block; + font-size: 16px; + font-weight: 600; + color: white; + } + + .desc { + width: 100%; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + text-overflow: ellipsis; + word-break: break-all; + color: white; + } + + .lable-list { + position: absolute; + left: 10px; + bottom: 30px; + display: flex; + justify-content: flex-start; + align-items: flex-start; + width: 100%; + .item { + display: inline-block; + font-size: 10px; + padding: .3em .9em; + margin: 0 .5em .5em 0; + white-space: nowrap; + background-color: #f1f8ff; + border-radius: 3px; + color: #0366d6; + overflow: hidden; + text-overflow: ellipsis; + max-width: 31%; + } + } + + .editor { + position: absolute; + right: 10px; + bottom: 10px; + } + } + } + } + } + } + +} diff --git a/web/src/js/view/newhome/module/workspace/index.vue b/web/src/js/view/newhome/module/workspace/index.vue new file mode 100644 index 000000000..953c1f68a --- /dev/null +++ b/web/src/js/view/newhome/module/workspace/index.vue @@ -0,0 +1,157 @@ + + + diff --git a/web/src/js/view/newhome/module/workspace/module/workspaceForm.vue b/web/src/js/view/newhome/module/workspace/module/workspaceForm.vue new file mode 100644 index 000000000..e297a552a --- /dev/null +++ b/web/src/js/view/newhome/module/workspace/module/workspaceForm.vue @@ -0,0 +1,168 @@ + + diff --git a/web/src/js/view/newhome/tips.md b/web/src/js/view/newhome/tips.md new file mode 100644 index 000000000..99a8d9821 --- /dev/null +++ b/web/src/js/view/newhome/tips.md @@ -0,0 +1,12 @@ +#### 开发注意 + +1. 自定义首页就在idnex.vue文件下开发,需要的工作空间和案例、快速入门在./module下,需要自行调试哦!!! + +2. 新增其他页面在view下面新建文件夹,页面对应的路由在:src\js\service\router.js下自行配置 + +3. 开发过程中可以使用:src\js\component下的公共组件,尽量不要修改,造成不通用,也可以新增组件 + +4. 目前开源的还没工作空间概念,所以对应的接口服务还没有,需要后台上传对应服务代码 + +5. 开发过程有问题随时联系 ![扫码加入](images/QR.png) + -- Gitee From af739cdd297c3b856a09700751a12b2b014e93e0 Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Mon, 22 Jun 2020 11:27:28 +0800 Subject: [PATCH 118/238] delete workspace --- web/src/js/view/newhome/images/111.png | Bin 22281 -> 0 bytes web/src/js/view/newhome/images/333.png | Bin 28244 -> 0 bytes web/src/js/view/newhome/images/QR.jpg | Bin 37822 -> 0 bytes web/src/js/view/newhome/images/desktop.ini | 11 - web/src/js/view/newhome/images/edit1.png | Bin 30795 -> 0 bytes web/src/js/view/newhome/images/u1191.png | Bin 461 -> 0 bytes web/src/js/view/newhome/images/u1225.png | Bin 684 -> 0 bytes web/src/js/view/newhome/images/u1226.png | Bin 581 -> 0 bytes web/src/js/view/newhome/images/u1229.png | Bin 283 -> 0 bytes web/src/js/view/newhome/images/u476.png | Bin 384 -> 0 bytes web/src/js/view/newhome/images/u501.png | Bin 687 -> 0 bytes web/src/js/view/newhome/images/u504.png | Bin 1190 -> 0 bytes web/src/js/view/newhome/images/u509.png | Bin 833 -> 0 bytes web/src/js/view/newhome/images/u513.png | Bin 1009 -> 0 bytes web/src/js/view/newhome/images/u517.png | Bin 433 -> 0 bytes web/src/js/view/newhome/images/u619.png | Bin 1103 -> 0 bytes web/src/js/view/newhome/images/u620.png | Bin 1226 -> 0 bytes web/src/js/view/newhome/images/u621.png | Bin 415 -> 0 bytes web/src/js/view/newhome/images/u82.svg | 1 - web/src/js/view/newhome/index.vue | 3 - .../module/caseAndIntroduction/index.js | 10 - .../module/caseAndIntroduction/index.vue | 227 ------------------ .../js/view/newhome/module/workspace/index.js | 10 - .../view/newhome/module/workspace/index.scss | 147 ------------ .../view/newhome/module/workspace/index.vue | 157 ------------ .../module/workspace/module/workspaceForm.vue | 168 ------------- web/src/js/view/newhome/tips.md | 12 - 27 files changed, 746 deletions(-) delete mode 100644 web/src/js/view/newhome/images/111.png delete mode 100644 web/src/js/view/newhome/images/333.png delete mode 100644 web/src/js/view/newhome/images/QR.jpg delete mode 100644 web/src/js/view/newhome/images/desktop.ini delete mode 100644 web/src/js/view/newhome/images/edit1.png delete mode 100644 web/src/js/view/newhome/images/u1191.png delete mode 100644 web/src/js/view/newhome/images/u1225.png delete mode 100644 web/src/js/view/newhome/images/u1226.png delete mode 100644 web/src/js/view/newhome/images/u1229.png delete mode 100644 web/src/js/view/newhome/images/u476.png delete mode 100644 web/src/js/view/newhome/images/u501.png delete mode 100644 web/src/js/view/newhome/images/u504.png delete mode 100644 web/src/js/view/newhome/images/u509.png delete mode 100644 web/src/js/view/newhome/images/u513.png delete mode 100644 web/src/js/view/newhome/images/u517.png delete mode 100644 web/src/js/view/newhome/images/u619.png delete mode 100644 web/src/js/view/newhome/images/u620.png delete mode 100644 web/src/js/view/newhome/images/u621.png delete mode 100644 web/src/js/view/newhome/images/u82.svg delete mode 100644 web/src/js/view/newhome/index.vue delete mode 100644 web/src/js/view/newhome/module/caseAndIntroduction/index.js delete mode 100644 web/src/js/view/newhome/module/caseAndIntroduction/index.vue delete mode 100644 web/src/js/view/newhome/module/workspace/index.js delete mode 100644 web/src/js/view/newhome/module/workspace/index.scss delete mode 100644 web/src/js/view/newhome/module/workspace/index.vue delete mode 100644 web/src/js/view/newhome/module/workspace/module/workspaceForm.vue delete mode 100644 web/src/js/view/newhome/tips.md diff --git a/web/src/js/view/newhome/images/111.png b/web/src/js/view/newhome/images/111.png deleted file mode 100644 index 0d0dc410e3b1143178f08e9125bdaeb787753ea3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22281 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 diff --git a/web/src/js/view/newhome/images/333.png b/web/src/js/view/newhome/images/333.png deleted file mode 100644 index 5f696746e0434b59b66ac3d198893bcf1c5ca473..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28244 zcmaHTc|4Tw_xGSkib|3!qf|m=OJp0BrA?AO%UF_R8IomeLlW8dr7)ooGL|9?gY0Ye zEyglqUuPJGS)O}*zRU0TdOgqc&zKkYeJ$sl>wV67pL6-}%%CHzz>h7jfjtn&ng71}ZGEq?m2|k5nE|;4vtB71|9!uq*4X2Vc3-gI*cT^b zaZ`!Y`cJ0WvV`-F^nJ1X@aMGpp_A&Tbz{2DjFu$)dGxuk@0!zSFLS8}G`{oo`u@I1 zyv(DVbfx`^NC0XcgJn5vg4$|VF+d8Hy7~HU#*()hDlCtkXbE@cAuZ0 z`alSdi`4=?c&ifsi;VOSQ6{vCL<1iZjv1m&;4>h@l~$Gj?f*Qj+7mw$ z?K4C564&Dc2C!K35{Xi^DehUqJRIqJI(yb8?TMOiRsC3Le=e$qG%Pg>%uy2}+V=O* zS+XlM4a}9(dlr~Mk^>z(7>}77QPj1Hdi(NH0L!5(;S<-HUxR!vzU9gH>N;yL6uOPt zqtc{^w}s#;(a8fKVZyA2tG{xLrVX${^fAJFBb|w+mkZTT$ef??&|4$D+YWm?zR5j` zOhP;&2-775PGc@enc&TeieG#MdZMT21UlV9-X!TeTMGj_l~8#E(BK=RWl@1=2eGJebAm2FEKbe0jQ71f2FNX$X>ubwhx3%q zg5pWD;u;@s8DaWDk2MN!cB^%4OPsOdiKt;XOXg((kUG_CYnGKWVCcponiF@QYm zH#8$Y$!L7`1dZ7HbRO%##OG>mp=@iv_dgt%{Ab#!`vdpimi=Z@dp;Z28vUvDh&q$w z{cLH!nTY3%&0qAgX*OFpp76a&BOu(YRk5ECol~=XrM8k1++rk!!NnT=L3i^Xkt4J) zO*IOF)F)j2kPEHmkG!kD9F0~cXd3DWS&n<1ew$BeNASbq!_sQe$;O51V zDGnS;-fe0UL4dKq6A)bkwA(G-XTrjm;}G*LqT=+tyo}e(#D_xg!%Y&Sz5FaT>*va4 zC=1N-42ckO9;d%L9F%zrq?seOtPQdVnb8jQ&w6!}IUuwjEM9$g!yOdDypY^r*-#Lr zs!SOX(?S_<+~Z)32cJ*WbXBDDNBP6*%6&i=I5<*L9B8*$KPeLk9TH$AGV2ll*er^v z0glPl1$(>N%OXw1hs25HRdrv|Urz72Yh$&clJ__=?e<04_~O2KVwBm4f{)0-(D?I9 zA2EXKUvFpReM2--yz)^J&l%=>7aiuR*L>GS<0ygaHtr_!9sijObtSUQdY5BzV_yvu+A?6WXr)R zu#}hz1(wP$Iog?l*mpSr$JeS12}rGoD6J zsAenJjU~Mu*(m!D-kmS2_wAVGkCU9xAq=Z)nB_azarkhH3F6f$0-Nyg+yk0mGK&xb z9OE#t0zLbhlcB-jwuknhI?H%1i!-@+_3qb_2&!+{BI04u`1t0hJ@^du_pg)OIui$$ z42;PN;NQ^@dEZ@q@adMycnGLT&l`^4D|LK_jG2-4K;w9565C-%|iUFqy~m z3n*OJ8}nwa%%2_EnJcLIv*Gu)NdBZd+~#xrp@TCO4xm>60NtYe;(N6^tayEzsy3lcsK|X7Ce5oA%yjp zovJ)7U}!TXPRru<#>G;S&J2^nR$H{m#2zh{E`)fT}$zS}EG;8mXbPxsJIVicU3 z_8Ch~Mv%1(soK8m!mm`UeltWuf-_I_CsLTsYC$?ZeXg~TTPMT=GgJ;VTuo8wRgSlu zwPu{7*X{f`OmV6u*vr?S)1CDondIdP$g5V2nKQ`^I9aQ zQkpd}6ZlhVXoo}2Mm*LGBN0J+cn%LRF?n=(`q=DPRkMJ!##0!kcnfur6E@yywQ?+g z$8PrK!E%4=wR%?^)7q-@t&sNydu&N(@gF=ZCOO&fGreGd&>rBOX~U#5bnhR{~_oo+Z-GD73$9Q$3GCUba?u~s)%Xo zI~z@$AV-Gz6IzJnV<^y(U$KZouRE(OF*dI!CJ7~a&9|Qt9Yr2^N zZr5pvlD^lTSup-7)k|aFSPz^muVC1XgmT91Ffc<2rN7;- zuKxzztd2*BTA;3iJ;y4_Y7l~$Ort8Hv@2`Y|6qXFanON~gkZr4(isrKRg&&xIw5QQ z7x!&+48vLech>*Kogr`2^!9LQWwNCoAZeGWZMAk zL#RIBTFnF4L{LXP?K#je-4-yx`s^wbD~~vLXE~B>4dz)Fva?IEO(bI z`_1bIK#f7SfDtmd32P*KE63rh^zRqEUvFuLFpP{Rf#O%9Tox1=&QPbsvB`#DogaJU z?{(fS$sWE!caQowYx)svdVm?X3D$m5&6oaS&*w#-1CmB%-aB=eUrUcX~;Um#<*^YrN z(kS1*_9B+JTOg%vRTI19+&>*!5$TRBDa|w>I4Sb_s+-nLf1k}uANOGYoRc#a_K~oj z#&<-95g4TyNv|bX9bJ|K-4&x3ZVKoMROt1xLiWMHesJey@L2c|IMkdxJk@a!KpeP% zMs!frt)Hl{`TOmVW##O*xA=qn#7F5sTp?z`OBPvr1o4=)L`U)glH3>9`7*hCm3Ts* zE3?q8f&c8g?dWS(SP%(9Xmx9Hz-IJlr^(W#@H#?pAQW%@Nx4i|GHX}VQa(&_aC@+( z8*GID&h9Ef0OX`J^KaPryV+ilV+I;T>JC-Ti%B^fyqwxz>A}TTm|HaD?x-8+0uJa~ zD6;-CYB+;zq*HW?t%rHz=@5DLTdPizJmj^+zAUi29=93+DMqv>h@2kGU9%G)o(s60 z;64d2*QGZ1@d|xvp*<3Uw{1QZVwn53=48spZ`7drse%9jbrarWulCBpzt9C3xW!nJtrf%551Yby406p6O|>Mr-zGL6?l7drQd5-)W)k=ReBy)zyu1?wm_*6A#(#PgEA=Qvuc$d{24a4 zd(O>_?_Ooh+y@tLxfSyp4y$>$95 zqgt_HQUkwsH{()#4l^ECMpadfvCR6V5Z24ls^`bOUpoBiu_W0MTE{OVbZ+!q9Ql<3 zNMD{Xq{sqek;-_zS_>$2Y{_`Xf9l#MVOKbs5F(jm=TYo>5?Cq>XAtp;!mTFx#jF~l zb6$%Vc8$gz%|-COB{?+z(s9dE5aek0Ws0GMqkuYZ-46V8WjNzE_kw3fi*{=BY!KR_ zeOV?RJF-x5(uZAmQjWQz;HdNn&fRlzqa@eQT#%~Oc^sAC5ItpompsyzySXcjO5S`h zv$4{RY3v3W1INe)5bGj3Nc1tEqk6`nKhdvOW0eD^YNrR|CE&g>!w1OoR2%DLE;|0or~unIg^W9b{X8WO;KHKQ;@e>!I8h2=hYp3#qiH{wug%sb4HJ zYpdT_$868E1&(|xuQ1v;ebiDUfPSv`t7-?l2s27Kyll{}tbQHqnX%25g~vF7PHbBT z03J^rhdSo5gmyXm;(I?`!Qj^YLm@09Y-;q8PtwMnvfcZ6Bm5~NI%7taZ7}k$HUyK4 z(Cn~-7s}}-OTOVAeJo?Z=Y0NUI&&ERSxnld&JSvis0#XwDFn93 z#^;{TeG~Gvph1W(?biHZbTh5ofeco{Ukv2a)d?Oxysv*zkL%f7 z*Lc3g{6!F03VdtsLz~Pbcbi%u+V2f?sa>ewCD1T)u{d(8BFdmarV#&C%dl5# zar06B2b*FHE^)17(X1T;wWFm}IJ6Bxe|5nYld>Q{D&v=!TOD$ZxT~wBeeHgZ&@8hmSk3R-~87bAWLAB;NMcQ)l|64T#9I2oD6o3=r~@^Q1eLJPjQ8i zO%X{>Smznog3!s>=S%g%>qE&`vw2yb%!zm^AI|C1S|rBR9;&lMBpRu%{kR{X+!Z7{ zPoNjK^5=a}UPc(xM7 zEbux?VPQoF{I&bxE07wwWnN=)qa{ez6CE%-f(2Hveut*#Db1MydeXcbJO4g6-_s~6 z-PgEud#Wzo55l@-KPMuuY+NPlmrzADw{aG+ll04y0`$(twdQEF zKK!WuSYRJp!?erOZCED#gPh9-wY9uc%LBfp`G8{gK+><*al*Tt39DcI) z5<3~mH0W>^Lg@21FP{0bt+>I^i!Fzc`Ng_yU^iY5z?UQt(5pQwma`Yykp#&@8EW%8 z+dqq5$48$W%#8|MQYn#@?PP<0Bj|Va7>4Ypr@m2f*&2?3lDw?soVH>eEDC#iM;6u< zK_lJw>N6>TiA9Qf{n1v{6m(m1o=IsDN&XH@FVpNM;I=$pPrF~UT4q~sgS!2vVb?Y! z_rxBc+>S^7HrZIsmH);^#Hr3xFq^uBuKNkm*-;;#og$@(f>r?SCLgwlRTHA_y@Rc# zKk}0<23t{%1`R*NLr;a+dD1RySg;^Op}kdq(IFQ>cie0WpafcO*w_o#vSCt?dSP?8;4@r z6`Ez_pU)AGvqpcQs+ z0&j7`ZEJYmuK5+hGRfwbq$Wo6cM)Y!dk&?TFj*qdi5&*{ThKK3eyviYY>Os}r zMGl?@QZE&q`DXjVD~*|^QFYf1ZISZF;R8i8pA@5Wa`wKeZ#M-}bkun(5A){% zG%RQ1_Y2uq6F(06O)EoqA0PW-9O9Oil9Nt~GqT-8d=a z1HtMC-M?fy3*FjrSjWJ_O%Iv`0pdxJ(4zMC58uBD5N7Z5c<6|-PCnbIAi-};x5PE` z33UWsA+iW@(;(x>o&;XQLdZ*KHbM7h@aEQOzl3u=QX`9-M>EfE6MWx^NfHPR+;-P& z?~*<3fD~+mTrI0}2>jFn*hOwr7*8Rh5HXQzcUHiIw$`bq!3_*n1ZTdH3@7|wd`lAUvtYKjsVB~9!ywN&dm9{O3A)gq+=)?OeNzpC%=;Wt26A+n% z$uxQo7gJjME)eRk#~^qGh||w#vF>`OKU`;0|1Roy_8@NtI8?&=(7%uOD48RN$Ps=L zV0MSKmypj*Y3;rj|8synXbpViXERb@2HjmTNCQp5qPLC9)vHG%(C=J{O3HfuXL@otq>gMd&VDGl+~l$;Nm@ zKsu5j${^_rtRannfyGl(qAM-G>;KW)s11vYdR@)}(cezlrDSGoiVLkJgyHgP<1Rd{>m&OTp z^Ng7k;@fvG{dPMwQ3qB66^qdm;0cg}0>UyhbK{h16&B9@Ij1D+M36R+H3G!~UD`y1 z-3hqJ|M*2sh+WJ~Nd4NBE?Z#1R=t+Z2fBHO+L1Nz}108k#tt16!Ib#}Z{>y`3{ zG)jRhdG_lH<)1k$&bMMXqR96&X@>LI$Z)Xahta5d1_OE^hIo`<1(OVT&8z98rk(K5l3tj|E9uWK$v!g_1+8b~M2K+& zuyf_2#0HP2Jv{swjL(7P8lw9Y2wYl{wD|*cWg8(gcpX61 zIIm6d3wWfB(1ql6C3yWvB0^>N^%BJJX1#tAdk&>cmhf}XMM~2m8W&lWZ@*qF5^^>+ zC{yu~0qJS|b!Ne%mTJ$>m0ckW7DrUcfCjsm&AArDLC8_VO`m4tb;F_Bjpk>^s24 zWw;$tkmsa&CM$$V#u${RS@p|t{m9c$!7b2I;O9r@t3h*?KYdT!YuRbi#DE%j+_gIn z6J!oadNKF?*pN4HNQq7>ip%FKLNEet(kl5cz?WeG%+7exR!$iuw=I{WHv-z@w5!1; z*|nwdjyi4XYOI$aIR>GE5#%Vf?;~tUipw7(^er!*<_+;((jOp0L)zmnkkY;$=bp6n zF9S*i^1<7ZbY;=rP&>q3h>=$7qJM^@dA^(FbK$(&V;`_J8dWHJjqU|znQ{pg zDv}yD7`S;&2A`~|UzKU=v8dGpd+tx{u%ULGlbp`p2PkrF8;$d`q9$vACziB+SJSK)6tWPxDDt}P9eFL;i|oI|MkBWq2#X=AO0R;f~N4n z06?^|4^^zlD_yI6=!CsZ*DcuPIxIm)5gzFKVx89ISAH6VPzkYNi`v;K&~}Xc=CP*~ zsS!ctb|iYTlRHp#;m5p`KO4210yLizjX-5+^08zVXT2LEkosxJgzt{Wv z$I)73MjkCv^h!w2Vi{o&=+nf$mMCIkmnxd8R9=&nRYY!{-tO`nfnK3!bjlv%R07c8 z(rWaN|CPV^oWwhX$!I4^DXdU{L_Wz#cOD|} zY|k@v4JusPeHq53Kv38CPM?gMAwAry-Ce%6A{nelXSj|zkw{;!vjPnJ|0~tLOu?M6 zysWNV87J3Rb?=AU;!X-Ibbxt8VmXMt-gA5`JnA@@fS}87L}ISKK!`=i=Xf`YO>chk zR(%D;ssG?dMRw0^quPPtdG-mBI-D8uTg8nCj161a$@vyA=sCW(-fB9lo;Vcs>x;(* z0gG*-#X-prTPom`oaXpeJVNd|0-ewlM-T;2O4EGshi5F0uZh0fbviQ+E(mLb85+?j zFZS!i%r40Rj^^#`=BEhC_ihY7FHl7+6J&toFo%~&uDsD$6#A&80v_B%Ov?DBp!FXuhznzoGRfcn7I8?91{*TeF`k$Cq?vOq4>@I2SpY6S<=-Vrjo680OMk)Kp zCn8qrPtZ>RRl^HsI{xjp@b8RNzuOm{^J85wTLOs27Vd>i!@7CMFK3!134KR$L3e+S#4Dnp;;pjpnc~}m7XbK9w?q)tx zYUplpLTSUkc1I`hXzZVOEpyTX_I>d112HKJwAQ6nfK*Urec3dc;#vKahTGnfrAuT? z+(%DVf>`k;G%)C;{-7=Ek@dV9C6-}O9&CK|SG^MpNpWN|VQqPLZ#_HaC=+M&X^h$N z$5E3{PyK=}E$a;P$qJAl?HJI1sXU^(-}wv*%he>nHK=@&NBc+h%<>WPn4uleuWlb}*^&i4Ga;b~j zqsxB2={yLJl+I{Q>-1zVv@`9*?9HBU#|r8w!Vq>ym%(_X zBFfK4Ro=CmL2vZ+UmZ#`>kGItq!rG18^wP!&LlR>yizO`NzM)hlwydzGY_+%j+xj81d_-Lr>gI zRcGb*?BsdF*Qa_%9Z_L?HFE*$(9*3vc8oP+4DN%fqbz7_WFeOVxIAxmR8~3J7sL$= zaV`HvU#ZC~tiy-$yhjhTirh}+w8=4gOawR3TK0_cl({az4p|p7-eQAw;=Arn_45O- zd1TMwE|ukf)N?|SMhDB>H}W!plTUr?=V6pML((;pb9%Ne2UU08b?b6_)QfZMfHV-l z#VUa!Y=H$ysAsT=`JY|k1RRBhCy*SzxvbBIUwIFSO-A2U#F2HIYz_yJ6h2z$2+EGH=<0np0znS*YlDn_v=cUs@1GV5a9HvI+ zWWa~~*9A@{;O|A~87Mzz?UXU7SbG$wjK1!L>QmK#F!UyI;~-^dTNXsOkHKvkIn(2Q z%Tp$H4S&D;Sro+)n6M@0eJ|}#g$x>TCPDx#&bK@85$HHD?C`PnACif&ukrgH@Msva zXxx>wE&NXsA&T>b-X&Lj^Ims($S?hUli7w%r(-P}KIB^L>qq<%)7x$OfO)=z zW}EX*pg0sXKx8o6?-_yOG8uh*KmC@O)#L713e&=D#|y!-$-z!_{9sbs>eNL^WnF6O zk$2mYehk<*;d(lIe|`+o45S&Qy8tM;Lo>|F$Ah8WySC8x;)E~bRHBg2pI8uSrHv5n zOS*@2PJL`n~*)>_k&04n>DW11_J?KBaj6={4nqJAZJeheHK`B(4vI2bes^q zq3jgIrSLO%2O_f6MM#A-yc#p+`d3DS7-p*T&^*c+4x7xaxpJ2fH+OhP0gVc?yYtvK zuk_Y8(mB1phq&n0fR%v^Ed53SVK{0WWWx3L|K$Q=(E47V*aQu;lX{YE_`KunVI$(^ zgQhsHBLX^`x}T!S8c2&iWToK)fB2?Q;*W~R8XLQhvyPqiXMotnxt+sjU%NHvSjfeG z3!CSzuvo;qc_*&ZI$tPa^sB@fl^WhC3rf!co{yXOGGr{N6Crn=OXjbiv7cMXIO)v( z7?SDF*h3tayt9-sL4QZ+fk=`TYb;mVF|5$X41}(mF_j{Od{;~0XO?T73lYqFr`M<~pNnSvzDO`lOnGZqP#7lRx zUs%hm{tWMu1JU~VabR*ps5$><(QS3re1b4~T8|4Q23}m4IB_)co+pNvd;ZxLLc@^)p zUiv=2Lhf|_X-mx({nt8)5YQlt7-9(HOE~r)(By>eN`CZY`Xi5&(U;ajNzga#+sZ5O z&9mj#o$_dj_T$AEo>x@a&zVA^2+#>ZO>!9x;3gOuUsS|2pp&C9qN;YtJ26(jyry7= zVE^r+Z$CU+!%R)tBx@GKvc7}C=O6EGX6#g1j>Z%0s2!pQ`~zcuv33Gwrng(4*oMxg zXh{@#m0uksk$mO@>Bmg=#@8E4qgXrNMyx^o*|_iivuNdGkG;_Z*LWbWj}T=R!%#*u zlZMZoGSsu?EBW0#S|~(pVhGp!E=4`f+~BM5^DBSuPH(HK=Fqxq$;@OPoLjd*cqVYfD|{uY z9wcCJ))Zu_D?Nc>74P8j>Ux>?4g0xYHwe>KE?4Mltq!YY zFx`Ds(Tp>sRruo{_?W(kgfaiQv6P=vBiIzJkM{)yRezwI_xQtoMZ7eO znJHvj@-X~^-W~AQjOdRaUr8V1#ADOFzWb4`Ju~%h(=g>y@H6@Kaw`1<-zQ4VRjAk; zRdCZ6Vpi@(%$GKTl+XQv3XO8lh`ya+R^cXnYfrrV8Av4M(nXl>SJZ@~`03Mqsk6CG z;&Cdc_gM1$|CkF2Zo%33hA;zOz?ALr-9Hf#9bn0?z)|-l4*5|-xJ`GEgpadgPER^2 z+?vBH@BL&!8|w~lO@%HJJ=eN7^;XkPNp{LwF?krY*5Hk9)}To-bfufzo2Iw2^Zn+B zQPhsl@Vh~$+nc10^hckshJz0--Yc`loKdI;& zdd1Vj6%%66Ia~_u#9z&x>uMj%X`85~y9e3392c5CeVl|6gp;vDf^SG0j~aXWNwq3p z@Iw$@l#kO7h3=rkl!eb{4m00mL{xXlK3VX~_03JnM9GwH$r@c6|NHdv;rCW@J^7oy zk}ZUDUoJ%JKiZKGeKYZSY9FbX>Ac0N;@X(@B6+RWa&Vzw9qP9`Xd`nHQwvtcIJfp; z)4of^GxQXp(;njMSN58I(9ETz$q+Z7<5}w(b6U*@ZADdrX@b5U6FC?oWWA-_k z$JnQWG%!0H>RskL7hU}E=3c9uSTI6dL<6Op%UYf;Z$*>*7qf zEp+7kAHL9cI#HiMu-BHqgPT9xHyNo?k@4yu2BlBye=sPXm4{BOp9>r}2tK<~*bc6_ zPctRanwh*DJ1dJ!R-yuz}eBPdNT%5!*TCS60m`VA%j ztx<<(OvZtNXZ~v;ylURhu_QM9piNS8GCR&=9%?Pg1e7@EZgAj{vKE$g85*lWwf^8k z)jS{35!`$AV+1e~D@d@i-z5s|u2Ev2_!TQlm48KhOm2Q_UJuwArW|_9OPI7s?74zy zhlHcObk>7`RsvaFXs9UN1Hj^*OEBVOF7)e#Yz_m9sN5e`fTDbB{tz=sL($$z6ifrZ zvw+_VZM>}~Y+||bd|NY&v?A+xc6lE(Mi{j?={w@K{Ot*iJl~{R!y5r~8vK)TsF8Ui z019w%lWdG=g@@$hsjh*@$}_$89uyQwj}|4lowoy^qU#ydgM(*BD~<#P;jJ< zciXf>OObx-Ixu)J5t;E!M=TM|1rYB#^00c|B4yLO22b8PiiJR*7=<>7*RZCe>Z)2?>CGNmh(1d)B7-RT-v z`I(XP6mj65O0GX`x^yC)eL)X& z(=IEepfw`Enk8RXH4SAFwez73E>v8ObP882+lAiY>L{LeKp- zT+kJpfSY)vOf*3!$Zr1uBICuT!R)*Fl)9yHwpw>s2Z;m&0tQ#Q@M9wd_b0a$BCTsX zlH%&%BWr^A!!ca-)>op|rwP$}yp=W9-u+ogsk6M*k;sw2%2y9`y6^fJU8`}Xh!*A^ zcw6+N(OaNDHw;e$IS2iRmjf5MUiTFbIL>?XxbKP+)Q1)zPba*}qB3Afu+DFAyNl~P zhoaGK{1U4BU8UsQ%)+G)tRQk{$e7o)%~xQRyR_J7UUAQ`DXGC-y+7s|NiV4s+gy4r z`Q>^6V@mQIpZeqx25OOKZZ+NQc~rAoj?w+$O!kr|MALTd^n*=bL}6HCWSQRSiO;=d zktlkln)QS@&C&5tsrJlxHV_-}>6y$UaX0;0XvB>NKYhPf!cf;gQvhWxRVa_+xZ1=G!xtg)obY z2v9)w9`*SQTOu7_Rg*uH`_F*KJiL|LAu5wgOd%0WQc{UC%k0j3_mNyk+SLgv|DHD$ zsr_p;H6g6Bbu&1fOBN;H1}R-_{4yijCe&hI;W`r2LIfz^$3)rv0N_$tg_a-!(UfUm$7?ISN!;hF|v{feW| zF;_vzpnv5A1PZye-c;S4 zu9lTiyAkHjHEjYL=x0#W^6rO~kH4v=;Ooz*SC^sQ+gu>!nS?)D-{!M(a-Jyz-WF*$ zDb#ib>Y9f48$ypJEmAqiVHwG%U(e*#_}t!sh`zz(xdAaT^(L$QW&t|i-cxN4 z=Ry}6+irrqGokk(ydNxN>%&joA{)&TS{{l4IP?%ryU&Y_($JTwMcmHCBI0^N8@QdZ zw}vbzWb5c<47fR(5KY4eJ&kEzNtKaP&$1Cn|^UuYP_60$nkn z_n&NPL1Y+hjQCvAi**MTr^mj%OP==|E68nLFMA%20wwC@c9#Gx)=^V0JptN$U(`jl z$AcoC+k?9KN+`Os-QDraoKo8cbC$d)osj?I`R@Jec**>AUc}y*Bnx6 zbp7EwQ-s4f|4N1hy%zVcA_K!kn!g|b_dGn3AA&ZEPX00nG}N6>>D8MR{j>A*N-fLe zq}@hu>Llc3T5Q-c!Tz1d6$>H~QJ4>xc@25IWw*4kH>c_hhsixME_nNCV%_SQjM=LB zI4mVU?f6tUKcYU#jQ9HZ5#IcFPJ|^qYMse)8#M9yH1JnH!9zI1P zuhw?bY1`dt(vZ83yuXOUJospe-G%XHtZdLj2?IDKc=hC{AWS8YuVAwR0`M89p93)r2&e){ZiX<*MtXMgEFiv|66>-i2C z20J_YaX{t4%;sNKOKc%D3Dl6YS|;H=dwd}3K`24;iiNNtE!1pXD=qTw=FJzy)r5=P zK8~d~2&=K=1-2A95ya#dYi$4l#GjP>{6)>2-gfIYmY$8Ud_X`s?449!(o4(?R8Csl zjZ9I+{LQmJBvlvbD4>Icf?R5(;>6!HzL{s!?79P*j6kx7Q?BXyU@<@~JizDzLU?<7 zE{5c~?-eQZ@@_5bLU+~z*GXjl`$K!N>`HVY3QeWMme}%GfBQi`-QY2dRvG3CVIzdN zzO6X!yGM%y+;p9b~CJ*@6H)eW`J5 zBYrQ>?>@2w+GWg=no~D;S$t(A<2MV^<{*t{i2?z)i)=;C{&e2u5)3?NqZ_D|8AyyZ_w(F3it6-}mq7 zAq?f8zO2bZ_sF^3KoJ&qoHEs$%jEl!uxyZNaG_RyI1#!xTV5~H;qe3U6bci6MaBML zzWeOZJuTXkdL%_QzacdY3O6U-ekBF2`}6!c3&;wJfsU~~zQ2@_9;ngx$5l+&P3H7e zSKzhn<)h!|AJoKOeX>(?@nI8LUY9#!vg#nYQ0+~AW}yj$N+SPaSwA+10k;b9$TK?S zzGq%v#cDHGibc*S)sas3{4Mp=o*1gR+*zj5Pjv6`XDcr|@rNlj zCiBjYiRT8q<(T*KTGE{bh7OL4qlgp7o4!>7P1zvVx3a9Y|(>C)?$>o42~?92*LPJ{q4XhJv1ZLE<`^2 zt|3mJ<{|_x-AdxW!asyrtNTxY)VW~@u=u?7c>8vU5h|AozLWX>Q6p@?K-(ugC8x3D zLiHHt_IcD~f}<*H;qI(5H|NdgGXAd$#isqMF;%ZR2cwG=SCZ|b3t>Vr1vDe+8n~B+ z6A{xmRU*k|P`Mzv_uhWOi_`Y^-mv+<3Uzi-6>nZ_JMzGP)Zw{!YKj?@OwRaZn8c@@ zVnKW6V$Wuh&c?*a{`ujHpQ7tKoGW!BcP5Xu=m^UQh54if6cwecA!^Y@i}{2q;C{%k zypPNTUDIsvjXqHFIiFXqw$*4x;tlp)Q|P`Q?oVIsVg#EL!ShxweY1(tpE|pdw=M3i za`;Nw6i*yR5YSSQOY2E;5y(%ZRC;1$b-l56z)JjdefO9owC2-a8hrS;0_4U^;vZDI ztj#7-P1;b{hN;rSTuoPZ9=1LLB_GLOzr7LVnnr)dMz>6dEz@awq~5=BN*`~z>hI{b zj2T4;<%i84!#Tj0BtHox-tT}ZFR~2j0ZM2*s4NCI`V?3-jGZ)+(~*v<{j)u>L$*kK zOqq127Tv3;5y|Pnjv8l>L8P8y%5eBIxeosPO~wWs-#9uuyC12ZwI8b4+M1n=qL`;q!|@XLN3Lv3n(IP%zFc|olTnZFvtMuBn`1Jp8$R+``S*SWk4tSyp;d!KYG+FaMy1s0No-nvST#}D zXk=0~uptqmTK>6(L93;0VB*gPUY-2JgYl!1>wz@9~3|XVU)mNm<>#Ntj0J@>tv~*rV&) zK5Ow|eyzYQlJw#h=G&%#-vs-u5Xq|PMjmBb zOy?9eR;KopyBl%oqUUN`Ea+{&Y%$bk;Cy^ID99c}oGNDr4%z@QE}FGT3N?!0QheE; zm?W%)4WB?^{ti=dnQ(}t`c~gxpDzh~N(V4eek9A1oWyL4=r2R=L zOHBzbJ9GNG&-__kzpuRQh;Z8qx@Bt|Hlu=4#4%<}KSlgcA(zqV`+w<7nz1Yl+BqNK zrfD|uCX#*jRA^e+Y$DOD%}QE-ZA3p}A3!eW9(AASs+Gi3r}r}sZH)l)ADW7=m7T?e z3x6Un?9|&Jjp_U@ee)q{`!?5>^w{p{mOuZlNjm3hKulTH?JPeWUy9C0E=f!d>0Do- zceB8XX_tQY7q&x{oLQc${@n}{iRe~)b( zHk~E$_U_HcH(p&9d*g`X^pOY@xOub_BiQ8Y-pSnoJG*ZP%gUiftcaGUM@pgivmhc!f@zDA|Kt6E8|gvn81 zEdSh|^2+M|5CMwZ$P~Z9zt5;3qkcFpWFP(BR*ZH8Wc%jDpvd94=n8eIqO9^o$6zxq z%L*ZxRn*KoFrmnA=Oc~ov*hOGg$8=1l8nx2(WV!g=*kDI5J(BaAXz2s^nVTy=wsNY zvR4Vto!zv^N|)H-bIQ*j&loLUz9y;ldH#C33H8Z&e74OAIodjpk@Ef#{y2=<`yVF0GBYffq+U0Ufjl>FUu-O4)NtA4%bn>9MHq z?}JL1=L`TZa3^T{JSZ1{5AnAgN!L)QOfv?7{Y_6rNM{W zKPkFL{dC5h-(gCLvxl?ev>w_SPD}{S@WSe-0*&S!(K8XBYuIEHo^qd+7*FL z4krTdJ&o0oYJC@vX1wGtN0Z;X<5fPCJ&a$^Yf#7UX;t@SPK=j=a6Bjt^tq2}{oKA4 zTFe?o4(R+D&a6|E;!05@%{R;dHOa{2jb18nL*ZXdb2|^n$-{f=`cr>9k>rjaw#NU$mf=G{K{Y`lYIcmw`Tkf;19oOXb zF?`fUwtZQk8r=yJPAu~W+J@G<&;&)g(-X58doqVqwyojdaTOJRM!8d{u0Ix{hU@z9 zif7%%gk%xbe%)my{hHnK2`$~r*2?+f7p#?XytoG(-!6FTlJBTP&M2W@x1k(VmkD0; zz@Q{qYZN6T9Qc(F}qOGFMOHTwC# zB9v01kSuoHs7y&K%r|{hKm69uO&Q{NpngkK9xayQw8%Gw7 z-j3evxYTpdJXCp$2+LqfTr^Q2Vrsr-F4+OS)P;!qWhv1&h*pd~A+$PSXZX(6$A}K- zMsAYHU^39XSwg!+-wf4j@cnX7$k+sE8VFn|24UWhKVje6kV=P|p36s^h3Q@Z{%gPx zrcv2S^(p>74hM|{>JPR+Go}xcLQQ6VZF2^PKs@Z_mS8Xl&+<)mSMv+u7tau)Cv&Qfg0CK5bi5d4g91^w8k zUkFub>dpcxQj^UEg-#!@Uf^m>ezo-4;B#eR&29ptJF?$ty>+oGalK+xbNI_r$KBe{QI zy_k4V1F%w+>11?X-p=G=*?6H(3o~M|!hUI8^05C|fgYl>sL@Z#B_?x|wKm%YpjZs* zoSx@R;QpdB{J&{`uPi9;<(E3kmU;Xg+DRc|>}?CU6Hz@>^&EWck{f~T417>^n!%Bz zl>=uN0X>BHOY>tlNk)kFs3}(@>%eMLsL{&u=>JFQ8^H<}arjiAzV)GXq9iqe{?q{0 z)vzq;{K#hvQH6M$M}uqiAG;L?lq&LQwWa0cN5J*R-M$~r^*~4RZ{B}*BqQXf3?4hE zHlOr+wXe4%*5Mv3e?^XgbgC1is9#ILDw!koe(aUWhFG=fWdSu|+v zD6##kt%xqvRq!jHd_-Z_5`6h8MSJk$n{f$d=_slvD2U?`Egfl{*QvVD zp1fBITq`Ae!ZL2-BGrH}7F(7}1qdW9pyNRPw;gSL?7VC(kdqlQ>^X-l36d&O!(+*# z6|F}n8-eSkcx(-v^}n;=TB@uLc<&bG z^)sUM3WCvLo%~PxG{TCg`3MR9Kka>aAe8OfHc67CQqS0@EXh(+6nYFJM5rVol+h~0 zRKjR*i%=vxm93JLrAfBRGN!^@5qtBjDR%@Mi@a z(7VEG;K!+Aj`y(e(tF7s-0RotHCPf!HWdR4x8dh=D$b5%sD{>ONp_%wsx((HA1NF; zP>_sFmB5Pz+06lPbW!cuCwdMc^WC)hh9Do0H71uFJQ!Ob-X0LzB15BXZe7D=z2< zJ(5h~W|x@HM1UR2Yrph{H zPRH}&WfEOYhN_3&kzoclONGDi(+jz=$)gL(;P_P2@-YI}^8VtcMWTs#&?yadE@G3$ z>1v>-HG7-{E0b$Dp@NL}NnumUzOh`NS^Q)z`Gs8hk5W6nA*{idEPqKN>Cvbd$5Rl% z{7oLj*S8`2Ci9>k91P+N$R7lkG$vtJ<3^7aFCD`M2@W!cPJklF=joC(*WG{RP{iUe zA0r=RF5jmc30c}QbE)Ib$e<`QP(eXQT4D;pS>A>$mV%n-F8K4QCtl-lp6%YrRN)4r zrg^P%FFjB}dYbCsShS9KvJ;wZqSckFKluUSLXG>1YHB0@5 zx$lNd%3~Hqil*6qUOsR~dlYo+MrU0;7_06~=XhCWM@C&HOT>wjelgwb<*$?zL6+7G zAifwmC>|7`p#lkN-EN_REhKbm(`?R}YpRRNyF@vXHvNYN-wR~xx6MD_A$~%P6geT& znMBZlgS(g9d&X-*8e{!zLK-+VO&I7*GhE#yblD(`%qo4>0_LvGp>%rUtM+XVWp|gi zgokV1kFEy&*f$5-5(boYf@gxtkNiW2{m+w8r-#XlMX*S#vHM(JL*Gnucs)@v3CjI* zA!-oJa$onj?5Vl=Ed?O~@sLWiKH;i~4X$R6{H=Tw)sA@Gpf?%Wl*1~fY8ec@|Lefi z#MQqKz}oXV^3QnA=VoYcANw@Sw-$H?-4CxbUX9igVj^d+YvFrzv$Pq)4zCKJ0b{TD z2#VADk(5Y#F%s25MX)+@?%9(Hk8-%~CmENsM+%Q}1goX(Dafid^HSd7E@>)ts4Y3! z#f?&wgxuLbN501wvG|{bkP8c-yWfUYYAox!3WP@a{SqJ|{a;(0csMc~khMaUW{7|E z<1;ybg0o*?eyG)+n$dI~=iMEkQ&(}fov;7WSVq?B?6C-CsD`Rb#zvh-Po|HVy+_2l6Tj*XzR6SOixH`{ZkcY|)4V`|SV zbNimHZJ?~8bvL}g2O{C)i6x@B){eJK*O6*C_K!+-KYy|D#K}#p)avANlIrsZ{R^hR z1O5A4`?5{jmd1V7;G`lfSf76L%%!lwNrRbGET*-=2GP=@VgJ%E#Z{-z60Ui+Bn`~g^4%f7W(f|LG)i%u^}EZieJ|Du@{KD( z^{t$9gy_C%V2@&SPS*>)+3WZkhS2dp3glu;nXpYu_GkmYyObI@B%J`+VtGEXd3_km zI*6*F4u#f-?hv(^`@;|?c;bn{8%L&ZNxO>F_1!^muq*lQe3|8FM;dL?>}bn{F9M7c z+_$j58vGH8y}WLW{Jxk@`FWGDK`{e_=Y1P*yGKQKTgl355Z~oH-Zf!HJ9Uuai=`7W zA~i$?*t=orHY=uPgSnn%k2)bkHlfz~2t_l<>kxaepY)EVKJa5wm3N3zC$~SD?K<5U zc@l3FH=gKRw-e&9Ugm~9Erg_J_1Nw{EmdWFv7bE;epU)W6DByAWr_iOI`#n1&&+{Tzk&+EW$ z+?)8BARwnFYI&ywpsiCipHVhB5%!X(X}ixm((JvhAJtesgv=@`G~SgUBUMKqSem)(5qUEv?c;OZjX#lpWQ4O zKeCtWu?Xw9TIRxj%m>2l%?qe?>W{;Joj4%8Y`%Hk++6blm1_ zGP=AnNa4?3>Gcszw=PCF*zB`;73I^&eFy%j~PlfUJW!s_k>e!rfU z)}!qB2?@fZNSDg(N4}*SCZQgV28>b&x4?qd6T0jEdNauIQXi9IAU<0O(NdPwlvDXy zcaFdh-*Z^JZBS4Z>K6Zs4J3%kE#3rdF58xSsR0dY!9h5VUQ1ZHzVr31w4dIX0$d(4 zGjf_!pWgBM=u9qg(vwXtJnfoNJVkKXmo!9;D+p=7tvu0}ULkQ}};FjA2v@z$o0+X=k0h^*b>Ax_iAGWrCE7xhNKD{?`x|(}w zLgYLHb(XHc-HA10obexyC*TMh0@7~zA2+U)m!JMYz~3U7M!jwa!)y`gR^?6~sKUr_ zeP1oI^d2)D2M>feT>oqt2Ytm&Q6~MWH6i+HjhlASE-}zt`M@V!;h90ouF@Gq!@6x9 zX?5t0#h-3$%Y?*Z(UJ@ExFPoBz1t+VZ^dMbWyB{6ELOXCJ9oH=H6(uYJ3@`l`cu~1Bgf~v`$ zj>8`$-i+Ree;_TZs>YD3mx*X zz#(I~?x(X4&iOch=-IIirEFVXOKdu~IX%KZb}F1zdc#F2Kw&-6ghTIR)`%!)$Kpd{ zzoBX1g&c`t@Zf;T`?pyAMEBb+shT7>Q=H&~O>)N97=f!jzP-7MUZe0_^M??FvMOCk zXKf&s9s_x&M=2{TB(q9IkrtOFSm3Vp*6wZZ<4A^FpA2r};|DvYJwiDzR|+xThYYJB z?ygfNWw7jKg`*@zcy z@GK=;-P3``hc>gfQm1Z*+2w7DunG0tICiA8B1Qm-B@vX79yXk}yhFoQQKfd}40yEV zMitJ=qqEZc7nE!rdg{?j*JU`Ud^NI(hYjju zSZ8TyTuPP)Q**w5D?}q7QJu|Ve?P8Y~_w1r7cZ7`X{ej+ zS<*wM*6C&lPMa-~sb9AmOrX{xM3MRtE?duCahLN3!f#^|>UikYPSmIi3WL9zdd03suL z=PHK_QCT&}%cCi(Ls4@=%-xx1j6-^i@5GkL={*1bZULFO&`0o}7lNB`?hH3*{tMK! z6C5462Ra)cBnX>u#`FBei`8rTc3dcm)r}(c3@bD>86OI4%-{Zg71D)vghs|TV~;eQ zl-kK3!|lR4yuL?Re*!1xMWfs*6=r550bM>ke~Y#FK0a*Ll#@?y-Z}kd#~Vg;EHv(s zR5D2J3lC?-qI92sz^^0kD7!(xiaQ6hq0L+#whdz5V%IYOT>@7c6z4k!ZKR^?&n~u`hblBm! z&FNI>#xp|9c&=7c;W9+EvCK&GU1bHjsnvHgcflBxHOo9#5l>i9yP_#K~r9^|Y50cNTit+cIv+BN#_V)MKaM=ue&M?D!RW^f(gxqTVW z$V6_H6YP>Y-U1(k?@A)XiH+0~bR<7JU7_!+YtKl;ILom4#h9OZo#=TjRt-oS3P3%l*g9g%0n%ox5zR7x)5N2ky2z`kW0*Ku>#zK)&5s0{Fb;6&fLB~tJdHAIL4yxR zazo!B66zrHUthIRC9Pt;hfp+hhVpmvoFv9JkL5o2E3fj(>x482H*q%s6ptQCnFE0;p~=FU!VJA4xQ%!!RR9mUQ)w98XYrSiyO~W3W zsTHf<@d~jY+X68tPyK!-+*Jt3O8A1dPk3R+l}$s297kf|%5b6>-j`vQLCavQD(onj zI`;v)jq4#m-Y5ffOyE>pTF7%3Msi74?w5tv9UE%A=9pyloX$A3?Kd%t%OIozr#`F{ z_3RqYUQ7LUIha)kozM9A`j-F4a@5`E=sQX}BzSL0G$9IUN-@W^-9>r;q**Xis!QvH zny}k)+2TuF3S%xd;@D-VX({($jAIwf)ARi#hq)c{edCaO<(iI_?$!2QuVZ)&zAtLl z1-&sgMIeTts4JBJIp~F@e)Q>`qc-&owgIdaT7xoX^jb4PL2#4=LNGPZB5bw!Mi3zDT|i~R=?1zo~SyaxW8 zm}Io&p1jw`F59dTSwChA5Un0m=+Ves|JXLuR?@p5A<#WfcPdxGr;{vcyn7%POQ~4x+|zqjOG;^% zn#l0N0WX-I_#?^ytR6;)4BscA?NU&92KTHW|fgQ)Z@|OESB%J~GYO=d7p}WfK^d_7Vw|f!0 z2-7WPs~7Y{$^zj)Lop~?bamosI;Q%_p^%OF>;%HaS6;hh>(7|x&s-@`pb;jfGwhES zDsl5a!jt;8K>b}UEG=x3nS>u%^|{w}!ET)NX;y>s zHi2O8pTcUti{yxFKN~;hR5?4mnL#-bQwhzjioyWF@I3DaraX1=gmg*s;hG#+#x+Dale`3in?av zwS(*i|4~~G?D7xO^UQ1;2v)Xz^AWktfvQ`8+GpAgd=KjC{>8z}uz%0Nm=NhBLif0b zx*2v1^eHAxIfPel9nj+B`3q3Li2+7*#h~20B>vw>xOksKB4MYefFjq1I-Ye$J?2lj z48>#RLR;pf_fOICiryvyA;2R*RPnLb;W^t7^;cdI%zO@A5!$kSA5-!bC`I6stxmj{ z`!6Ne-~2p-H93ARjVZ=#A2wT<4yZ}ltj2YCQ#^wpQ5=~TkCQkC>xy8^x!~c?jj@2r zU9C8AxV0~_^t>_W;DFelYIljJlU1L;9b%b6dxq0a4S6|U9fT`zySmjq8ZwB4J;}Nu zAOSI4loL5R+}G!|=`a|dFay(Q#F1rOLJA8h7#%(VqyW&fNmEJsZy}CD)w1ZFn(6?FV}^+6Ct!b}S67=()GQmDYIo4m2Rf+s_a zISM~z2-kM(!=CLeU6#y99w9zb_xbDqhv^z}M)kS(5A1aWlA3)QfD`5<_4%&Mp^vR+ zlqDL^DF0>)kf3E-fLHIuLb~0JQ=I;D2IC%C(2^pV&RAc6$v!RH@Ea@ZxF`V1>d=EYofHzF2F zMQ~t4l}ER6Reqt{Q7?VNW_uTo5og9Pj^m#(b)mYRVC(6@7GccUa^jw4p<;MC55ngXQZklHg1W1C5}UADceki{(X2J+F^>?p zN6Ic$b}`(yKP$V^<;pHJc~!B3ka$s1hcFQ1w=>@hGnBcB0ftn026~#Kqpz>A6%=>f zRgv*Dqy5hCoXb#zzv-aX9@_W`!?zBvXuRvS6IgCDgel z5FQ=LZv)K!?14%2&}P3fivL8X)`D*lYO!_f(zUr9E;M=xf4^dW1y4@%Bswo3D(2f? zF3Xa+`*V$WF1=8mF}A*IaUMe$_uJqXxP^_gHm)SGws21oGf^XTC{oF*OT5^i@(L9p zF*ziSf&%tg`YB+4giwCkAH-3MB_;A5I3I{!zD!;aNV0zNIF{Zwlc^Q{SDp9~p6GV~ zB4Pcng6hx0cFha()BM3bBPFo9)pAH|!1Jb-9F{le0Ad5%>{p@qLgJ_s=X712y{oqx zv{jNAA{70Pz8NtZI6xsnV$8XSQnWl*2hBn>20S{%v0jB*8h!b7q=M?JW>6W7PAjsR z`qZX~L@57j*8+?-na@(PvVf{WgzzwA_JzBwih;wCjO4FpgQ`PZ&I^f;MV22Xp$1#v zbYKKpBpyHI1%l`wu>T&6E$#S#UHI_t>KS}0Cif4X8TgbjDM>b8Fxj$XQu4+w7VeS~ z5xJy@!4sjApa9ykd|18-KKiFIMhr3KNXspicHpwUnH@{~xp4L`GgU~;DT9%5>)^$c z#?YRnq%XcvhUXrF#~jDgsT|-Re6J>SMJQ8T=)f8PGn?MOl-OmNLY)MU|FrIygC@KO zVfJg?DJqPy%|eqJ^K5(Os+#4;^jihRwz_ZkBm7RSvXt#fmDj4Ff~$RUyPXsjcmuzg zonMcJmGZa3f8#w`1pnY5JSjCb(YBNUi`xLE_$=|A-toPDR(IpshhLqI(B<1-S4Wm$ z@jOPJ(Tv9~DlwwL?!~*WuzDKm{Ld-n)~Yq!B0=wwW>6&=3$`B6YNaI{K_*TOGW*=R zw4DFqlS(-MSDzG1Us$$DV<4~I&hz@EN_ODizu+sHT1!}xz|bb1RZg65>woimrUsva z<(UpG{m~MTnR69bkPmKUI7cG2%c#|dNfZg@OU;S+%_p?>?5u~?AKehucH{w4TZFeZ z-hN*?=bn+eyAucwb3@sd`fMG2w`R?prpY$Nj!3~EgdOnOi6PpXoWQ<9^vLw3Pj?kS z=8hNVJ%zV}{h1e#7BB6nyZ8N!gjg5h<_ms@e0a-i#L)*F2Mi@}gLdt7Q1n!rs?C#r z!GaoEb7212n`lt%A36y9fF)c-xzMftc1l5l zb2{B6S*E-;aXIFI{~HlKQV(U5M0gbnsCAcs77NQw>&vV!Pm?h{QH4$Q5GArSP_*%2{L>-}f(&m76sU{e61l@^jQ` zu-=Op0K)?sjw#DmcquE0)!=9Q!~M_^-sroxV=6V7U$`Gk6S041zdtPxz+JAs1Haun zgjHqGsL^0+%G8eW^_BEInBGceJ5{ho@7?n3nx^j5qx&Xz8?&54l(C@AqjViADf0C1Vw+T z%`N78{n(gZ)SnsR*q}KiFe{3w;D|h4aF=JeZPVqgZQD?VVh((F3r!mj{y##){KbIs zJNB;pm(6bX+4M^2tnO`Tv6>GqqnaLXigwIIZIP#JJu^Xi-IPIyX>}FgEwtWHg}OXi zT*30z1Hx_`0?OGQ=wGCjzInr`x4a*}T>h?ZDMWaf7#8eo3OQXJl6AroTOGedv|tcg zWKBuLNrr3+uF+r#q~}7@w(!;;EV0vEd4n%sYnx$U;-kYDtsq`*1Ya?$7onnh+S%wp U@n-Pf;`q!C95H@j=p6ii0Eh`!cK`qY diff --git a/web/src/js/view/newhome/images/QR.jpg b/web/src/js/view/newhome/images/QR.jpg deleted file mode 100644 index f85da5edab90395d797154fde95c82226ac9747d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37822 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 TG+_u)00000NkvXXu0mjfdj0cY diff --git a/web/src/js/view/newhome/images/u1229.png b/web/src/js/view/newhome/images/u1229.png deleted file mode 100644 index 11052cd14c1a0401a56c366ea39a6f12703bae21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^MnKHN!3HE1{NLpODaPU;cPEB*=VV?2IV|apzK#qG z8~eHcB(eheoCO|{#S9F5he4R}c>anMpx_2i7sn6}@8lGTo&}AGrW39t{5WqQ?r}aL zBjpF9*l}jI)$Z?@Jy|*0AF^I>p6ejBzJ11mF9~cy2Ohj*fApK@D-Wx~8AefeM(2ad z1`XGpdk$pS@GkLHxTDA#FiGZw@_)rg&SDKVSFEN?64PVwO0rSt-@{nkF870>r_)U# zjAfFn^THpl>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0ToF^K~yMHm6APA z0znXlX9i;|_yO2k(EHWc@Ef$TAeyKYBqmZ)8F~^ahy|3E*jrFsA&rW$vGWhmYof`K zeVrXw%yL|UPc@4M+WLX)Y}XF=6Ji6&UTM^7`A$09M%6yIDeVpssb)gIkNXc)PoLqp%(6>Z+kn!;D7V;uYNGQmpv zg~1}Rw<8@N^4XKSkKRI6fPlD`|6c-X4&^e2zW{3L#WN<$4t eDpvDEBBF2OS$&L9INbyQ0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0z^qfK~z{r#g-vY z98na7cP0n~V#NwX1tcUztRU$otRMl?qym9JP=_dvx{7)v5>ZjnAJ94k0+I@v06|a` zB;5poC<%g1K#$bJ5uZ7= zjJ{Al5hm1$->%hv$bCnmuMMh)PK`e>{zxo5I9DaFD}DsIYh+Gy?)kR^;lvEF#V%sR zQjg%A7K3kuUNh}F^s4+J>YURG^^#a5KZ?d+j^@4%!%#h(G07p~grW%@4+=cmc#IS6 zXaOOyG-y+SM-{KtXsjRpgCmkfd=&bE@kMmim`*VGW%;srty|r2<5FqJxQGwF7u@b? z87F?M2S{DU{>xi_sxmHS=kEazb4|w2f{bt7usnFUZe`qZho#bz@qrtc%6`CQ4-;qn z;XS`9MWfrSB{Sql|M3cm#656P;Gs|Bdps{(23WJT3D_hu?<|v`=QXj-&^7~=%3mtx Vga(ro=XwAD002ovPDHLkV1k@bF=YS% diff --git a/web/src/js/view/newhome/images/u504.png b/web/src/js/view/newhome/images/u504.png deleted file mode 100644 index 59fd43ac276892b0a3870a09e67bd15e6404c7a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1190 zcmV;X1X=ruP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1UpGYK~!i%?U-9^ z6jd0<=epgpS`u1lDA)=Ji6Egw5-}l0!AR6#hyfy`1PB;4kU;Rw2OoSep^*fhl;9i2 zs7;I{VuaEvu_PFvt(X!}Zqib0YZ036?%d8C|FiprOykaFXQtYR{biG#|Cuwp|2dcM zeCLRqb786?(f5?3VlFBbb5WVn<`N4f_UNzX^)^vbltnF4&3r12M*`+x%jjw4#)DMz zyMibiy$7Yt9Ch(dsct#dh)Q&GJUeI&bXaJu)O2;pTk`BxbVCr>-7d552<$44uag_s zN{=+sjWQ|69MkQw8_s9sqIKttn5t2lUQwD}6*CP~VIubUZ8p%s`cH9fRBm`)n)x)k zTdJ8SND9>mBETHp-n@L2-95{5gMysKPdk55+bqvrBdQsy6bRGV&^h$JJ$4h0F)mRC zuj=AA(dxx2rGYsgvfr#WZ+&a$hDaxeHTYA$y@iAaexZa7Uy$opIvrO%i;9xN8KY{3 z=Z8s`!Z*$_4Fij=Cjn7ZIMYa!qOw9nB{6dtJ=Py5tQ%h=)=*Jwk}zjm#)S{EUp%Fq z-m3kuE7!I{JM%U-vvfBG37Es$W&Cmo7D)?&b?qzt$6X|15Z4@{zj5gh2^ZGwlL)*d zq7v7fgApb;&yOl8AwyIiw8S7$f0}HPA^{1=#R;q%$OZ5f#7G#@F1mdY&I5;SFLh z@-`9$5Ri@TRubNDeH3j>q7=U7s%QCU4M@(6?gLuq4$>~nzK^x`&GuhCUUM06?^{Iz z#+;a*fmD&iM9kkm&wbf!^c?W|dxW~&@iltaKGGAxYX|Ow0?Z-lWqA8ZfQ|G>6Q|L? z2}skiid(;ZmRj*XX%|>MF=$A5gCSpXVCh|Z@w5J8E_j2JKe@4bZ5s&}=oc*WB)mz# z@M(!en(25p{o*l_9t3nNkn5IXZ$cs=teeN>$6g}gLt!W32X;64&YdI@BKQ3UZfPXE z32r%biu7n>{1oFMNT`&#s|C4=v=3y`7hAs{xQz=7Geb5T2yQumbxdw}4sn%q42<4` z>cY*Tnk~$PD1zO&{r8oaor|!{^?St`skq%9i^EoVB#?S9b_0Oma zw@{HcM(;;_yua$%){v9HP1p(HMpQFZs}A$*Aoiy|TWH+UI=73}^{5=d8Hmzy4{;7$ zyFV1GYSrfb?)=9ozjW9+@m#t)&iQaGb43te%)U=>p)T6WndThCPMecjwm1I4Spw#Y zpqI_7$IyN1lRE;=D?^i*xyc~Pg!s>>n2SoqTr>pXAL#-fg>$5C-T(jq07*qoM6N<$ Eg3LZKEC2ui diff --git a/web/src/js/view/newhome/images/u509.png b/web/src/js/view/newhome/images/u509.png deleted file mode 100644 index 986e39719427393967ecf944b43164db875a9042..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 833 zcmV-H1HSx;P)500001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0@g`HK~z{ry_YX+ z6hRb+?=BT5Dk=~a2uMyKAVDHdAP^Om6%`dtAfWYI+Nt+-_4!*bZ>(cJd-0YCs`;wP8e|~S?yWQEn*~b4e91hq2cwqdQ zB$I=rN6PPGTCyZs@<~ugr`c=<6H?3-HIoPyV+)dW2kU7lhe9r?8KNVf!#YdY>*PWS z=n{B<&#m&&~Of8wtiPB{UGXKhc2XE$n(SUDRoA1&-B?3GiuigdF-}7c0EV2m{;&0QwW9%blaaDPwJaMS}35$=! zE;DvjAsO`TY22112%7f_@q=a-(Hypl#oi;OxAIw#EIVZw)>y$^$Jz?Ze$5tE`Q3sx zzVX1;RY(-H``BjFI*P9Z@@uVD>yx@c(Afq(biHaM{cDrpxJn_0ZBX=;w5KE$17GB; zlB7>9rgSujkfcxEGjN$(@J;O?EZfG8&`xP6N{fJ}*l+ctpna(3NYJgP6oUTWEu~{8 zyLqffdn9NU6y^oVEi@-i?Z+Nv>>kaVSblITfhhWCiKdS`cMhiCW_$yS6*5pr9K?%? zi-L9+vs2vw8(G9D=vI{~4&oPzs|D8I!^IDA2-jRly^v=|Dg7X@Kgvp%dK}mfSL%%7 zOYe5d<2VNH%9o*7d%W}SrMe;4l2ZFY6Z&qlvHSQ+n;YE+tcQ7j9OKoVD73{d%3WOk zS!xTp89&T#NNQ`@q3x}k$>wZNE^E3P1lTS6jM)*i_;TxFL5NwAG=rfj#`>5YqUJR` z9$0)f%Nl@$bCOO55(bZ|%w3c$iPZDVS>DN?gIZp48vL$q0*%IB^zX7KjaOb000000 LNkvXXu0mjfjuv?x diff --git a/web/src/js/view/newhome/images/u513.png b/web/src/js/view/newhome/images/u513.png deleted file mode 100644 index 97905ddd3b40ad5b200571701bf1cd47412692be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1009 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1BOXNK~z{ry_i2p z)ln43eJ=+GA&DRdA%`F-2Zx4+HwXziIM^6CI5@Nj4Gl&PZ4C|%jkY&5XcQD=ROGHw zkfD&FP|+KT0tG|+eD1ry*L%J9#6R!%`@;8~bMHO(ocsITd+xpOmuuMvySux+h^|~N z*NN=j+uJ*XR8J_rCdBR=aveK$xun5?K&Jr$-iM#ij|F^ez!^9g-PZ!UVGI^aU7C;R zdpL$Gfy(JpbNV3GBSh;7ekPcU$vB48L97eJJe6Yvs}#<~`b{WLy-zk+2G zfUhn147ERo2{4a`^7;JJSPsCb4N*W|MS4*5@p_U&VPDXvhPB?|lh=qXoN?yP*il?LPv4O94 ze2&0bV}xL!?#@M(qhEl&u8&Ga>C^l`ZwUHzKo?IRJP&E2Y)3x z>p5=(d=&kefSH1aoem>ViFK)iSm8Vlfdz$3Zy+_7JsJm~`8&wGxj2pt{Ft8e@G+@s z%9i2ca-SZDE3vK&I+}NvP+h4PVK+3NWhKmG^Vgf@GE!e=!aA}F`17`UPsP`;1HDaB!3zGwwrD+a zld?8m_}xa`?M_0cCD3|gT^M*4gX;Tk%3zR72EL5$0&6c-rwf8^6YF|X=wSe>$W#$y z6hhDhR5(wgG``cQnZV}<#3(G!xu=tdeAT}?3{9&ccm=vpJOmCj75Fo!Jw(>%^9DJG ztlA^=?;P)-KcMk8Y-2V2x1SFuZZ^k{|t=4UJh`u#fXJ7S3y@vmR zGw00#NjH|TfdKpZhTK3p4(My!iJn5q6vTXJboW#b=S)B>_w7=KpcvfEygd2MhQ5t~ zT6->7N#hvw-$eN;dQ|8GdS$*ru_|E0&rKS_0o3rh3H>a3@|nqePA>H2&rOp0&(Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0Y*tgK~z{r?UkWU z1TheXx2w*QAUFkr1OyU+L?U?v9sojjDH z$b`u}(Hv^pa7fY;HQLZN38lT!+bHH{u;7Je7`hNV$}a+b%MoZuF^f`GMZ#59gP3nh~Z!Ax?ams zx`|u@2jX=XMqukEPi1B-pM%@4Xc6+S(1nI^q_ipI6QNy`{J$fp7`Z7%ZiPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1LR3WK~z{ry_u~~ z96=a|xyuOz0)aq~Z~}p>KwMG;q5{DmfS|4dfkYrGnjnw}L`9n*sHsAYQXaWfh^!d%a$Fa=p-0t4Tle{;(@7L_j&dkls)kZ3EdwbhNTD4kD?7AMAc6cWJPnSE783=#T4{&NSqte3{!_>nl5Ab< z>lP9R2MvhaB-k{HADMe;h;5Q1cfes&OV68o77Ut7Qo$c6#?8Gl>Rk( zY9x=sQ%M_(bC@a#ZkjVMeMG=QosX9JWwIV>9Kg5Iig+kc*AE)%uif5fMh_UgVmTA^%Wj8-wh0e$ zEja40GyJnM3ZqUdnCQqemnsBx(nt+GVDKt2j8j+Y*W)ohu`kvOu{U`deL#UR+Bc0W zE0d6;(7r={Y81P@&q<9}^&I1-DefTXX}w;L&QI91+F0~=aqzh!?|UTH`7_|FCDwtz z>wx~X`qK&*0qBdZaQgstZCkY&)OdQzS$~@aqc${CmSbR0mDY#RMKXH-mbf@DT?X`9 z&S8L1$EsDA0lk)aev{9QcKiY8lZ(z?A-5I^d4~ZT=H?u=c+^rm0KK*W{hm@Bx4BBkx zZnCi*B9%urDb(kpueA;KWpj^%Lv&QN!LHLOEz`?vq%@VRB6$PCfqmOT(%`7Gk|g+C zBHB7WL4tiOx(Q@nl_FiwYw*zyuUHqtQJZ+Tzby*>>O05C5mM>^34c9YxLNN8fjYG8 zdhpW=;-bF#nS_#DCC^wlAU`tBZ*TFzC2{OX%)$g!`k zIK*fKZy=@4rfXJ~hKd#_ba1I%p??-bUNGq8$zZ2iqPK>+Gi)X5+Nfa{{gT$ Vp7osyv<3hG002ovPDHLkV1j#G23r6C diff --git a/web/src/js/view/newhome/images/u620.png b/web/src/js/view/newhome/images/u620.png deleted file mode 100644 index 05c87dec578e8d99c342cf438d99f7b33e18058d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1226 zcmV;*1U37KP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1Yb!+K~!i%-I*^; z98nO);etRQ5C{ZgA`qCSBozpnASx;l6*Os^3eq4d zDiAb5K!T`1LenNRp$SdercG#|zwhnr-rnBs-tOJrLHZ>hH*em&*_plfXWr4(E?iz- z4qjYbJcbAGBV2_e)_wg!u;cJ0JSUktpx=VG&HQ?S_<9L$79M!vHU_qbZ~?L3+*}<9 zVwhl7;Hir)1a#-{4Pph3A+N*Vt}_I5Kj2fuo94E2;K60M3G1d0x)Z3iF=XZe=pKMe z^c^|l2++UhW75pq3m!HN;}Y0|Gl;!rnh0!q;FJYk1NnvvX4*dRkk9r^|Djsg5nEoY_~?b2a^Y`!!n%uxoO{oxLT?Z1jgFdGW-wfv zh0d2V&sz;Tn@AW0q&YtYdu&K7=%2(kcC!fK>JsrmfZCOo;D8O)*go|0@K82Upm!C3 zHHE8B#0P%!%+uRaT5yvvA;B>t)z$ zIgF!gSngy7&iYw|i!ip(%YkKcSp)p){;~n%D&yEqAs28^R|B<(AQ5EUUuNK**Odc|=wnL{ z+JjKVUQiJyK{hb1{6B>&h~f3&fG)9=LFZ39uX>;{0_(Czm-*&~O%Jwr;f@=e0obY} znMG{4ps^c*NjFiwpt6iMOy@vbcjqh@W<-q!XT z{YB&0_|vuWL#Op8_}#T?A)S1Gajl%NgVe=G{C}O&Lq%D}f-H~VB4Va*23y_ZGi?Ca z1Pj}Srvf|ea&s_t0}v7u@u9%rI%3^nh)xgC9e&ptN1(ALCITD%csGYwceO>Y^_x~X z2b(~{M8aU;4piV;d=0lzs4X`W7;^>{w1U3_x2&rM=z~L&&tR9$l}H+Jsz7vy54KU{ z%!xDtzIWj?VsHc$nh4Gkw^4L0C4yf~YpuJoxvT;D))O%&soN<1O(%l?H9k^ntZ*W& zl<~)GhaXHX9Qb|t8r|o&$nt2fX z9E9u=@YGeHQ{|u+SG``)NDL+p7F=oqd<1U|dBVnIg?>XzOaP{D&va%=h<;s&8YU10 zeVGz6KQ%ztIDsfI&if6eCJ+U-nZKc?5{QDqsR`vxAPUANCR9iQQQ*u^NcR*~xVqLh ooj?@$QbO;bf>(u`BZ022f9^L#hPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0W?WOK~z{r?U%7? z0znXl_rxNFjc|p9g}n)+wDbWiEG%sE4npu9gx~`N;v3j$X<=buZ>dEdAfUxT;MQ;4 zK`n$33^<1UV3~jCmb+nwo#7G>&M*bFW-${Wg|6TC%q%{i!!qhldkysFkhQMHlcFcV z>%FO4Oeh;ng$zCf&mFXx$iF9!x@$2LAcf3WA1wL(JRv0(ZanI~F*Q9dqwXy{u`}vs zG-qkj2hbyxW=i}_vX0XO-B4-jw{uM9hS*28ujs1yW1G1S=k|&Txr!Cv|9t=e002ov JPDHLkV1jk)u)_cV diff --git a/web/src/js/view/newhome/images/u82.svg b/web/src/js/view/newhome/images/u82.svg deleted file mode 100644 index e67551d38..000000000 --- a/web/src/js/view/newhome/images/u82.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/web/src/js/view/newhome/index.vue b/web/src/js/view/newhome/index.vue deleted file mode 100644 index 09d9d0d42..000000000 --- a/web/src/js/view/newhome/index.vue +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/web/src/js/view/newhome/module/caseAndIntroduction/index.js b/web/src/js/view/newhome/module/caseAndIntroduction/index.js deleted file mode 100644 index 9ea52ad7e..000000000 --- a/web/src/js/view/newhome/module/caseAndIntroduction/index.js +++ /dev/null @@ -1,10 +0,0 @@ -export default { - name: 'CaseAndIntroduction', - events: [], - dispatchs: { - }, - data: { - API_PATH: process.env.VUE_APP_MN_CONFIG_PREFIX || `http://${window.location.host}/api/rest_j/v1/`, - }, - component: () => import('./index.vue'), -}; \ No newline at end of file diff --git a/web/src/js/view/newhome/module/caseAndIntroduction/index.vue b/web/src/js/view/newhome/module/caseAndIntroduction/index.vue deleted file mode 100644 index 6a84b0813..000000000 --- a/web/src/js/view/newhome/module/caseAndIntroduction/index.vue +++ /dev/null @@ -1,227 +0,0 @@ - - - - diff --git a/web/src/js/view/newhome/module/workspace/index.js b/web/src/js/view/newhome/module/workspace/index.js deleted file mode 100644 index 01be3f453..000000000 --- a/web/src/js/view/newhome/module/workspace/index.js +++ /dev/null @@ -1,10 +0,0 @@ -export default { - name: 'Workspace', - events: [], - dispatchs: { - }, - data: { - API_PATH: process.env.VUE_APP_MN_CONFIG_PREFIX || `http://${window.location.host}/api/rest_j/v1/`, - }, - component: () => import('./index.vue'), -}; \ No newline at end of file diff --git a/web/src/js/view/newhome/module/workspace/index.scss b/web/src/js/view/newhome/module/workspace/index.scss deleted file mode 100644 index 9987fbef0..000000000 --- a/web/src/js/view/newhome/module/workspace/index.scss +++ /dev/null @@ -1,147 +0,0 @@ -@import '../../../assets/styles/variables.scss'; - -.page-bgc { - background-color: #f7f7f7; - background: #fff; - - .page-bgc-header { - padding: 10px 25px 0; - } - - .header-info { - padding: 10px 0 10px 20px; - - p { - line-height: 24px; - } - } - - .workspace-main { - padding: 10px 25px; - display: flex; - justify-content: flex-start; - align-items: flex-start; - - .left { - flex: 1; - box-shadow: 0 1px 6px rgba(0, 0, 0, .2); - border-color: #eee; - min-height: 500px; - - .workspace-type-header { - padding: 10px 20px 0; - line-height: 30px; - display: flex; - justify-content: flex-start; - align-items: center; - - .workspace-type-header-label { - font-size: 14px; - display: inline-block; - margin: 0 5px; - font-weight: 900; - } - } - - .workspace-create-search { - padding: 0 35px; - display: flex; - justify-content: flex-start; - align-items: center; - margin: 10px 0 50px 0; - - .workspace-create { - flex-basis: 200px; - display: flex; - justify-content: flex-start; - align-items: center; - padding: 15px 10px; - &:hover { - box-shadow: 0 2px 12px 0 rgba(0,0,0,.2); - border-radius: 4px; - } - .workspace-create-text { - margin-left: 10px; - cursor: pointer; - } - } - - .header-search { - flex: 50%; - } - } - - .item-header { - font-size: 14px; - margin: 20px 25px 10px 25px; - font-weight: bold; - padding-left: 5px; - border-left: 3px solid $primary-color; - } - - .workspace-content { - .content-item { - .workspace-item { - cursor: pointer; - height: 180px; - margin: 15px; - box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.2); - background: #fff; - padding: 10px; - position: relative; - background: url("../../../assets/images/workspace.png") center center no-repeat; - background-size: cover; - min-width: 222px; - .name { - display: block; - font-size: 16px; - font-weight: 600; - color: white; - } - - .desc { - width: 100%; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 2; - overflow: hidden; - text-overflow: ellipsis; - word-break: break-all; - color: white; - } - - .lable-list { - position: absolute; - left: 10px; - bottom: 30px; - display: flex; - justify-content: flex-start; - align-items: flex-start; - width: 100%; - .item { - display: inline-block; - font-size: 10px; - padding: .3em .9em; - margin: 0 .5em .5em 0; - white-space: nowrap; - background-color: #f1f8ff; - border-radius: 3px; - color: #0366d6; - overflow: hidden; - text-overflow: ellipsis; - max-width: 31%; - } - } - - .editor { - position: absolute; - right: 10px; - bottom: 10px; - } - } - } - } - } - } - -} diff --git a/web/src/js/view/newhome/module/workspace/index.vue b/web/src/js/view/newhome/module/workspace/index.vue deleted file mode 100644 index 953c1f68a..000000000 --- a/web/src/js/view/newhome/module/workspace/index.vue +++ /dev/null @@ -1,157 +0,0 @@ - - - diff --git a/web/src/js/view/newhome/module/workspace/module/workspaceForm.vue b/web/src/js/view/newhome/module/workspace/module/workspaceForm.vue deleted file mode 100644 index e297a552a..000000000 --- a/web/src/js/view/newhome/module/workspace/module/workspaceForm.vue +++ /dev/null @@ -1,168 +0,0 @@ - - diff --git a/web/src/js/view/newhome/tips.md b/web/src/js/view/newhome/tips.md deleted file mode 100644 index 99a8d9821..000000000 --- a/web/src/js/view/newhome/tips.md +++ /dev/null @@ -1,12 +0,0 @@ -#### 开发注意 - -1. 自定义首页就在idnex.vue文件下开发,需要的工作空间和案例、快速入门在./module下,需要自行调试哦!!! - -2. 新增其他页面在view下面新建文件夹,页面对应的路由在:src\js\service\router.js下自行配置 - -3. 开发过程中可以使用:src\js\component下的公共组件,尽量不要修改,造成不通用,也可以新增组件 - -4. 目前开源的还没工作空间概念,所以对应的接口服务还没有,需要后台上传对应服务代码 - -5. 开发过程有问题随时联系 ![扫码加入](images/QR.png) - -- Gitee From 159588d2a6b97f20af137dd199b51b214dc0358c Mon Sep 17 00:00:00 2001 From: zwx-master <1208247854@qq.com> Date: Wed, 24 Jun 2020 11:06:26 +0800 Subject: [PATCH 119/238] readOnly value modification --- web/package.json | 2 +- web/src/js/component/editor/editor.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/package.json b/web/package.json index 95693d327..6d748244c 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "dataspherestudio", - "version": "0.5.0", + "version": "0.8.0", "private": true, "scripts": { "serve": "vue-cli-service serve", diff --git a/web/src/js/component/editor/editor.vue b/web/src/js/component/editor/editor.vue index dad5484c9..79ae4e638 100644 --- a/web/src/js/component/editor/editor.vue +++ b/web/src/js/component/editor/editor.vue @@ -91,7 +91,7 @@ export default { if (newValue == this.getValue()) { return; } - let readOnly = this.editor.getRawOptions().readOnly; + let readOnly = this.currentConfig.readOnly; if (readOnly) { // editor.setValue 和 model.setValue 都会丢失撤销栈 this.editor.setValue(newValue); -- Gitee From 322288cf1e4281568a1eeeeee12293568ed21673 Mon Sep 17 00:00:00 2001 From: luxiaolong Date: Mon, 22 Jun 2020 18:19:31 +0800 Subject: [PATCH 120/238] add workspace featrue --- web/src/assets/iconfont/font-dws-icon.svg | 172 ++++---- web/src/assets/iconfont/font-dws-icon.ttf | Bin 24364 -> 24808 bytes web/src/assets/iconfont/font-dws-icon.woff | Bin 24440 -> 24884 bytes web/src/assets/styles/iconfonts.scss | 134 +++++-- web/src/assets/styles/workspace.scss | 272 ++++++++----- web/src/commonData/i18n/common/zh.json | 22 +- web/src/js/module/header/index.scss | 377 ++++++++++-------- web/src/js/module/header/index.vue | 30 +- web/src/js/module/header/workspaceMenu.vue | 74 ++++ web/src/js/module/project/feature.vue | 1 + web/src/js/service/mixin.js | 2 +- web/src/js/service/router.js | 9 + web/src/js/view/login/index.vue | 2 +- .../view/newhome/module/workspace/index.scss | 12 +- web/src/js/view/workspace/index.vue | 310 ++++++++++++-- web/vue.config.js | 20 +- 16 files changed, 1009 insertions(+), 428 deletions(-) mode change 100644 => 100755 web/src/assets/iconfont/font-dws-icon.svg mode change 100644 => 100755 web/src/assets/iconfont/font-dws-icon.ttf mode change 100644 => 100755 web/src/assets/iconfont/font-dws-icon.woff create mode 100644 web/src/js/module/header/workspaceMenu.vue diff --git a/web/src/assets/iconfont/font-dws-icon.svg b/web/src/assets/iconfont/font-dws-icon.svg old mode 100644 new mode 100755 index 776dd6f8c..2b1c8c606 --- a/web/src/assets/iconfont/font-dws-icon.svg +++ b/web/src/assets/iconfont/font-dws-icon.svg @@ -1,85 +1,103 @@ -Generated by IcoMoon + + + +{ + "fontFamily": "font-dws-icon", + "description": "Font generated by IcoMoon.", + "majorVersion": 1, + "minorVersion": 0, + "version": "Version 1.0", + "fontId": "font-dws-icon", + "psName": "font-dws-icon", + "subFamily": "Regular", + "fullName": "font-dws-icon" +} + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/src/assets/iconfont/font-dws-icon.ttf b/web/src/assets/iconfont/font-dws-icon.ttf old mode 100644 new mode 100755 index ad3754489b4f4908f51cb9dcf7cbd796c826e206..ddfdc404d24a2ba5f5d5f49320bd116c45aecccf GIT binary patch delta 1102 zcmb7DUr19?82`R|u6J&-%{jZ)%s8MV>-3mpV&%!T94I3 zP}h14qo9`}V=rPQOM1|#2zm)B=pn?}O9YWUwDsL}2NFHl;OzVT`wr(^&Ub$SSD#@L z5CBTxA~0w=+SlmRm#NN@@`RQ@7!JhdU!B(h;CABEqk(vgYANwqs>P!d7eZ~(dCKA( zz^M;oBZ1-i*0*~B2Byh(kC9-QE$t=#lK76XaAN96bLkD@U#aK7L^RkH@SZs#0Qg)K zxEl^k#lVje@pr^)BZ2Tp=Yx}j#Mi0ebu1cB&_U_vUy^-be9N`8ms`_c$F`0sl1y|u z1{%6m?Ml&#Z8ewKnrY4)${b$Ptm$*Vayhw~Jji>PF=bjaJ+ddoP%IV?ie1!>l3}Pa zbsOiauv;3a>5=Z$#5sUeW$mpJ^+R|JOYjlCNsG2eSTDsJ7MU&^l05b|DYe6DPv+7* zur$=ufz1Y&#fEjl7K6D?sKRow*=#5m+tBIWV=z129q6*KPuUrxHmx;gXS7D67X5jG zej;3FzG(jykZ*y&q61YrR25VQS}lSeby!i26$O!e zL9D@Q^iWShBwuvzLoZq#$bMv((Zlh`m`YNWshPlKm$S>9z|>_VForyb9uhVrlB7`2 zhREf=1={3)ca?9OUrm84qeJ@k?@+?a-vHiMbkp-F)LdFC9q)HyZ|YKiI~L0kTAcKJ zU`ErhZja=5>6K0o?n-LOllLSWRPb5B476}l!93xg3NE4P?WU6-xJ}2TxMtx4NF}!Z5$@z4y(&d9(gf+cAVkdR8pw}wggVZhVTMDIfXK#I}Kc>D1 zOgD>peI~Lp-2hGxGe2Hrp!ZQQK|MpgyJ*zsj*SK-^<{cuB{Mgn_tpk)0IAn3Xc_uk z1!=*8Gqxd8){XqlDc?`(CJmP=X06Uf`DME7JQVfN)fY!yR{WYc++Sp98@p5B;jJQT z?zQN8#|l}a)}$4eDG>^HHaZ=M&eyQI{gc+E1vI~=Y6=ZPzRPOuMX}T`CS_@0O7zJm z12xgzjz(?=d=IdMH~5I}@_lqsHiuuiew~uXN0tTJp*@2m5&jn&cULDeJ+U7MsJ6rh zYvKIAT|P}66p8k?R7}XRbj$7zNXV7+(7cyqE5HRWvJNZcafelM!(lgHs?T8$<8g=m z2xGy%hU#Oao0-4tA{QK1$VVJj$ro%sK!ck@<0Su>JxnAW_G1ipW^<-tnq|x)2NMRD siL%_0-F0Hq%%;I)zR)P?RUVvYHw~1aqxxT^e49zyqf_jske{>O--B$JRR910 diff --git a/web/src/assets/iconfont/font-dws-icon.woff b/web/src/assets/iconfont/font-dws-icon.woff old mode 100644 new mode 100755 index 978571427d8bf8f0e5f9b0c3bf62fa6516b907ea..efd6d59b70bbc7e4a718d21dc4967ad3a4a00eec GIT binary patch delta 1212 zcmb7DO-vI(6n<}K+0sJ)DDGktehLZ)XjQ<1fQX5LK@9<;CL)wgfkK29DF~iQ;z@60 z)uX}a!Ha*XCsZVy#6)AFH#L%I2*r5O7%|b-H|v7L7=xR9JKucodvE4VW>#kK-W8e2f?qtF=t5 z7nbeXA*^ku6~PS-U|^yC3l`HBOP5lKoJ2+9K;q!CW!awkkxG$=mRbZoh6#6~CegeW z!_+&sxcRM;sbnY?MO2u)U*1dg_~|LyP(X}-#OYjY(r)B8YoGI@0zf=ea3#Zh8}7qn zcmtm_TiIPK(jJw~FHaR_oQZ8o86&`1{ zT#M!YolZ}=e>YYZvxVf8%Q|ayC8w+|mleD833ky$XwV1i-weDp1R*uYl57T!0Bo(s z9cH9otRAcU#oN$_CL5YoRUeiVOLnxOl84HwNO4Kd$2_c}oK=zHvVRZOV~G#h*W^4_ z2_iCP(o9)qCJD*;gB{DrRxCJUw!x~0a|h`I$2)utj;E7T}>u#`kt$*G~F$&$uRA)77vLn8|H zP(0L=45A*C9t3Y%Ne|M4hhDtq;6;#%3c&?0f`TCF_RYHWVi!KO z*`XzUY6=YWdtdBglj211N6UCaRImWAoRU)rLh4+M>q{4p|?RtZbH1jV{B9i1u-p{TC zoHW1AE~UkZ4nu*25OqN72D_u*T<3^0?o2yrx97SPr)9eEeCEWRNhjs`%>5ddkA717 z)u{z?UHjlGu{^n$g#dtugvw`-K_ADBHiA}u2NBrO?60dnDu@%^v;Sa|; z4DI=|BV(FarT5~?)%?NaFGOWA#Rq5g_TI?l+(o9hler}0cjwl`W&xd_$)8^CBl0c} z0ra8ZvqU`MvrOFdIY<{A^EpI*+UE%3Sfw^FIZVy~MgDSt*z{Q6iUky5!y?(Ja + + +
{ + api.fetch('/mock/dss/getBaseInfo', 'get').then((rst) => { if (!isEmpty(rst)) { this.userName = rst.userInfo.basic.username; storage.set('baseInfo', rst); @@ -162,6 +171,12 @@ export default { this.$emit('set-init'); } }); + + api.fetch(`/mock/dss/workspaces`, 'get').then(rst=>{ + if (!isEmpty(rst)) { + this.workspaces = rst.workspaces; + } + }) }, goto(name) { this.$router.push({ @@ -247,6 +262,17 @@ export default { setTimeout(() => { newTab.location.href = url; }, 500); + }, + goSpaceHome(){ + console.log('workspaceId', this.$route.query.workspaceId) + this.$router.push({path: '/home',query: Object.assign({}, this.$route.query)}); + }, + goConsole(){ + console.log('workspaceId', this.$route.query.workspaceId) + this.$router.push({path: '/console',query: Object.assign({}, this.$route.query)}); + }, + changeWorkspace(data){ + this.$router.push({path: '/workspace',query: Object.assign({}, this.$route.query, {workspaceId: data.id})}); } }, }; diff --git a/web/src/js/module/header/workspaceMenu.vue b/web/src/js/module/header/workspaceMenu.vue new file mode 100644 index 000000000..f497c31c1 --- /dev/null +++ b/web/src/js/module/header/workspaceMenu.vue @@ -0,0 +1,74 @@ + + + + + \ No newline at end of file diff --git a/web/src/js/module/project/feature.vue b/web/src/js/module/project/feature.vue index 437e04b82..989654ee5 100644 --- a/web/src/js/module/project/feature.vue +++ b/web/src/js/module/project/feature.vue @@ -72,6 +72,7 @@ export default { }, methods: { goto(type) { + console.log('--->', type) this.gotoCommonIframe(type); }, createProject() { diff --git a/web/src/js/service/mixin.js b/web/src/js/service/mixin.js index 4ca8713dc..e65a44b4a 100644 --- a/web/src/js/service/mixin.js +++ b/web/src/js/service/mixin.js @@ -142,7 +142,7 @@ export default { localStorage.removeItem('appJointProjectId') url = info.homepageUrl } - window.console.log(url, 'url') + window.console.log(url, 'url', info) // 如果没有提示用户功能暂未开发 if (Object.keys(info).length === 0) { this.$Message.warning(this.$t('message.constants.warning.comingSoon')); diff --git a/web/src/js/service/router.js b/web/src/js/service/router.js index 194890ba6..6a6697cc7 100644 --- a/web/src/js/service/router.js +++ b/web/src/js/service/router.js @@ -74,6 +74,15 @@ const router = new VueRouter({ }, component: () => import('../view/workspace/index.vue'), }, + { + path: 'workspace1', + name: 'workspace1', + meta: { + title: 'Workspace1', + publicPage: true, + }, + component: () => import('../view/newhome/module/workspace/index.vue'), + }, { path: 'commonIframe', name: 'commonIframe', diff --git a/web/src/js/view/login/index.vue b/web/src/js/view/login/index.vue index 8b6808293..0c4d1678b 100644 --- a/web/src/js/view/login/index.vue +++ b/web/src/js/view/login/index.vue @@ -86,7 +86,7 @@ export default { }, methods: { getIfLogin() { - api.fetch('/dss/getBaseInfo', 'get').then(() => { + api.fetch('/mock/dss/getBaseInfo', 'get').then(() => { this.$router.push('/'); }).catch(() => { this.clearSession(); diff --git a/web/src/js/view/newhome/module/workspace/index.scss b/web/src/js/view/newhome/module/workspace/index.scss index 9987fbef0..45d914b50 100644 --- a/web/src/js/view/newhome/module/workspace/index.scss +++ b/web/src/js/view/newhome/module/workspace/index.scss @@ -1,4 +1,4 @@ -@import '../../../assets/styles/variables.scss'; +@import '../../../../../assets/styles/variables.scss'; .page-bgc { background-color: #f7f7f7; @@ -48,7 +48,7 @@ display: flex; justify-content: flex-start; align-items: center; - margin: 10px 0 50px 0; + margin: 10px 0 50px; .workspace-create { flex-basis: 200px; @@ -56,10 +56,12 @@ justify-content: flex-start; align-items: center; padding: 15px 10px; + &:hover { box-shadow: 0 2px 12px 0 rgba(0,0,0,.2); border-radius: 4px; } + .workspace-create-text { margin-left: 10px; cursor: pointer; @@ -73,7 +75,7 @@ .item-header { font-size: 14px; - margin: 20px 25px 10px 25px; + margin: 20px 25px 10px; font-weight: bold; padding-left: 5px; border-left: 3px solid $primary-color; @@ -89,9 +91,10 @@ background: #fff; padding: 10px; position: relative; - background: url("../../../assets/images/workspace.png") center center no-repeat; + // background: url("../../../../../assets/images/workspace.png") center center no-repeat; background-size: cover; min-width: 222px; + .name { display: block; font-size: 16px; @@ -118,6 +121,7 @@ justify-content: flex-start; align-items: flex-start; width: 100%; + .item { display: inline-block; font-size: 10px; diff --git a/web/src/js/view/workspace/index.vue b/web/src/js/view/workspace/index.vue index 1fdf70ddf..5c0635549 100644 --- a/web/src/js/view/workspace/index.vue +++ b/web/src/js/view/workspace/index.vue @@ -2,77 +2,317 @@
-

{{$t('message.project.infoHeader')}}

-

{{$t('message.project.infoBodyFirstRow')}}

-

{{$t('message.project.infoBodySecondRow')}}

+

{{$t('message.workSpace.home.welcome', {text: workspaceData.name})}}

+

{{workspaceData.description}}

+ +
+

- {{this.$t('message.console.sideNavList.function.name')}} + {{this.$t('message.console.sideNavList.function.name')}}

-
- +
+
+ + {{$t('message.workSpace.home.enter', {text: item.title})}} +
- - 进入脚本开发 +
+ +
+ +
+ +
+
+ +
+ +

- {{this.$t('message.console.sideNavList.function.name')}} + {{adminApps.title}}

-
- - 进入脚本开发 +
+ + {{item.title}}
-
-
- - - -

- {{this.$t('message.console.sideNavList.function.name')}} -

-
-
- - 进入脚本开发 +
+
+ + +
+ +
+
+ +
+ + {{item.title}} + {{tag}} +
+ + +

{{item.description}}

+
+ +
+ + {{$t('message.workSpace.home.running')}} +
+
+ + {{$t('message.workSpace.home.stop')}} +
+ +
+ +
+ +
-
- +
+ + +
+ + +
+ - 标签二的内容 - 标签三的内容 - +
- +
+ +
+ + + - + + + +
+ +
+ + +
+ +
- - \ No newline at end of file + + + \ No newline at end of file diff --git a/web/vue.config.js b/web/vue.config.js index 78edce85e..41f201bdd 100644 --- a/web/vue.config.js +++ b/web/vue.config.js @@ -41,8 +41,24 @@ module.exports = { errors: true }, proxy: { //代理转发 + + '^/api/rest_j/v1/mock': { + target: 'http://rap2.taobao.org:38080/app/mock/162239', //后端服务地址 + ws: true, + changeOrigin: true, + pathRewrite: { + '^/api/rest_j/v1/mock': '/api/rest_j/v1' + }, + logLevel: "debug" + }, + // '^/ws/api': { //websocket + // target: 'ws://127.0.0.1:8089', + // ws: true, + // secure: false, + // // logLevel: 'debug', + // }, '^/api/rest_j/v1': { - target: 'http://127.0.0.1:8089', //后端服务地址 + target: 'http://42.123.106.20:8088', //后端服务地址 ws: true, changeOrigin: true, pathRewrite: { @@ -50,7 +66,7 @@ module.exports = { } }, '^/ws/api': { //websocket - target: 'ws://127.0.0.1:8089', + target: 'ws://42.123.106.20:8088', ws: true, secure: false, // logLevel: 'debug', -- Gitee From 20f5eb0a9372c25878624929f2969724e1914e64 Mon Sep 17 00:00:00 2001 From: luxiaolong Date: Sat, 27 Jun 2020 14:47:44 +0800 Subject: [PATCH 121/238] add devserve config & clear debug --- web/src/js/view/login/index.vue | 2 +- web/src/js/view/workspace/index.vue | 17 +++++++---------- web/vue.config.js | 23 +++-------------------- 3 files changed, 11 insertions(+), 31 deletions(-) diff --git a/web/src/js/view/login/index.vue b/web/src/js/view/login/index.vue index 0c4d1678b..8b6808293 100644 --- a/web/src/js/view/login/index.vue +++ b/web/src/js/view/login/index.vue @@ -86,7 +86,7 @@ export default { }, methods: { getIfLogin() { - api.fetch('/mock/dss/getBaseInfo', 'get').then(() => { + api.fetch('/dss/getBaseInfo', 'get').then(() => { this.$router.push('/'); }).catch(() => { this.clearSession(); diff --git a/web/src/js/view/workspace/index.vue b/web/src/js/view/workspace/index.vue index 5c0635549..f8bd8592b 100644 --- a/web/src/js/view/workspace/index.vue +++ b/web/src/js/view/workspace/index.vue @@ -190,24 +190,24 @@ export default { methods: { init(){ - api.fetch(`/mock/dss/workspaces/${this.workspaceId}`, 'get').then(data=>{ + api.fetch(`/dss/workspaces/${this.workspaceId}`, 'get').then(data=>{ this.workspaceData = data; }) - api.fetch(`/mock/dss/workspaces/${this.workspaceId}/favorites`, 'get').then(data=>{ + api.fetch(`/dss/workspaces/${this.workspaceId}/favorites`, 'get').then(data=>{ this.favoriteApps = data; }) - api.fetch(`/mock/dss/workspaces/${this.workspaceId}/managements`, 'get').then(data=>{ + api.fetch(`/dss/workspaces/${this.workspaceId}/managements`, 'get').then(data=>{ this.adminApps = data.managements ? data.managements[0]: []; }) - api.fetch(`/mock/dss/workspaces/${this.workspaceId}/applications`, 'get').then(data=>{ + api.fetch(`/dss/workspaces/${this.workspaceId}/applications`, 'get').then(data=>{ this.applications = data.applications; }) }, deleteFavoriteApp(favouritesId, index){ - api.fetch(`/mock/dss/workspaces/${this.workspaceId}/favorites`, 'delete').then(data=>{ + api.fetch(`/dss/workspaces/${this.workspaceId}/favorites`, 'delete').then(data=>{ this.favoriteApps.splice(index, 1); }) }, @@ -217,8 +217,7 @@ export default { if (valid) { // this.addAppLoading = true; this.show = false; - api.fetch(`/mock/dss/workspaces/${this.workspaceId}/favorites`, {applicationId: this.formDynamic.selectApp},'post').then(data=>{ - console.log('添加成功') + api.fetch(`/dss/workspaces/${this.workspaceId}/favorites`, {applicationId: this.formDynamic.selectApp},'post').then(data=>{ const app = this.findAppByApplicationId(this.formDynamic.selectApp) this.favoriteApps.push({ ...app, @@ -254,7 +253,7 @@ export default { } return false; }) - this.searchResult = [{title: '搜索结果', appInstances: [...this.searchResult]}]; + this.searchResult = [{title: '', appInstances: [...this.searchResult]}]; this.search = true; }else{ this.search = false; @@ -277,7 +276,6 @@ export default { return this.applications.map(item=>({title: item.title, id: item.id})) }, apps: function(){ - console.log('this.formDynamic.selectType', this.formDynamic.selectType); if(this.formDynamic.selectType){ const arr = this.applications.filter(item=>item.id==this.formDynamic.selectType); return arr[0].appInstances; @@ -286,7 +284,6 @@ export default { }, tabsApplication: function(){ if(this.search){ - console.log('dsadad', this.searchResult, this.applications) return this.searchResult; } return this.applications; diff --git a/web/vue.config.js b/web/vue.config.js index 41f201bdd..9b48f0852 100644 --- a/web/vue.config.js +++ b/web/vue.config.js @@ -33,7 +33,7 @@ module.exports = { publicPath: './', outputDir: 'dist/dist', devServer: { - port: 8091, + port: 8080, open: true, disableHostCheck: true, overlay: { @@ -41,24 +41,8 @@ module.exports = { errors: true }, proxy: { //代理转发 - - '^/api/rest_j/v1/mock': { - target: 'http://rap2.taobao.org:38080/app/mock/162239', //后端服务地址 - ws: true, - changeOrigin: true, - pathRewrite: { - '^/api/rest_j/v1/mock': '/api/rest_j/v1' - }, - logLevel: "debug" - }, - // '^/ws/api': { //websocket - // target: 'ws://127.0.0.1:8089', - // ws: true, - // secure: false, - // // logLevel: 'debug', - // }, '^/api/rest_j/v1': { - target: 'http://42.123.106.20:8088', //后端服务地址 + target: 'http://host:port', //后端服务地址 ws: true, changeOrigin: true, pathRewrite: { @@ -66,10 +50,9 @@ module.exports = { } }, '^/ws/api': { //websocket - target: 'ws://42.123.106.20:8088', + target: 'ws://host:port', ws: true, secure: false, - // logLevel: 'debug', }, } // after: require('./mock/mock-server.js') -- Gitee From f9333f955d5e8b283d2579f78434539f8182b76a Mon Sep 17 00:00:00 2001 From: luxiaolong Date: Sat, 27 Jun 2020 14:51:41 +0800 Subject: [PATCH 122/238] add i18n --- web/src/commonData/i18n/common/en.json | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/web/src/commonData/i18n/common/en.json b/web/src/commonData/i18n/common/en.json index d89c38063..4cdf41d22 100644 --- a/web/src/commonData/i18n/common/en.json +++ b/web/src/commonData/i18n/common/en.json @@ -490,7 +490,7 @@ "cancel": "Cancel", "timeout": "Timeout on publishing project {name}!" }, - "tableDetails" : { + "tableDetails": { "BZBSX": "Table basic attributes", "BZDXX": "Table column information", "BTJXX": "Table statistical information", @@ -1018,6 +1018,20 @@ }, "error": { "fileExists": "Duplicated file!" + }, + "home": { + "welcome": "Welcome to the {text} workspace!", + "setting": "Seting", + "exit": "Exit", + "enter": "Enter {text}", + "dlgTitle": "New Fast entry", + "selectType": "Please select category", + "selectApp": "Please select Application", + "save": "Save", + "cancel": "Cancel", + "running": "running", + "stop": "disable", + "searchPlaceholder": "Search application" } }, "database": { @@ -1614,4 +1628,4 @@ } } } -} +} \ No newline at end of file -- Gitee From aedf2ca8cc0c41c1ee814c9d45f43fbc7446b278 Mon Sep 17 00:00:00 2001 From: luxiaolong Date: Sat, 27 Jun 2020 16:27:33 +0800 Subject: [PATCH 123/238] icon support color --- web/src/assets/styles/workspace.scss | 4 +++- web/src/commonData/i18n/common/zh.json | 1 - web/src/js/module/header/index.vue | 13 ++++++------ web/src/js/view/workspace/index.vue | 28 +++++++++++++++++--------- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/web/src/assets/styles/workspace.scss b/web/src/assets/styles/workspace.scss index 876205e41..552942ed4 100644 --- a/web/src/assets/styles/workspace.scss +++ b/web/src/assets/styles/workspace.scss @@ -71,6 +71,7 @@ .left { flex: 1; + min-height: 137px; // box-shadow: 0 1px 6px rgba(0,0,0,.2); border-color: rgba(0,0,0,0); padding: 0; @@ -79,6 +80,7 @@ .right { // flex: 1; margin-left: 25px; + min-height: 137px; width: 500px; // box-shadow: 0 1px 6px rgba(0,0,0,.2); border-color: rgba(0,0,0,0); @@ -188,7 +190,7 @@ .pane-item { float: left; - margin: 10px 100px 20px 0; + margin: 10px 100px 0 0; width: 450px; } diff --git a/web/src/commonData/i18n/common/zh.json b/web/src/commonData/i18n/common/zh.json index 50e4f491e..1328e2b32 100644 --- a/web/src/commonData/i18n/common/zh.json +++ b/web/src/commonData/i18n/common/zh.json @@ -1020,7 +1020,6 @@ "fileExists": "该文件已经存在!" }, "home": { - "adminArea": "管理员功能", "welcome": "欢迎来到 {text} 的工作空间!", "setting": "设置", "exit": "退出设置", diff --git a/web/src/js/module/header/index.vue b/web/src/js/module/header/index.vue index 8f3aa3a1b..53e2df896 100644 --- a/web/src/js/module/header/index.vue +++ b/web/src/js/module/header/index.vue @@ -160,7 +160,7 @@ export default { }, methods: { init() { - api.fetch('/mock/dss/getBaseInfo', 'get').then((rst) => { + api.fetch('/dss/getBaseInfo', 'get').then((rst) => { if (!isEmpty(rst)) { this.userName = rst.userInfo.basic.username; storage.set('baseInfo', rst); @@ -170,13 +170,14 @@ export default { this.$emit('set-init'); } + api.fetch(`/dss/workspaces`, 'get').then(rst=>{ + if (!isEmpty(rst)) { + this.workspaces = rst.workspaces; + } + }) }); - api.fetch(`/mock/dss/workspaces`, 'get').then(rst=>{ - if (!isEmpty(rst)) { - this.workspaces = rst.workspaces; - } - }) + }, goto(name) { this.$router.push({ diff --git a/web/src/js/view/workspace/index.vue b/web/src/js/view/workspace/index.vue index f8bd8592b..53d724944 100644 --- a/web/src/js/view/workspace/index.vue +++ b/web/src/js/view/workspace/index.vue @@ -18,7 +18,7 @@
- + {{$t('message.workSpace.home.enter', {text: item.title})}}
@@ -43,11 +43,13 @@ {{adminApps.title}}
-
- +
+ {{item.title}}
+ +
@@ -61,16 +63,16 @@
- + {{item.title}} - {{tag}} + {{tag}}

{{item.description}}

-
+
{{$t('message.workSpace.home.running')}}
@@ -81,7 +83,7 @@
-
+
@@ -163,8 +165,8 @@ export default { name: "", description: "" }, - favoriteApps: [{icon: 'fi-exchange', url: ""}], - adminApps: [], + favoriteApps: [], + adminApps: {}, setting: false, show: false, applications: [], @@ -188,6 +190,14 @@ export default { }, methods: { + iconSplit(icon){ + if(icon){ + return icon.split('|') + } + // icon="fi-scriptis|rgb(102, 102, 255)" + // return icon.split('|') + return ['',''] + }, init(){ api.fetch(`/dss/workspaces/${this.workspaceId}`, 'get').then(data=>{ -- Gitee From d772d51953c1b5f8f1fe4439f556c0614de5e0c5 Mon Sep 17 00:00:00 2001 From: luxiaolong Date: Sat, 27 Jun 2020 16:42:52 +0800 Subject: [PATCH 124/238] fixed #176 --- web/src/js/module/footer/index.scss | 9 +++++++++ web/src/js/module/footer/index.vue | 1 + 2 files changed, 10 insertions(+) diff --git a/web/src/js/module/footer/index.scss b/web/src/js/module/footer/index.scss index 5df19daf3..ee8cf90c6 100644 --- a/web/src/js/module/footer/index.scss +++ b/web/src/js/module/footer/index.scss @@ -50,3 +50,12 @@ color: $text-color; } } +.footer-mask { + position: fixed; + top: -100vh; + left: -100vw; + width: 200vw; + height: 200vh; + background-color: #00000000; +} + \ No newline at end of file diff --git a/web/src/js/module/footer/index.vue b/web/src/js/module/footer/index.vue index 16d9fd644..e47a22d73 100644 --- a/web/src/js/module/footer/index.vue +++ b/web/src/js/module/footer/index.vue @@ -9,6 +9,7 @@ ref="resourceSimple" @update-job="updateJob"> +