From d9572ea8cef4acb475ed835d9d8bffd75aebea46 Mon Sep 17 00:00:00 2001 From: zeaslity Date: Thu, 16 Nov 2023 14:33:26 +0800 Subject: [PATCH] [ Server ] [ Harbor ] - sync status - 1 --- agent-go/executor/HarborExecutor.go | 74 +++++++++++++++++-- .../func/auto/beans/HarborFunctionEnum.java | 7 +- .../auto/service/HarborFuncScheduler.java | 41 +++++++++- .../wdd/func/controller/AutoController.java | 22 ++++++ 4 files changed, 134 insertions(+), 10 deletions(-) create mode 100644 server/src/main/java/io/wdd/func/controller/AutoController.java diff --git a/agent-go/executor/HarborExecutor.go b/agent-go/executor/HarborExecutor.go index 9a59378..4354ab9 100644 --- a/agent-go/executor/HarborExecutor.go +++ b/agent-go/executor/HarborExecutor.go @@ -6,6 +6,7 @@ import ( "fmt" "net" "os" + "strconv" "strings" "github.com/mittwald/goharbor-client/v5/apiv2" @@ -39,6 +40,7 @@ func NewHarborOperator() *HarborOperator { // HarborOperatorCache 饿汉式单例 var HarborOperatorCache = NewHarborOperator() +var OctopusReplicationPolicyName = "octopus-sync-replication" func (hOp *HarborOperator) Exec(baseFuncName string, funcArgs ...string) (bool, []string) { // 参见 HarborFunctionEnum @@ -56,7 +58,9 @@ func (hOp *HarborOperator) Exec(baseFuncName string, funcArgs ...string) (bool, case "SYNC_PROJECT_BETWEEN_HARBOR": resultOk, resultLog = hOp.SyncProjectExec(funcArgs) break - + case "SYNC_STATUS_HARBOR": + resultOk, resultLog = hOp.SyncStatusExec(funcArgs) + break } return resultOk, resultLog @@ -221,7 +225,7 @@ func (hOp *HarborOperator) SyncProjectExec(funcArgs []string) (bool, []string) { return false, append(syncNotExistHarborProjectError, "targetClient") } } - octopusReplicationPolicyName := "octopus-sync-replication" + OctopusSourceHarborName := "octopus-source" // add source registry to destination harbor @@ -231,7 +235,7 @@ func (hOp *HarborOperator) SyncProjectExec(funcArgs []string) (bool, []string) { policies, _ := targetClient.ListReplicationPolicies(ctx) if policies != nil { for _, policy := range policies { - if policy.Name == octopusReplicationPolicyName { + if policy.Name == OctopusReplicationPolicyName { err := targetClient.DeleteReplicationPolicyByID(ctx, policy.ID) if err != nil { log.ErrorF("[Harbor Sync Project ] - delete exists replication policy failed ! => %v ", policy) @@ -296,9 +300,13 @@ func (hOp *HarborOperator) SyncProjectExec(funcArgs []string) (bool, []string) { Type: "name", Value: "cmii/**", // 根据需要同步的仓库进行调整 }, + { + Type: "name", + Value: "rancher/**", // 根据需要同步的仓库进行调整 + }, }, ID: 0, - Name: octopusReplicationPolicyName, + Name: OctopusReplicationPolicyName, Override: true, ReplicateDeletion: false, Speed: nil, @@ -322,7 +330,7 @@ func (hOp *HarborOperator) SyncProjectExec(funcArgs []string) (bool, []string) { } } - realOctopusReplicationPolicy, err := targetClient.GetReplicationPolicyByName(ctx, octopusReplicationPolicyName) + realOctopusReplicationPolicy, err := targetClient.GetReplicationPolicyByName(ctx, OctopusReplicationPolicyName) if err != nil { return false, []string{ "[Harbor Sync Project ] - failed to get the realOctopusReplicationPolicy!", @@ -335,13 +343,65 @@ func (hOp *HarborOperator) SyncProjectExec(funcArgs []string) (bool, []string) { }) if err != nil { return false, []string{ - "[Harbor Sync Project ] - failed to start the harbor sync execution !", + "[ Harbor Sync Project ] - failed to start the harbor sync execution !", err.Error(), } } - return true, nil + return true, []string{ + "[ Harbor Sync Project ] - sync started !", + } } + +func (hOp *HarborOperator) SyncStatusExec(funcArgs []string) (bool, []string) { + + if hOp.TargetHarborClient == nil { + ok, createClient := hOp.CheckAndBuildHarborClient(funcArgs[0], true) + if !ok { + return false, []string{ + "[ Sync Status ] - Error !", + } + } + hOp.TargetHarborClient = createClient + } + targetClient := hOp.TargetHarborClient + + ctx := context.Background() + // check replication policy exists + + replicationPolicy, err := targetClient.GetReplicationPolicyByName(ctx, OctopusReplicationPolicyName) + if err != nil { + return false, []string{ + "[ Sync Status ] - get replication error !", + err.Error(), + } + } + + // list execution status + replicationExecutions, err := targetClient.ListReplicationExecutions(ctx, &replicationPolicy.ID, nil, nil) + if err != nil { + return false, []string{ + "[ Sync Status ] - replication has no sync work !", + err.Error(), + } + } + + // find the newest one only have one here + for _, execution := range replicationExecutions { + if !strings.HasPrefix(execution.Status, "Succeed") { + log.InfoF("[sync status]- status are => %v", execution) + // report status + return false, []string{ + fmt.Sprintf("[sync status] - not complete ! progress is => %s %", strconv.FormatInt(execution.Succeed/execution.Total, 10)), + } + } + } + + return true, []string{ + "[sync status]- sync completed !", + } +} + func (hOp *HarborOperator) Command(baseFuncName string, funcArgs ...string) []string { return nil } diff --git a/server/src/main/java/io/wdd/func/auto/beans/HarborFunctionEnum.java b/server/src/main/java/io/wdd/func/auto/beans/HarborFunctionEnum.java index 5bfa08d..d3b329c 100644 --- a/server/src/main/java/io/wdd/func/auto/beans/HarborFunctionEnum.java +++ b/server/src/main/java/io/wdd/func/auto/beans/HarborFunctionEnum.java @@ -16,7 +16,12 @@ public enum HarborFunctionEnum { SYNC_PROJECT_BETWEEN_HARBOR( "SYNC_PROJECT_BETWEEN_HARBOR", - "在源Harbor和目标Harbor之间同步Project, args 为目标Harbor的HostName,不带端口, 源Harbor的HostName,不带端口" + "在源Harbor和目标Harbor之间同步Project, args 为目标Harbor的HostName,不带端口; 源Harbor的HostName,不带端口" + ), + + SYNC_STATUS_HARBOR( + "SYNC_STATUS_HARBOR", + "查询目标Harbor的同步状态进度, args 为目标Harbor的HostName,不带端口;" ); diff --git a/server/src/main/java/io/wdd/func/auto/service/HarborFuncScheduler.java b/server/src/main/java/io/wdd/func/auto/service/HarborFuncScheduler.java index 2f1b492..c7d173e 100644 --- a/server/src/main/java/io/wdd/func/auto/service/HarborFuncScheduler.java +++ b/server/src/main/java/io/wdd/func/auto/service/HarborFuncScheduler.java @@ -11,6 +11,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; @Service @Slf4j @@ -31,13 +32,28 @@ public class HarborFuncScheduler { // after run - afterRunProcedure(); + afterRunProcedure(projectDeployContext); return true; } - private void afterRunProcedure() { + private void afterRunProcedure(ProjectDeployContext projectDeployContext) { + + int maxSyncStatusCheckCount = 1000; + int timePinch = 2; + + int waitCount = 0; + + while (waitCount < maxSyncStatusCheckCount && !checkHarborSyncStatus(projectDeployContext)) { + waitCount++; + + try { + TimeUnit.SECONDS.sleep(timePinch); + } catch (InterruptedException e) { + log.error("wait for sync status error !"); + } + } // 检查是否安装完成, 对安装环境进行判定 log.debug("afterRunProcedure complete!"); @@ -202,6 +218,27 @@ public class HarborFuncScheduler { } + private boolean checkHarborSyncStatus(ProjectDeployContext projectDeployContext) { + ServerInfoPO masterNode = projectDeployContext.getMasterNode(); + + ArrayList syncHarborArgList = new ArrayList<>(); + syncHarborArgList.add(HarborFunctionEnum.SYNC_STATUS_HARBOR.getOpName()); + syncHarborArgList.add(masterNode.getServerIpInV4()); + + + log.info( + "{} start ! args are => {}", + HarborFunctionEnum.SYNC_STATUS_HARBOR.getOpName(), + syncHarborArgList + ); + + return funcService.callHarborFuncAndJudge( + masterNode.getTopicName(), + HarborFunctionEnum.SYNC_STATUS_HARBOR, + syncHarborArgList + ); + } + private void beforeRunProcedure(ProjectDeployContext projectDeployContext) { diff --git a/server/src/main/java/io/wdd/func/controller/AutoController.java b/server/src/main/java/io/wdd/func/controller/AutoController.java new file mode 100644 index 0000000..d88bb60 --- /dev/null +++ b/server/src/main/java/io/wdd/func/controller/AutoController.java @@ -0,0 +1,22 @@ +package io.wdd.func.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController("/auto") +@Api("Octopus自动化介入") +public class AutoController { + + @GetMapping("/harbor/status") + @ApiOperation("查看Harbor的Sync的同步状态") + public void GetHarborSyncStatus( + @RequestParam(name = "projectId") @ApiParam("projectId") Long projectId + ) { + + } + +}