Browse Source

更新构建目录接口

reghao 2 năm trước cách đây
mục cha
commit
2aa4e459c3

+ 4 - 6
manager/src/main/java/cn/reghao/devops/manager/app/controller/config/BuildDirController.java

@@ -1,14 +1,12 @@
 package cn.reghao.devops.manager.app.controller.config;
 
 import cn.reghao.devops.manager.app.service.config.BuildDirService;
-import cn.reghao.devops.manager.app.model.po.config.build.BuildDir;
 import cn.reghao.jutil.jdk.result.Result;
 import cn.reghao.jutil.jdk.result.WebResult;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.MediaType;
-import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 /**
@@ -26,10 +24,10 @@ public class BuildDirController {
         this.buildDirService = buildDirService;
     }
 
-    @ApiOperation(value = "迁移构建目录")
-    @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
-    public String modifyBuildDir(@Validated BuildDir buildDir) {
-        Result result = buildDirService.modify(buildDir);
+    @ApiOperation(value = "清空构建目录")
+    @PostMapping(value = "/erase", produces = MediaType.APPLICATION_JSON_VALUE)
+    public String emptyBuildDir() {
+        Result result = buildDirService.erase();
         return WebResult.result(result);
     }
 }

+ 22 - 26
manager/src/main/java/cn/reghao/devops/manager/app/controller/page/config/BuildDirPageController.java

@@ -1,25 +1,20 @@
 package cn.reghao.devops.manager.app.controller.page.config;
 
-import cn.reghao.devops.common.machine.Disk;
-import cn.reghao.devops.manager.app.db.repository.config.build.BuildDirRepository;
 import cn.reghao.devops.manager.app.model.po.config.build.BuildDir;
-import cn.reghao.devops.manager.machine.model.vo.DiskUsage;
-import cn.reghao.devops.manager.util.db.PageList;
+import cn.reghao.devops.manager.app.service.config.BuildDirService;
 import cn.reghao.devops.manager.util.db.PageSort;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
-import oshi.SystemInfo;
 
 import java.util.List;
-import java.util.stream.Collectors;
 
 /**
  * @author reghao
@@ -30,36 +25,37 @@ import java.util.stream.Collectors;
 @Controller
 @RequestMapping("/app/config/build/dir")
 public class BuildDirPageController {
-    private final BuildDirRepository buildDirRepository;
-    private final Disk disk;
+    private final BuildDirService buildDirService;
 
-    public BuildDirPageController(SystemInfo si, BuildDirRepository buildDirRepository) {
-        this.disk = new Disk(si);
-        this.buildDirRepository = buildDirRepository;
+    public BuildDirPageController(BuildDirService buildDirService) {
+        this.buildDirService = buildDirService;
     }
 
     @ApiOperation(value = "构建目录页面")
     @GetMapping
     public String buildDirPage(Model model) {
+        BuildDir buildDir = buildDirService.get();
+        List<BuildDir> list = List.of(buildDir);
+
         PageRequest pageRequest = PageSort.pageRequest();
-        Page<BuildDir> page = buildDirRepository.findAll(pageRequest);
-        PageList<BuildDir> pageList = PageList.pageList(page);
+        Page<BuildDir> page = new PageImpl<>(list, pageRequest, list.size());
 
         model.addAttribute("page", page);
-        model.addAttribute("list", pageList.getList());
-        return "/app/config/builddir/index";
+        model.addAttribute("list", list);
+        return "/app/config/build/builddir";
     }
 
-    @GetMapping("/diskinfo")
-    public String diskInfoPage(Model model) {
-        List<DiskUsage> diskUsages = disk.detail().stream().map(DiskUsage::new).collect(Collectors.toList());
-        model.addAttribute("list", diskUsages);
-        return "/app/config/builddir/diskinfo";
-    }
+    @ApiOperation(value = "目录容量详情页面")
+    @GetMapping("/usage")
+    public String usagePage(Model model) {
+        BuildDir buildDir = buildDirService.get();
+        List<BuildDir> list = List.of(buildDir);
 
-    @GetMapping("/edit/{id}")
-    public String editAppConfigPage(@PathVariable("id") BuildDir buildDir, Model model) {
-        model.addAttribute("buildDir", buildDir);
-        return "/app/config/builddir/add";
+        PageRequest pageRequest = PageSort.pageRequest();
+        Page<BuildDir> page = new PageImpl<>(list, pageRequest, list.size());
+
+        model.addAttribute("page", page);
+        model.addAttribute("list", list);
+        return "/app/config/build/builddir";
     }
 }

+ 0 - 14
manager/src/main/java/cn/reghao/devops/manager/app/db/repository/config/build/BuildDirRepository.java

@@ -1,14 +0,0 @@
-package cn.reghao.devops.manager.app.db.repository.config.build;
-
-import cn.reghao.devops.manager.app.model.po.config.build.BuildDir;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
-
-/**
- *
- * @author reghao
- * @date 2020-01-21 14:53:03
- */
-public interface BuildDirRepository extends JpaRepository<BuildDir, Integer>, JpaSpecificationExecutor<BuildDir> {
-    BuildDir findByMachineId(String machineId);
-}

