[ Cmii ] [ Octopus ] - reformat agent-go - 1

This commit is contained in:
zeaslity
2024-03-29 11:39:14 +08:00
parent aa4412f042
commit 1be48aaac2
52 changed files with 683 additions and 557 deletions

View File

@@ -0,0 +1,420 @@
package a_executor
import (
"context"
"encoding/json"
"fmt"
"net"
"os"
"strconv"
"strings"
"github.com/mittwald/goharbor-client/v5/apiv2"
"github.com/mittwald/goharbor-client/v5/apiv2/model"
)
type HarborOperator struct {
SourceHarborHost string `json:"sourceHarborHost,omitempty"`
TargetHarborHost string `json:"targetHarborHost,omitempty"`
HarborPort string `json:"harborPort,omitempty"`
HarborAdminUser string `json:"harborAdminUser,omitempty"`
HarborAdminPass string `json:"harborAdminPass,omitempty"`
TargetHarborClient *apiv2.RESTClient
SourceHarborClient *apiv2.RESTClient
}
// NewHarborOperator 返回一个带有默认HarborAdminPass的HarborOperator实例
func NewHarborOperator() *HarborOperator {
return &HarborOperator{
HarborPort: "8033",
HarborAdminUser: "admin", // 设置默认值
HarborAdminPass: "V2ryStr@ngPss", // 设置默认值
}
}
// HarborOperatorCache 饿汉式单例
var HarborOperatorCache = NewHarborOperator()
var OctopusReplicationPolicyName = "octopus-sync-replication"
func (hOp *HarborOperator) Exec(baseFuncName string, funcArgs ...string) (bool, []string) {
// 参见 HarborFunctionEnum
resultOk := true
var resultLog []string
switch baseFuncName {
case "CREATE_PROJECT":
resultOk, resultLog = hOp.CreateProjectExec(funcArgs)
break
case "LIST_PROJECT":
resultOk, resultLog = hOp.ListProjectExec(funcArgs)
break
case "SYNC_PROJECT_BETWEEN_HARBOR":
resultOk, resultLog = hOp.SyncProjectExec(funcArgs)
break
case "SYNC_STATUS_HARBOR":
resultOk, resultLog = hOp.SyncStatusExec(funcArgs)
break
}
return resultOk, resultLog
}
func (hOp *HarborOperator) CreateProjectExec(funcArgs []string) (bool, []string) {
if hOp.TargetHarborClient == nil {
ok, createClient := hOp.CheckAndBuildHarborClient(funcArgs[0], "", true)
if !ok {
return false, []string{
"[Harbor Create Project] - Error !",
}
}
hOp.TargetHarborClient = createClient
}
client := hOp.TargetHarborClient
// create project
// 定义你想要创建的仓库(项目)的详细信息
log.Debug("[Harbor Create Project] - create project !")
needToCreateProjectNameList := []string{"cmii", "rancher"}
// 使用客户端创建项目
ctx := context.Background()
for _, projectName := range needToCreateProjectNameList {
log.DebugF("start to create proect => %s", projectName)
projectReq := &model.ProjectReq{
ProjectName: projectName, // 仓库名称
Metadata: &model.ProjectMetadata{
Public: "true", // 是否是公开的
},
}
exists, _ := client.ProjectExists(ctx, projectName)
if !exists {
err := client.NewProject(ctx, projectReq)
if err != nil {
errorLog := fmt.Sprintf("Error creating project %s: %s\n", projectName, err.Error())
return false, []string{errorLog}
}
}
log.DebugF("[Harbor Create Project] - Project %s already exists ! continue ", projectName)
}
successLog := "[Harbor CreateProjectExec] - Project Create Success !"
log.Info(successLog)
return true, []string{successLog}
}
func (hOp *HarborOperator) CheckAndBuildHarborClient(targetHarborHost string, targetHarborPort string, isTarget bool) (bool, *apiv2.RESTClient) {
log.InfoF("[Harbor Client Create] - start to create harbor client %s", targetHarborHost)
parseIP := net.ParseIP(targetHarborHost)
if parseIP == nil {
log.Error(
fmt.Sprintf("[Harbor Client Create] - ip format is wrong! parseIP is => %s ", parseIP),
)
return false, nil
}
if targetHarborPort == "" {
targetHarborPort = hOp.HarborPort
}
if isTarget {
hOp.TargetHarborHost = "http://" + targetHarborHost + ":" + targetHarborPort + "/api/"
log.DebugF("[Harbor Client Create] - harbor host is => %s", hOp.TargetHarborHost)
} else {
hOp.SourceHarborHost = "http://" + targetHarborHost + ":" + targetHarborPort + "/api/"
log.DebugF("[Harbor Client Create] - harbor host is => %s", hOp.SourceHarborHost)
}
// check connection
var client *apiv2.RESTClient
var err error
if isTarget {
client, err = apiv2.NewRESTClientForHost(hOp.TargetHarborHost, hOp.HarborAdminUser, hOp.HarborAdminPass, nil)
} else {
client, err = apiv2.NewRESTClientForHost(hOp.SourceHarborHost, hOp.HarborAdminUser, hOp.HarborAdminPass, nil)
}
if err != nil {
errorLog := fmt.Sprintf("Error creating REST client: %s\n", err.Error())
log.Error(errorLog)
return false, nil
}
return true, client
}
func (hOp *HarborOperator) ListProjectExec(funcArgs []string) (bool, []string) {
if hOp.TargetHarborClient == nil {
ok, createClient := hOp.CheckAndBuildHarborClient(funcArgs[0], "", true)
if !ok {
return false, []string{
"[Harbor Create Project ] - Error !",
}
}
hOp.TargetHarborClient = createClient
}
client := hOp.TargetHarborClient
// 使用客户端列出所有项目
ctx := context.Background()
projects, err := client.ListProjects(ctx, "")
if err != nil {
fmt.Printf("Error listing projects: %v\n", err)
os.Exit(1)
}
// 打印所有项目的信息
for _, project := range projects {
fmt.Printf("Project ID: %d, Name: %s, Public: %v\n", project.ProjectID, project.Name, project.Metadata.Public)
}
marshal, _ := json.Marshal(projects)
return true, []string{
fmt.Sprintf("List Projects of %s ", hOp.TargetHarborHost),
string(marshal),
}
}
func (hOp *HarborOperator) SyncProjectExec(funcArgs []string) (bool, []string) {
if hOp.TargetHarborClient == nil {
ok, createClient := hOp.CheckAndBuildHarborClient(funcArgs[0], "", true)
if !ok {
return false, []string{
"[Harbor Sync Project ] - Error !",
}
}
hOp.TargetHarborClient = createClient
}
targetClient := hOp.TargetHarborClient
if hOp.SourceHarborClient == nil {
realHost := funcArgs[1]
realPort := ""
if strings.Contains(funcArgs[1], ":") {
split := strings.Split(funcArgs[1], ":")
realHost = split[0]
realPort = split[1]
}
ok, createClient := hOp.CheckAndBuildHarborClient(realHost, realPort, false)
if !ok {
return false, []string{
"[Harbor Sync Project ] - Error !",
}
}
hOp.SourceHarborClient = createClient
}
needToSynchronizedProject := funcArgs[2]
log.InfoF("[Harbor Sync Project ] - start to sync harbor project => %s", needToSynchronizedProject)
log.DebugF("[Harbor Sync Project ] - start to check projects all exists!")
ctx := context.Background()
// check both source and target harbor project exists
needToCreateProjectNameList := []string{"rancher", "cmii"}
for _, projectName := range needToCreateProjectNameList {
syncNotExistHarborProjectError := []string{
"[Harbor Sync Project ] - project not exists !",
}
exists, _ := targetClient.ProjectExists(ctx, projectName)
if !exists {
return false, append(syncNotExistHarborProjectError, "targetClient")
}
}
OctopusSourceHarborName := "octopus-source"
// add source registry to destination harbor
log.InfoF("[Harbor Sync Project ] - start to create source harbor endpoints => %s", hOp.SourceHarborHost)
log.Debug("[Harbor Sync Project ] - start to delete exist replication policy !")
policies, _ := targetClient.ListReplicationPolicies(ctx)
if policies != nil {
for _, policy := range policies {
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)
}
}
}
}
log.Debug("[Harbor Sync Project ] - start to delete exist exist harbor endpoints !")
exitRegistry, _ := targetClient.GetRegistryByName(ctx, OctopusSourceHarborName)
if exitRegistry != nil {
log.Debug("[Harbor Sync Project ] - source endpoints already exists ! delete it !")
err := targetClient.DeleteRegistryByID(ctx, exitRegistry.ID)
if err != nil {
log.ErrorF("[Harbor Sync Project ] - source endpoints delete failed ! => %v ", exitRegistry)
}
}
// todo cqga failed
octopusSourceRegistry := &model.Registry{
Credential: &model.RegistryCredential{
AccessKey: "admin",
AccessSecret: "V2ryStr@ngPss",
Type: "basic",
},
Insecure: true,
Name: OctopusSourceHarborName, // 源 Harbor 实例的注册表 ID通常为 0
Type: "harbor",
URL: strings.Split(hOp.SourceHarborHost, "/api")[0],
}
err := targetClient.NewRegistry(ctx, octopusSourceRegistry)
if err != nil {
sprintf := fmt.Sprintf("[SyncProjectExec] - source endpoints create failed ! => %s", err.Error())
log.Error(sprintf)
return false, []string{sprintf}
}
// get the real one for it's ID
realOctopusSourceRegistry, err := targetClient.GetRegistryByName(ctx, OctopusSourceHarborName)
if err != nil {
sprintf := fmt.Sprintf("[SyncProjectExec] - get target registry id failed ! => %s", err.Error())
log.Error(sprintf)
return false, []string{sprintf}
}
// 创建复制策略
octopusReplicationPolicy := &model.ReplicationPolicy{
CopyByChunk: nil,
Deletion: false,
Description: "",
DestNamespace: "", // 可以指定目标 Harbor 中的特定项目,如果为空,则使用源项目名称
DestNamespaceReplaceCount: nil,
SrcRegistry: &model.Registry{
ID: realOctopusSourceRegistry.ID,
},
DestRegistry: &model.Registry{
ID: 0,
},
Enabled: true,
Filters: []*model.ReplicationFilter{
{
Type: "name",
Value: needToSynchronizedProject + "/**",
},
},
ID: 0,
Name: OctopusReplicationPolicyName,
Override: true,
ReplicateDeletion: false,
Speed: nil,
Trigger: &model.ReplicationTrigger{
Type: "manual", // 可以是 "manual", "scheduled", 或 "event_based"
// 如果是 "scheduled",还需要设置 Cron 表达式
// TriggerSettings: &model.TriggerSettings{Cron: "0 * * * *"},
},
}
// 在源 Harbor 中创建复制策略
log.InfoF("[Harbor Sync Project ] - Start To Sync Project => %s !", needToSynchronizedProject)
err = targetClient.NewReplicationPolicy(ctx, octopusReplicationPolicy.DestRegistry, octopusReplicationPolicy.SrcRegistry, octopusReplicationPolicy.Deletion, octopusReplicationPolicy.Override, octopusReplicationPolicy.Enabled, octopusReplicationPolicy.Filters, octopusReplicationPolicy.Trigger, octopusReplicationPolicy.DestNamespace, octopusReplicationPolicy.Name, octopusReplicationPolicy.Name)
if err != nil {
syncErrorMessage := fmt.Sprintf("[Harbor Sync Project ] - Sync Project [ %s ] Failed ! Error is => %s\n", needToSynchronizedProject, err.Error())
log.Error(syncErrorMessage)
return false, []string{
syncErrorMessage,
}
}
realOctopusReplicationPolicy, err := targetClient.GetReplicationPolicyByName(ctx, OctopusReplicationPolicyName)
if err != nil {
return false, []string{
"[Harbor Sync Project ] - failed to get the realOctopusReplicationPolicy!",
err.Error(),
}
}
err = targetClient.TriggerReplicationExecution(ctx, &model.StartReplicationExecution{
PolicyID: realOctopusReplicationPolicy.ID,
})
if err != nil {
return false, []string{
"[ Harbor Sync Project ] - failed to start the harbor sync execution !",
err.Error(),
}
}
return true, []string{
fmt.Sprintf("[ Harbor Sync Project ] - sync project [ %s ] started !", needToSynchronizedProject),
}
}
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") {
bytes, _ := json.Marshal(execution)
log.InfoF("[sync status]- status are => %v", string(bytes))
// report status
return false, []string{
fmt.Sprintf("[sync status] - not complete ! progress is => %s %%",
strconv.FormatFloat(float64(execution.Succeed)/float64(execution.Total)*100, 'f', 2, 64)),
}
}
}
return true, []string{
"[sync status]- sync completed !",
}
}
func (hOp *HarborOperator) Command(baseFuncName string, funcArgs ...string) []string {
return nil
}