From 41021633bfee5b5c9c57cb888423f3392c530f98 Mon Sep 17 00:00:00 2001 From: ludc Date: 星期一, 25 三月 2024 18:31:08 +0800 Subject: [PATCH] 业务类型bug修改,集成接口,远程部署等功能修改。 --- Source/UBCS/ubcs-service/ubcs-deploy/src/main/java/com/vci/ubcs/deploy/service/impl/DeployAppsServiceImpl.java | 371 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 361 insertions(+), 10 deletions(-) diff --git a/Source/UBCS/ubcs-service/ubcs-deploy/src/main/java/com/vci/ubcs/deploy/service/impl/DeployAppsServiceImpl.java b/Source/UBCS/ubcs-service/ubcs-deploy/src/main/java/com/vci/ubcs/deploy/service/impl/DeployAppsServiceImpl.java index 6913f3f..2427ebe 100644 --- a/Source/UBCS/ubcs-service/ubcs-deploy/src/main/java/com/vci/ubcs/deploy/service/impl/DeployAppsServiceImpl.java +++ b/Source/UBCS/ubcs-service/ubcs-deploy/src/main/java/com/vci/ubcs/deploy/service/impl/DeployAppsServiceImpl.java @@ -5,45 +5,107 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.nacos.shaded.com.google.protobuf.ServiceException; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import com.vci.ubcs.deploy.entity.CmdConfig; import com.vci.ubcs.deploy.entity.DeployApps; -import com.vci.ubcs.deploy.entity.Instance; +import com.vci.ubcs.deploy.enumpack.CmdConfigEnum; import com.vci.ubcs.deploy.mapper.DeployAppsMapper; import com.vci.ubcs.deploy.service.IDeployAppsService; import com.vci.ubcs.deploy.vo.DeployAppsVO; import com.vci.ubcs.starter.util.HttpUtils; +import jodd.io.StreamGobbler; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springblade.core.secure.utils.AuthUtil; +import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.Func; -import org.springblade.core.tool.utils.UrlUtil; +import org.springblade.core.tool.utils.WebUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.Environment; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; +import java.io.*; +import java.net.InetAddress; import java.net.URL; -import java.util.ArrayList; -import java.util.List; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; /** * @author ludc * @date 2024/1/7 19:54 */ @Service -public class DeployAppsServiceImpl extends ServiceImpl<DeployAppsMapper, DeployApps> implements IDeployAppsService { +@RequiredArgsConstructor +@Slf4j +public class DeployAppsServiceImpl extends ServiceImpl<DeployAppsMapper, DeployApps> implements IDeployAppsService, EnvironmentAware { - @Autowired - private DeployAppsMapper deployAppsMapper; + private final DeployAppsMapper deployAppsMapper; @Value("${password-free.pwd-free-addr:localhost}") private String pwdFreeAddr; - // 閫氳繃鏈嶅姟娉ㄥ唽涓績鑾峰彇缃戝叧鐨勭鍙e彿 + /** + * 閫氳繃鏈嶅姟娉ㄥ唽涓績鑾峰彇缃戝叧鐨勭鍙e彿 + */ @Autowired private DiscoveryClient discoveryClient; + + /** + * 鍚勪釜鏈嶅姟瀛樻斁鐨勭殑鐖惰矾寰� + */ + @Value("${local-log.parent-path:/data1/ubcs/ubcs-server}") + private String PARENTPATH; + + /** + * 鏃ュ織鏂囦欢鐨勫叿浣撲綅缃� + */ + @Value("${local-log.log-path:/target/log}") + private String LOGPATH; + + /** + * 鏍规嵁鎿嶄綔绯荤粺鐢熸垚鍒嗛殧绗� + */ + private String SEPARATOR = "/"; + + /** + * 鏍规嵁褰撳墠杩愯鐨勭幆澧冿紝瀵归厤缃殑鏃ュ織璺緞鏍煎紡杩涜璋冩暣 + * @param environment + */ + @Override + public void setEnvironment(Environment environment) { + String os = environment.getProperty("os.name").toLowerCase(); + if (!os.contains("win")) { + this.SEPARATOR = "/"; + }else{ + this.SEPARATOR = "\\"; + } + } @Override public List<DeployAppsVO> getApplications(ServletRequest servletRequest) throws ServiceException { @@ -80,12 +142,284 @@ deployAppsVO.setStatusTimestamp(jsonObject.get("statusTimestamp").toString()); deployAppsVOList.add(deployAppsVO); } - } }catch (Exception e){ throw new ServiceException("璋冪敤ubcs-admin鑾峰彇鏈嶅姟淇℃伅澶辫触锛屽師鍥狅細"+e.getMessage()); } + // 鍐嶆煡璇㈠簱涓凡缁忓瓨鍦ㄧ殑鏈嶅姟閰嶇疆淇℃伅锛岃繘琛屾槸鍚﹀凡缁忓惎鍔ㄧ殑鍒ゆ柇 + List<DeployApps> deployApps = deployAppsMapper.selectList(null); + // 搴撲腑鏈厤缃紝鐩存帴杩斿洖姝e湪杩愯鐨勬湇鍔′俊鎭� + if(deployApps.isEmpty()){ + return deployAppsVOList; + } + // 绛涢�夊嚭涓嶅湪杩愯鐨勫苟鐢熸垚榛樿鐨勬湇鍔′俊鎭� + List<DeployAppsVO> deployAppsVOS1 = deployApps.stream() + .filter(deployApp -> deployAppsVOList.stream() + .noneMatch(deployAppVO -> deployApp.getServerName().equals(deployAppVO.getName()) && + deployApp.getServerName().equals(deployAppVO.getName()))) + .map(deployApp -> { + DeployAppsVO deployAppsVO2 = new DeployAppsVO(deployApp.getServerName(), "DOWN", "", "", 0); + if(deployApp.getServerName().equals("web")){ + deployAppsVO2.setStatus("UP"); + deployAppsVO2.setPort("8080"); + deployAppsVO2.setServiceNum(1); + } + return deployAppsVO2; + }) + .collect(Collectors.toList()); + deployAppsVOList.addAll(deployAppsVOS1); return deployAppsVOList; + } + + @Override + public DeployApps saveOrGetServiceConfInfo(DeployAppsVO deployAppsVO) throws ServiceException { + if(deployAppsVO.getName().isEmpty()){ + throw new ServiceException("缂哄皯蹇呬紶鍙傛暟name"); + } + List<DeployApps> deployApps = deployAppsMapper.selectList(Wrappers.<DeployApps>query().lambda().eq(DeployApps::getServerName, deployAppsVO.getName())); + if(Func.isNotEmpty(deployApps)){ + return deployApps.get(0); + } + // 鏈粠搴撲腑鏌ヨ鍒帮紝闇�瑕佺敓鎴愭湇鍔′俊鎭繚瀛橀粯璁や俊鎭埌搴撲腑 + DeployApps defaultDeployApps = new DeployApps(); + defaultDeployApps.setLogPath(PARENTPATH + SEPARATOR + deployAppsVO.getName().replace("-","_") + LOGPATH); + defaultDeployApps.setServerName(deployAppsVO.getName()); + defaultDeployApps.setStartCmd(CmdConfigEnum.START_CMD.getValue() + deployAppsVO.getName()); + defaultDeployApps.setStopCmd(CmdConfigEnum.STOP_CMD.getValue() + deployAppsVO.getName()); + defaultDeployApps.setRestartCmd(CmdConfigEnum.RESTART_CMD.getValue() + deployAppsVO.getName()); + defaultDeployApps.setServerPath(PARENTPATH + SEPARATOR + deployAppsVO.getName().replace("-","_")); + int eft = deployAppsMapper.insert(defaultDeployApps); + if (!SqlHelper.retBool(eft)) { + throw new ServiceException("鐢熸垚榛樿鏈嶅姟淇℃伅鍒板簱涓椂澶辫触锛�"); + } + return defaultDeployApps; + } + + /** + * 淇敼鎴栦繚瀛� + * @param deployAppsVO + * @return + * @throws ServiceException + */ + @Override + public R saveOrUpdateServiceInfo(DeployAppsVO deployAppsVO) throws ServiceException { + boolean checkBoolean = checkCmdVer(deployAppsVO.getStartCmd()) && checkCmdVer(deployAppsVO.getStopCmd()) && checkCmdVer(deployAppsVO.getRestartCmd()); + if(checkBoolean){ + return R.fail("閰嶇疆鐨勫懡浠や腑鍖呭惈鍗遍櫓鍛戒护锛屽锛歳m銆乵v銆乺m -rf銆乧hmod绛夊懡浠ゅ拰鍏抽敭璇嶏紒 "); + } + return R.status(this.saveOrUpdate(deployAppsVO)); + } + + /** + * 鏂板鏈嶅姟淇℃伅 + * @param deployApps + * @return + * @throws ServiceException + */ + @Override + public boolean addSave(DeployApps deployApps) throws ServiceException { + if (Func.isBlank(deployApps.getServerName()) || Func.isBlank(deployApps.getServerPath())) { + throw new ServiceException("蹇呬紶鍙傛暟[鏈嶅姟鍚嶇О锛屾湇鍔″瓨鏀捐矾寰刔涓嶈兘涓虹┖"); + } + List<DeployApps> deployAppsList = deployAppsMapper.selectList(Wrappers.<DeployApps>query().lambda().eq(DeployApps::getServerName, deployApps.getServerName())); + if (!deployAppsList.isEmpty()) { + throw new ServiceException("鏂板鏈嶅姟鐨勬湇鍔″悕閲嶅锛�"); + } + return SqlHelper.retBool(deployAppsMapper.insert(deployApps)); + } + + /** + * 鏇存柊鏂囦欢涓婁紶 + * @param files + * @param serverName + * @return + */ + @Override + public R importJarUpdate(MultipartFile[] files, String serverName) throws ServiceException { + // 鏍规嵁鏈嶅姟鍚嶆煡鐪嬪埌鏈嶅姟鐩稿叧淇℃伅 + List<DeployApps> deployAppsDB = deployAppsMapper.selectList(Wrappers.<DeployApps>query().lambda().eq(DeployApps::getServerName, serverName)); + if(deployAppsDB.isEmpty()){ + return R.fail("No configuration information related to "+ serverName +" service found"); + } + // 閬嶅巻MultipartFile鏁扮粍锛岄�愪釜澶勭悊鏂囦欢 + try { + for (MultipartFile file : files) { + // 閰嶇疆浜嗗浠芥枃浠惰矾寰勶紝鍏堝浠藉啀鏇挎崲 + if(Func.isNotEmpty(deployAppsDB.get(0).getFileBack())){ + File backFile = new File(deployAppsDB.get(0).getFileBack()); + // 璺緞涓嶅瓨鍦ㄥ氨鍒涘缓 + if (!backFile.exists()) { + backFile.mkdirs(); + } + String backName = ""; + String fileType = "file"; + // 鏄帇缂╂枃浠�,鍥犱负鍙細瀛樺湪涓ょ鎯呭喌锛屾枃浠跺悕鏄帇缂╂枃浠讹紝鎴栬�呮枃浠讹紙.jar绫诲瀷鐨勬枃浠讹級 + // 褰撳墠鏃堕棿 + String currentDateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + if (file.getContentType().equals("application/zip") || file.getContentType().equals("application/x-zip-compressed")) { + backName = file.getOriginalFilename().replace(".zip","_" + currentDateTime); + }else{ + backName = file.getOriginalFilename().replace(".","_" + currentDateTime + "."); + } + File source = new File(deployAppsDB.get(0).getServerPath() + this.SEPARATOR + file.getOriginalFilename().replace(".zip", "")); + File destination = new File(deployAppsDB.get(0).getFileBack() + this.SEPARATOR + backName); + copyFolder(source, destination); + } + Path filePath = Paths.get(deployAppsDB.get(0).getServerPath(), file.getOriginalFilename()); + Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING); + // 妫�鏌ユ枃浠剁被鍨嬶紝濡傛灉鏄帇缂╂枃浠跺垯瑙e帇缂� + if (file.getContentType().equals("application/zip") || file.getContentType().equals("application/x-zip-compressed")) { + //sourcePath鍘嬬缉鍖呮枃浠惰矾寰� + try (ZipFile zipFile = new ZipFile(new File(deployAppsDB.get(0).getServerPath()+ this.SEPARATOR +file.getOriginalFilename()))) { + Enumeration enumeration = zipFile.entries(); + while (enumeration.hasMoreElements()) { + //渚濇鑾峰彇鍘嬬缉鍖呭唴鐨勬枃浠跺疄浣撳璞� + ZipEntry entry = (ZipEntry) enumeration.nextElement(); + String name = entry.getName(); + if (entry.isDirectory()) { + continue; + } + try (BufferedInputStream inputStream = new BufferedInputStream(zipFile.getInputStream(entry))) { + // 闇�瑕佸垽鏂枃浠舵墍鍦ㄧ殑鐩綍鏄惁瀛樺湪锛屽鐞嗗帇缂╁寘閲岄潰鏈夋枃浠跺す鐨勬儏鍐� + String outName = deployAppsDB.get(0).getServerPath() + this.SEPARATOR + name; + File outFile = new File(outName); + File tempFile = new File(outName.substring(0, outName.lastIndexOf("/"))); + if (!tempFile.exists()) { + tempFile.mkdirs(); + } + try (BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outFile))) { + int len; + byte[] buffer = new byte[1024]; + while ((len = inputStream.read(buffer)) > 0) { + outputStream.write(buffer, 0, len); + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + File file1 = new File(deployAppsDB.get(0).getServerPath() + SEPARATOR + file.getOriginalFilename()); + // 鍘嬬缉鏂囦欢涓婁紶鎴愬姛涔嬪悗锛屽垹闄よВ鍘嬫枃浠� + file1.delete(); + } + } + String output = execute(deployAppsDB.get(0),"UP"); + return R.success(output.toString()); + } catch (IOException e) { + e.printStackTrace(); + log.error(e.getMessage()); + return R.fail("Failed to upload files"); + } + + } + + /** + * 鎵ц鍛戒护 + * @param deployAppsVO + * @return + */ + @Override + public R cmdExecute(DeployAppsVO deployAppsVO) throws ServiceException { + String excuteRes = ""; + try { + List<DeployApps> deployAppsDB = deployAppsMapper.selectList(Wrappers.<DeployApps>query().lambda().eq(DeployApps::getServerName, deployAppsVO.getName())); + if(deployAppsDB.isEmpty()){ + return R.fail("鍛戒护鎵ц鍑洪敊锛屽簱涓湭鎵惧埌"+ deployAppsVO.getName() +"鏈嶅姟鐩稿叧閰嶇疆锛�" ); + } + excuteRes = execute(deployAppsDB.get(0),deployAppsVO.getStatus()); + return R.success("鍛戒护鎵ц缁撴潫锛�"+excuteRes); + }catch (Exception e){ + throw new ServiceException(e.getMessage()); + } + } + + /** + * 鎵ц鍛戒护 + * @param deployApps + * @return + * @throws ServiceException + */ + public String execute(DeployApps deployApps,String type) throws ServiceException { + // 澶勭悊涓婁紶鏂囦欢鐨勯�昏緫 + StringBuilder output = new StringBuilder(); + try { + String cmd = ""; + if(type.equalsIgnoreCase("UP")){ + cmd = deployApps.getRestartCmd(); + }else { + cmd = deployApps.getStartCmd(); + } + if(Func.isEmpty(cmd)){ + return "The executed command is empty"; + } + if(checkCmdVer(cmd)){ + return "閰嶇疆鐨勫懡浠や腑鍖呭惈鍗遍櫓鍛戒护锛屽锛歳m銆乵v銆乺m -rf銆乧hmod绛夊懡浠ゅ拰鍏抽敭璇嶏紒 "; + } + // 鎵цLinux鍛戒护 + log.info("寮�濮嬫墽琛屽懡浠わ細"+cmd); + // Process process = Runtime.getRuntime().exec(cmd); + ProcessBuilder processBuilder = new ProcessBuilder(cmd.split("\\s")); + // processBuilder.command(cmd); + Process process = processBuilder.start(); + // 绛夊緟鍛戒护鎵ц瀹屾垚 + int exitCode = process.waitFor(); + + InputStream inputStream = process.getInputStream(); + OutputStream outputStream = process.getOutputStream(); + InputStream errorStream = process.getErrorStream(); + // 璇诲彇鍛戒护鎵ц缁撴灉 + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + String line; + while ((line = reader.readLine()) != null) { + output.append(line).append("\n"); + } + reader.close(); + + // 璇诲彇鍛戒护鎵ц鐨勯敊璇緭鍑烘祦 + BufferedReader errorReader = new BufferedReader(new InputStreamReader(errorStream)); + StringBuilder errorOutput = new StringBuilder(); + String errorLine; + while ((errorLine = errorReader.readLine()) != null) { + errorOutput.append(errorLine).append("\n"); + } + String errorOutputString = errorOutput.toString(); + errorReader.close(); + + log.info("閿欒杈撳嚭锛�" + errorOutputString); + int exitValue = process.exitValue(); + log.info("鍛戒护鎵ц缁撴灉锛�" + output.toString()+":"+exitCode+","+exitValue); + return output.toString(); + }catch (IOException | InterruptedException e){ + e.printStackTrace(); + log.error("鍛戒护鎵ц鍑洪敊锛屽師鍥狅細" + e.getMessage()); + throw new ServiceException("Command execution failed"+e.getMessage()); + } + } + + /** + * 鏂囦欢澶囦唤鎿嶄綔 + * @param source 婧愭枃浠� + * @param destination 鏂囦欢澶囦唤璺緞 + * @throws IOException + */ + private void copyFolder(File source, File destination) throws IOException { + // 鏂囦欢瀛樺湪鎵嶉渶瑕佸浠� + if(source.exists()){ + if (source.isDirectory()) { + if (!destination.exists()) { + destination.mkdir(); + } + String[] files = source.list(); + for (String file : files) { + File srcFile = new File(source, file); + File destFile = new File(destination, file); + copyFolder(srcFile, destFile); + } + } else { + Files.copy(source.toPath(), destination.toPath()); + } + } } /** @@ -93,7 +427,7 @@ * @param serviceId * @return */ - public String getGatewayPort(String serviceId) { + private String getGatewayPort(String serviceId) { List<ServiceInstance> instances = discoveryClient.getInstances(serviceId); if (!instances.isEmpty()) { ServiceInstance gatewayInstance = instances.get(0); @@ -102,5 +436,22 @@ return "8080"; } + /** + * 鍚姩銆佸仠姝€�侀噸鍚懡浠ゆ牎楠� + * @param cmd + * @return true: 鍖呭惈楂橀闄╁懡浠わ紝 false锛氫笉鍖呭惈 + */ + private boolean checkCmdVer(String cmd){ + if(Func.isEmpty(cmd)){ + return false; + } + String[] highRiskCommands = {"rm", "rmdir", "mv", "unlink", "rm -rf", "mv -rf", "dd", "chmod", "chown", "mkfs", "shutdown", "reboot", "kill"}; + for(String highRiskCmd : highRiskCommands){ + if(cmd.contains(highRiskCmd)){ + return true; + } + } + return false; + } } -- Gitblit v1.9.3