+ 8 - 32
manager/src/main/java/cn/reghao/devops/manager/app/model/po/config/build/BuildDir.java

@@ -1,51 +1,27 @@
 package cn.reghao.devops.manager.app.model.po.config.build;
 
-import cn.reghao.devops.manager.util.db.BaseEntity;
 import lombok.*;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-
 /**
  * 应用构建需要使用的本地目录
  *
  * @author reghao
  * @date 2019-08-27 00:17:55
  */
-@NoArgsConstructor
+@AllArgsConstructor
 @Getter
 @Setter
-@Entity
-public class BuildDir extends BaseEntity {
-    @Column(nullable = false, unique = true)
-    @NotBlank(message = "机器 ID 不能为空白字符串")
+public class BuildDir {
     private String machineId;
-    @NotNull
     private String machineIpv4;
     // 本地目录,包含 local-repo, compile-dir 和 pack-dir 三个子目录
-    @Column(nullable = false)
-    @NotBlank(message = "新目录路径不能为空白字符串")
     private String dirPath;
-    @NotNull
     private String mountedOn;
     // TODO 磁盘容量类型修改为 Long
-    @NotNull
-    private String total;
-    @NotNull
-    private String used;
-    @NotNull
-    private String avail;
-
-    public BuildDir(String machineId, String machineIpv4, String dirPath, String mountedOn,
-                    String total, String used, String avail) {
-        this.machineId = machineId;
-        this.machineIpv4 = machineIpv4;
-        this.dirPath = dirPath;
-        this.mountedOn = mountedOn;
-        this.total = total;
-        this.used = used;
-        this.avail = avail;
-    }
+    private long total;
+    private String totalStr;
+    private long used;
+    private String usedStr;
+    private long avail;
+    private String availStr;
 }

+ 5 - 4
manager/src/main/java/cn/reghao/devops/manager/app/service/config/BuildDirService.java

@@ -3,13 +3,14 @@ package cn.reghao.devops.manager.app.service.config;
 import cn.reghao.devops.manager.app.model.po.config.build.BuildDir;
 import cn.reghao.jutil.jdk.result.Result;
 
+import java.io.File;
+
 /**
  * @author reghao
  * @date 2021-09-17 15:56:49
  */
 public interface BuildDirService {
-    void createAndSave();
-    void refresh(BuildDir buildDir);
-    Result modify(BuildDir buildDir);
-    BuildDir get(String machineId);
+    void init(String dirPath) throws Exception;
+    Result erase();
+    BuildDir get();
 }

+ 39 - 94
manager/src/main/java/cn/reghao/devops/manager/app/service/config/impl/BuildDirServiceImpl.java

@@ -2,7 +2,6 @@ package cn.reghao.devops.manager.app.service.config.impl;
 
 import cn.reghao.devops.common.machine.Disk;
 import cn.reghao.devops.common.machine.Machine;
-import cn.reghao.devops.manager.app.db.repository.config.build.BuildDirRepository;
 import cn.reghao.devops.manager.app.model.po.config.build.BuildDir;
 import cn.reghao.devops.common.build.model.LocalBuildDir;
 import cn.reghao.devops.manager.app.service.config.BuildDirService;
@@ -18,7 +17,6 @@ import oshi.SystemInfo;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.Objects;
 
 /**
  * @author reghao
@@ -28,44 +26,35 @@ import java.util.Objects;
 @Service
 public class BuildDirServiceImpl implements BuildDirService {
     // TODO 将 machineId 设置为一个常量
-    private final BuildDirRepository buildDirRepository;
+    private static BuildDir buildDir;
+    private static DiskDetail diskDetail;
     private final ByteConverter converter;
     private final Disk disk;
 
-    public BuildDirServiceImpl(SystemInfo si, BuildDirRepository buildDirRepository) {
+    public BuildDirServiceImpl(SystemInfo si) {
         this.disk = new Disk(si);
-        this.buildDirRepository = buildDirRepository;
         this.converter = new ByteConverter();
     }
 
     @Override
-    public void createAndSave() {
-        try {
-            BuildDir buildDir = defaultLocalBuildDir();
-            buildDirRepository.save(buildDir);
-        } catch (Exception e) {
-            e.printStackTrace();
-            log.error("创建本地构建目录失败: {},devops-manager 结束运行", e.getMessage());
-            System.exit(1);
-        }
-    }
-
-    private BuildDir defaultLocalBuildDir() throws Exception {
-        String home = System.getProperty("user.home");
-        String localBuildDir = String.format("%s/.devops", home);
-        return createLocalBuildDir(localBuildDir);
+    public void init(String dirPath) throws Exception {
+        buildDir = createLocalBuildDir(dirPath);
     }
 
     private BuildDir createLocalBuildDir(String localBuildDir) throws Exception {
-        DiskDetail diskDetail = disk.diskDetail(localBuildDir);
+        diskDetail = disk.diskDetail(localBuildDir);
         String machineId = Machine.ID;
         String machineIpv4 = Machine.IPV4;
         String mountedOn = diskDetail.getMountedOn();
-        String total = converter.convert(ByteType.Bytes, diskDetail.getTotal());
-        String used = converter.convertStr(ByteType.Bytes, ByteType.MiB, diskDetail.getUsed());
-        String avail = converter.convertStr(ByteType.Bytes, ByteType.MiB, diskDetail.getAvail());
-
-        BuildDir buildDir = new BuildDir(machineId, machineIpv4, localBuildDir, mountedOn, total, used, avail);
+        long total = diskDetail.getTotal();
+        String totalStr = converter.convert(ByteType.Bytes, total);
+        long used = diskDetail.getUsed();
+        String usedStr = converter.convertStr(ByteType.Bytes, ByteType.MiB, used);
+        long avail = diskDetail.getAvail();
+        String availStr = converter.convertStr(ByteType.Bytes, ByteType.MiB, avail);
+
+        BuildDir buildDir = new BuildDir(machineId, machineIpv4, localBuildDir, mountedOn,
+                total, totalStr, used, usedStr, avail, availStr);
         createLocalBuildDir(buildDir);
         return buildDir;
     }
@@ -89,83 +78,39 @@ public class BuildDirServiceImpl implements BuildDirService {
     }
 
     private void setLocalBuildDir(BuildDir buildDir) {
-        LocalBuildDir.localRepo = buildDir.getDirPath() + "/local-repo";
-        LocalBuildDir.compileDir = buildDir.getDirPath() + "/compile-dir";
-        LocalBuildDir.packDir = buildDir.getDirPath() + "/pack-dir";
-    }
-
-    @Override
-    public void refresh(BuildDir buildDir) {
-        setLocalBuildDir(buildDir);
         String dirPath = buildDir.getDirPath();
-        DiskDetail diskDetail = disk.diskDetail(dirPath);
-        if (diskDetail != null) {
-            buildDir.setUsed(converter.convertStr(ByteType.Bytes, ByteType.MiB, diskDetail.getUsed()));
-            buildDir.setAvail(converter.convertStr(ByteType.Bytes, ByteType.MiB, diskDetail.getAvail()));
-        } else {
-            log.error("本地目录 {} 不合法,devops-manager 结束运行", dirPath);
-            System.exit(1);
-        }
+        LocalBuildDir.localRepo = String.format("%s/local-repo", dirPath);
+        LocalBuildDir.compileDir = String.format("%s/compile-dir", dirPath);
+        LocalBuildDir.packDir = String.format("%s/pack-dir", dirPath);
     }
 
     @Override
-    public synchronized Result modify(BuildDir buildDir) {
-        if (buildDir.getId() == null) {
-            return Result.result(ResultStatus.FAIL, "构建目录不存在");
-        }
-
-        BuildDir oldBuildDir = buildDirRepository.findByMachineId(buildDir.getMachineId());
-        String oldDirPath = oldBuildDir.getDirPath();
-        String oldMountedOn = oldBuildDir.getMountedOn();
-        String newDirPath = buildDir.getDirPath();
-        String newMountedOn = disk.diskDetail(newDirPath).getMountedOn();
-
-        if (newDirPath.equals(oldDirPath)) {
-            return Result.result(ResultStatus.FAIL, "目录没有改变");
-        } else if (new File(newDirPath).exists()) {
-            return Result.result(ResultStatus.FAIL, "新目录已存在,请另外指定一个不存在的目录");
-        } else if (newMountedOn.equals(oldMountedOn)) {
-            return Result.result(ResultStatus.FAIL, "新目录和当前目录同属一个分区");
-        }
-
-        String oldPackDir = LocalBuildDir.packDir;
-        // TODO 目录迁移时不能有应用处于构建过程中
-        try {
-            BuildDir newBuildDir = createLocalBuildDir(newDirPath);
-            File file = new File(oldPackDir);
-            if (Objects.requireNonNull(file.list()).length != 0) {
-                try {
-                    copyDirContentToDir(oldPackDir, LocalBuildDir.packDir);
-                } catch (IOException e) {
-                    FileUtils.deleteQuietly(new File(newDirPath));
-                    return Result.result(ResultStatus.ERROR, e.getMessage());
-                }
-            }
-
-            buildDirRepository.save(newBuildDir);
-            return Result.result(ResultStatus.SUCCESS);
-        } catch (Exception e) {
-            return Result.result(ResultStatus.FAIL, e.getMessage());
-        }
+    public synchronized Result erase() {
+        // TODO 保证没有 app 处在构建状态
+        String localRepo = LocalBuildDir.localRepo;
+        erase(localRepo);
+        String compileDir = LocalBuildDir.compileDir;
+        erase(compileDir);
+        String packDir = LocalBuildDir.packDir;
+        erase(packDir);
+        return Result.result(ResultStatus.SUCCESS);
     }
 
-    // TODO 和 BuilderUtil 中的代码重复
-    private void copyDirContentToDir(String src, String dst) throws IOException {
-        File srcDir = new File(src);
-        File dstDir = new File(dst);
-        for (File file : Objects.requireNonNull(srcDir.listFiles())) {
-            if (file.isDirectory()) {
-                String dirname = file.getName();
-                File dstdir = new File(dst + File.separator + dirname);
-                FileUtils.copyDirectory(file, dstdir);
-            } else {
-                FileUtils.copyFileToDirectory(file, dstDir);
-            }
+    private void erase(String dirPath) {
+        try {
+            File dir = new File(dirPath);
+            FileUtils.cleanDirectory(dir);
+        } catch (IOException e) {
+            e.printStackTrace();
         }
     }
 
     @Override
-    public BuildDir get(String machineId) {
-        return buildDirRepository.findByMachineId(machineId);
+    public BuildDir get() {
+        buildDir.setUsed(diskDetail.getUsed());
+        buildDir.setAvail(diskDetail.getAvail());
+        buildDir.setUsedStr(converter.convert(ByteType.Bytes, diskDetail.getUsed()));
+        buildDir.setAvailStr(converter.convert(ByteType.Bytes, diskDetail.getAvail()));
+        return buildDir;
     }
 }

+ 14 - 8
manager/src/main/java/cn/reghao/devops/manager/config/spring/AppLifecycle.java

@@ -1,7 +1,5 @@
 package cn.reghao.devops.manager.config.spring;
 
-import cn.reghao.devops.common.machine.Machine;
-import cn.reghao.devops.manager.app.model.po.config.build.BuildDir;
 import cn.reghao.devops.manager.app.service.config.BuildDirService;
 import cn.reghao.devops.manager.log.Appenders;
 import cn.reghao.devops.manager.log.LoggerConfig;
@@ -16,6 +14,7 @@ import org.springframework.boot.ApplicationArguments;
 import org.springframework.boot.ApplicationRunner;
 import org.springframework.stereotype.Component;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -50,7 +49,7 @@ public class AppLifecycle implements ApplicationRunner, DisposableBean {
     @Override
     public void destroy() {
         machineService.flushToDataSource();
-        log.info("Manager 停止");
+        log.info("devops-manager 停止");
     }
 
     private void initLogConfig() {
@@ -73,12 +72,19 @@ public class AppLifecycle implements ApplicationRunner, DisposableBean {
     }
 
     private void initBuildDir() {
-        log.info("初始化本地构建目录");
-        BuildDir buildDir = buildDirService.get(Machine.ID);
-        if (buildDir == null) {
-            buildDirService.createAndSave();
+        String userDir = System.getProperty("user.dir");
+        String baseDir = String.format("%s/devops_data", userDir);
+        File dir = new File(baseDir);
+        if (!dir.exists() && !dir.mkdirs()) {
+            log.error("创建本地构建目录 {} 失败,devops-manager 结束运行", baseDir);
+            System.exit(1);
         } else {
-            buildDirService.refresh(buildDir);
+            try {
+                buildDirService.init(baseDir);
+            } catch (Exception e) {
+                log.error("初始化本地构建目录失败: {},devops-manager 结束运行", e.getMessage());
+                System.exit(1);
+            }
         }
     }
 

+ 10 - 7
manager/src/main/resources/templates/app/config/builddir/index.html → manager/src/main/resources/templates/app/config/build/builddir.html

@@ -14,21 +14,24 @@
                 <thead>
                 <tr>
                     <th class="sortable" data-field="machineIpv4">机器地址</th>
-                    <th class="sortable" data-field="dirPath">当前目录</th>
+                    <th class="sortable" data-field="dirPath">构建目录</th>
                     <th class="sortable" data-field="mountedOn">所属分区</th>
-                    <th class="sortable" data-field="size">分区总容量</th>
-                    <th class="sortable" data-field="used">分区已使用</th>
+                    <th class="sortable" data-field="size">分区总量</th>
                     <th class="sortable" data-field="avail">分区可用</th>
+                    <th>操作</th>
                 </tr>
                 </thead>
                 <tbody>
                 <tr th:each="item:${list}">
                     <td th:text="${item.machineIpv4}">机器地址</td>
-                    <td th:text="${item.dirPath}">当前目录</td>
+                    <td th:text="${item.dirPath}">构建目录</td>
                     <td th:text="${item.mountedOn}">所属分区</td>
-                    <td th:text="${item.total}">分区总容量</td>
-                    <td th:text="${item.used}">分区已使用</td>
-                    <td th:text="${item.avail}">分区可用</td>
+                    <td th:text="${item.totalStr}">分区总量</td>
+                    <td th:text="${item.availStr}">分区可用</td>
+                    <td>
+                        <a class="ajax-post"
+                           th:href="@{'/api/app/config/build/dir/erase'}">清空</a>
+                    </td>
                 </tr>
                 </tbody>
             </table>

+ 0 - 33
manager/src/main/resources/templates/app/config/builddir/add.html

@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<html xmlns:th="http://www.thymeleaf.org">
-
-<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
-
-<body>
-<div class="layui-form timo-compile">
-    <form th:action="@{/api/app/config/build/dir}">
-        <input type="hidden" name="id" th:value="${buildDir?.id}"/>
-        <input type="hidden" name="machineId" th:value="${buildDir?.machineId}"/>
-        <div class="layui-form-item">
-            <label class="layui-form-label">机器地址</label>
-            <div class="layui-input-inline">
-                <input class="layui-input" type="text" name="machineIpv4" readonly="true" placeholder="请输入机器地址" required th:value="${buildDir?.machineIpv4}">
-            </div>
-        </div>
-        <div class="layui-form-item">
-            <label class="layui-form-label required">新目录路径</label>
-            <div class="layui-input-inline">
-                <input class="layui-input" type="text" name="dirPath" placeholder="请输入新目录路径" required th:value="${buildDir?.dirPath}">
-            </div>
-        </div>
-        <div class="layui-form-item timo-finally">
-            <button class="layui-btn ajax-submit"><i class="fa fa-check-circle"></i> 保存</button>
-            <button class="layui-btn btn-secondary close-popup"><i class="fa fa-times-circle"></i> 关闭</button>
-        </div>
-    </form>
-</div>
-<script th:replace="/common/template :: script"></script>
-<script type="text/javascript">
-</script>
-</body>
-</html>

+ 0 - 30
manager/src/main/resources/templates/app/config/builddir/diskinfo.html

@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<html xmlns:th="http://www.thymeleaf.org">
-<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
-
-<body>
-<div class="timo-detail-page">
-    <div class="timo-table-wrap">
-        <table class="layui-table timo-table">
-            <thead>
-            <tr>
-                <th data-field="mountedOn">分区挂载路径</th>
-                <th data-field="total">总容量</th>
-                <th data-field="used">已使用</th>
-                <th data-field="avail">可用</th>
-            </tr>
-            </thead>
-            <tbody>
-            <tr th:each="item:${list}">
-                <td th:text="${item.mountedOn}">分区挂载路径</td>
-                <td th:text="${item.total}">总容量</td>
-                <td th:text="${item.used}">已使用</td>
-                <td th:text="${item.avail}">可用</td>
-            </tr>
-            </tbody>
-        </table>
-    </div>
-</div>
-<script th:replace="/common/template :: script"></script>
-</body>
-</html>