package executor import ( "context" "encoding/json" "fmt" "net" "os" "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() 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 } return resultOk, resultLog } func (hOp *HarborOperator) CreateProjectExec(funcArgs []string) (bool, []string) { if hOp.TargetHarborClient == nil { ok, createClient := hOp.CheckAndBuildHarborClient(funcArgs[0]) 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"} var err error // 使用客户端创建项目 ctx := context.Background() for _, projectName := range needToCreateProjectNameList { log.DebugF("start to create => %s", projectName) projectReq := &model.ProjectReq{ ProjectName: projectName, // 仓库名称 Metadata: &model.ProjectMetadata{ Public: "true", // 是否是公开的 }, } exists, _ := client.ProjectExists(ctx, projectName) if exists { log.DebugF("[Harbor Create Project] - Project %s already exists ! continue ", projectName) continue } err = client.NewProject(ctx, projectReq) if err != nil { errorLog := fmt.Sprintf("Error creating project %s: %s\n", projectName, err.Error()) return false, []string{errorLog} } } successLog := "[Harbor CreateProjectExec] - Project Create Success !" log.Info(successLog) return true, []string{successLog} } func (hOp *HarborOperator) CheckAndBuildHarborClient(targetHarborHost string) (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 } hOp.TargetHarborHost = "http://" + targetHarborHost + ":" + hOp.HarborPort + "/api/" log.DebugF("[Harbor Client Create] - harbor host is => %s", hOp.TargetHarborHost) // check connection client, err := apiv2.NewRESTClientForHost(hOp.TargetHarborHost, 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]) 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]) if !ok { return false, []string{ "[Harbor Sync Project ] - Error !", } } hOp.TargetHarborClient = createClient } targetClient := hOp.TargetHarborClient if hOp.SourceHarborClient == nil { ok, createClient := hOp.CheckAndBuildHarborClient(funcArgs[1]) if !ok { return false, []string{ "[Harbor Sync Project ] - Error !", } } hOp.SourceHarborClient = createClient } sourceClient := hOp.SourceHarborClient log.DebugF("[Harbor Sync Project ] - start to check projects all exists!") ctx := context.Background() // check both source and target harbor project exists needToCreateProjectNameList := []string{"cmii", "rancher"} for _, projectName := range needToCreateProjectNameList { syncNotExistHarborProjectError := []string{ "[Harbor Sync Project ] - project not exists !", } exists, _ := targetClient.ProjectExists(ctx, projectName) if !exists { return false, append(syncNotExistHarborProjectError, "targetClient") } projectExists, _ := sourceClient.ProjectExists(ctx, projectName) if !projectExists { return false, append(syncNotExistHarborProjectError, "sourceClient") } } // 创建复制策略 newPolicy := &model.ReplicationPolicy{ Name: "sync-repositories-to-target", Enabled: true, Deletion: false, Override: true, SrcRegistry: &model.Registry{ Name: "cmii", // 源 Harbor 实例的注册表 ID,通常为 0 }, DestRegistry: &model.Registry{ Name: "cmii", // 目标 Harbor 实例的注册表 ID,需要根据实际情况设置 }, DestNamespace: "", // 可以指定目标 Harbor 中的特定项目,如果为空,则使用源项目名称 Trigger: &model.ReplicationTrigger{ Type: "manual", // 可以是 "manual", "scheduled", 或 "event_based" // 如果是 "scheduled",还需要设置 Cron 表达式 // TriggerSettings: &model.TriggerSettings{Cron: "0 * * * *"}, }, //Filters: []*model.ReplicationFilter{ // { // Type: "name", // Value: "cmii/**", // 根据需要同步的仓库进行调整 // }, // { // Type: "name", // Value: "rancher/**", // 根据需要同步的仓库进行调整 // }, //}, Filters: nil, } // 在源 Harbor 中创建复制策略 log.Info("[Harbor Sync Project ] - Start To Sync Project !") err := sourceClient.NewReplicationPolicy(ctx, newPolicy.DestRegistry, newPolicy.SrcRegistry, newPolicy.Deletion, newPolicy.Override, newPolicy.Enabled, newPolicy.Filters, newPolicy.Trigger, newPolicy.DestNamespace, newPolicy.Name, newPolicy.Name) if err != nil { syncErrorMessage := fmt.Sprintf("[Harbor Sync Project ] - Sync Project Failed !: %s\n", err.Error()) log.Error(syncErrorMessage) return false, []string{ syncErrorMessage, } } return true, nil } func (hOp *HarborOperator) Command(baseFuncName string, funcArgs ...string) []string { return nil }