Files
ProjectOctopus/agent-operator/CmiiOperator.go
2024-04-17 16:42:02 +08:00

380 lines
14 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"errors"
"io/fs"
"os"
"path/filepath"
"slices"
"strings"
image2 "wdd.io/agent-common/image"
"wdd.io/agent-common/utils"
"wdd.io/agent-operator/image"
)
const OfflineImageGzipFolderPrefix = "/root/octopus_image/"
const OfflineDeployHarborHost = "harbor.wdd.io"
const PublicDeployHarborHost = "42.192.52.227"
const DirectPushDeployHarborHost = "36.134.71.138"
type ImageSyncEntity struct {
ProjectName string // 优先级3
ProjectVersion string // 优先级2
CmiiNameTagList []string // 优先级1 appName:tag的形式
FullNameImageList []string // 优先级1
DownloadImage bool // 下载镜像
CompressImageToGzip bool // 压缩镜像
UploadToDemoMinio bool // 上传镜像
ShouldDirectPushToHarbor bool // 直接推送到对方的主机 || 离线部署机 使用此部门
DirectHarborHost string // 目标Harbor仓库的Host全名称带端口 不带http前缀
}
type ImageSyncResult struct {
ErrorPullImageList []string
ErrorGzipImageList []string
ErrorPushImageNameList []string
RealImageNameList []string
RealGzipFileNameList []string
AllCmiiImageNameList []string
}
// PullFromEntityAndSyncConditionally 根据ImageSyncEntity拉取特定的镜像然后上传到特定的目标机器(或者上传的minio中)
func (sync ImageSyncEntity) PullFromEntityAndSyncConditionally() (imageSyncResult ImageSyncResult) {
var realCmiiImageList []string
var allCmiiImageNameList []string
var errorPullImageList []string
var allGzipFileNameList []string
var errorGzipImageList []string
var errorPushImageNameList []string
var gzipFolderFullPath string
if (sync.CmiiNameTagList == nil && sync.FullNameImageList == nil) || (len(sync.CmiiNameTagList) == 0 && len(sync.FullNameImageList) == 0) {
// 没有指定特定的镜像,那么根据 ProjectVersion 或者从DEMO拉取镜像
// pull images
// compress
if sync.ProjectVersion != "" {
// get version
if sync.DirectHarborHost == "" {
errorPullImageList, errorGzipImageList, allCmiiImageNameList = DownloadCompressUploadFromVersion(sync.ProjectVersion, true, sync.UploadToDemoMinio)
gzipFolderFullPath = OfflineImageGzipFolderPrefix + sync.ProjectVersion
} else {
errorPullImageList, errorGzipImageList, allCmiiImageNameList = DownloadCompressUploadFromVersion(sync.ProjectVersion, false, sync.UploadToDemoMinio)
}
} else {
// get demo images
if sync.DirectHarborHost == "" {
errorPullImageList, errorGzipImageList, allCmiiImageNameList = DownloadCompressUploadFromDemo(sync.ProjectName, sync.CompressImageToGzip, sync.UploadToDemoMinio)
gzipFolderFullPath = OfflineImageGzipFolderPrefix + sync.ProjectName
} else {
errorPullImageList, errorGzipImageList, allCmiiImageNameList = DownloadCompressUploadFromDemo(sync.ProjectName, false, sync.UploadToDemoMinio)
}
}
} else {
// 拉取特定的镜像
gzipFolderFullPath = OfflineImageGzipFolderPrefix + "tmp"
// 组装镜像名称
allCmiiImageNameList = concatAndUniformCmiiImage(sync.FullNameImageList, sync.CmiiNameTagList)
// DCU
errorPullImageList, errorGzipImageList, realCmiiImageList, allGzipFileNameList = DownloadCompressUploadFromFullNameList(allCmiiImageNameList, sync.CompressImageToGzip, gzipFolderFullPath, sync.UploadToDemoMinio)
}
// 直接传输到目标Harbor仓库
if sync.ShouldDirectPushToHarbor {
if sync.DirectHarborHost == "" {
log.ErrorF("DirectHarborHost is null ! can't push to target harbor !")
}
// push to
errorPushImageNameList = image.TagFromListAndPushToCHarbor(realCmiiImageList, sync.DirectHarborHost)
}
// build result
imageSyncResult.AllCmiiImageNameList = allCmiiImageNameList
imageSyncResult.RealImageNameList = realCmiiImageList
imageSyncResult.ErrorPullImageList = errorPullImageList
imageSyncResult.RealGzipFileNameList = allGzipFileNameList
imageSyncResult.ErrorGzipImageList = errorGzipImageList
imageSyncResult.ErrorPushImageNameList = errorPushImageNameList
return imageSyncResult
}
func concatAndUniformCmiiImage(fullImageList []string, cmiiImageList []string) []string {
if cmiiImageList != nil || len(cmiiImageList) > 0 {
// cmiiImageList has content
if fullImageList == nil {
fullImageList = []string{}
}
for _, cmiiImage := range cmiiImageList {
fullImageList = append(fullImageList, image2.CmiiHarborPrefix+cmiiImage)
}
}
return fullImageList
}
func DownloadCompressUploadFromFullNameList(fullNameList []string, shouldGzip bool, gzipFolderFullPath string, shouldOss bool) (errorPullImageList, errorGzipImageList, realCmiiImageName, allGzipFileNameList []string) {
// Download
log.Info("DOWNLOAD START !")
errorPullImageList = image.PullFromFullNameList(fullNameList)
// remove failed
fullNameList = slices.DeleteFunc(fullNameList, func(imageName string) bool {
return slices.Contains(errorPullImageList, imageName)
})
// Compress
if shouldGzip {
// mkdir folder
err := os.MkdirAll(gzipFolderFullPath, os.ModeDir)
if err != nil {
if !errors.Is(err, os.ErrExist) {
log.ErrorF("create folder error of %s", gzipFolderFullPath)
panic(err)
}
}
// 循环遍历压缩
log.Info("COMPRESS START")
for _, imageFullName := range fullNameList {
if !image.SaveToTarGZ(imageFullName, gzipFolderFullPath) {
errorGzipImageList = append(errorGzipImageList, imageFullName)
}
}
// remove failed
fullNameList = slices.DeleteFunc(fullNameList, func(imageName string) bool {
return slices.Contains(errorGzipImageList, imageName)
})
}
// Upload
if shouldOss {
//uploadGzipFileToDemoMinio()
// get gzip file name list
log.Info("UPLOAD OSS START !")
err := filepath.WalkDir(gzipFolderFullPath, func(path string, d fs.DirEntry, err error) error {
if err != nil {
log.ErrorF("error getting gzip file name list 1! %s", err.Error())
}
if !d.IsDir() {
allGzipFileNameList = append(allGzipFileNameList, d.Name())
}
return nil
})
if err != nil {
log.ErrorF("error getting gzip file name list 2! %s", err.Error())
}
// start to upload
// extract demo oss location suffix from gzipFolderFullPath
trimPrefix := strings.TrimPrefix(gzipFolderFullPath, OfflineImageGzipFolderPrefix)
bucketName := "cmlc-installation/" + trimPrefix
log.InfoF("gzip file location in demo oss is %s", DemoEndpoint+"/"+bucketName)
minioOperator := CmiiMinioOperator{}
for _, gzipFileName := range allGzipFileNameList {
if !minioOperator.UploadToDemo(bucketName, gzipFolderFullPath, gzipFileName) {
log.ErrorF("upload of %s to demo oss error !", gzipFolderFullPath+gzipFileName)
}
}
}
return errorPullImageList, errorGzipImageList, fullNameList, allGzipFileNameList
}
func uploadGzipFileToDemoMinio() {
}
// DownloadCompressUploadFromDemo 获取DEMO环境的全部镜像
func DownloadCompressUploadFromDemo(projectName string, shouldGzip bool, shouldOss bool) (errorPullImageList, errorGzipImageList, realCmiiImageName []string) {
// generate a project folder
err := os.MkdirAll(OfflineImageGzipFolderPrefix+projectName, os.ModeDir)
if err != nil {
if !errors.Is(err, os.ErrExist) {
log.ErrorF("[Download_Compress_Upload_From_Demo] - create folder of %s error %s", OfflineImageGzipFolderPrefix+projectName, err.Error())
return errorPullImageList, errorGzipImageList, realCmiiImageName
}
}
// get demo image version map
backendMap, frontendMap, srsMap := BackupAllCmiiDeploymentToMap(demo)
utils.BeautifulPrint(backendMap)
utils.BeautifulPrint(frontendMap)
utils.BeautifulPrint(srsMap)
// save map to file
backendMapFile := OfflineImageGzipFolderPrefix + projectName + "-backend-app.json"
frontendMapFile := OfflineImageGzipFolderPrefix + projectName + "-frontend-app.json"
srsMapFile := OfflineImageGzipFolderPrefix + projectName + "-srs-app.json"
_ = os.Remove(backendMapFile)
_ = os.Remove(frontendMapFile)
_ = os.Remove(srsMapFile)
utils.AppendContentToFile(
utils.BeautifulPrintToString(backendMap),
backendMapFile,
)
utils.AppendContentToFile(
utils.BeautifulPrintToString(frontendMap),
frontendMapFile,
)
utils.AppendContentToFile(
utils.BeautifulPrintToString(srsMapFile),
srsMapFile,
)
// download image
backendFullNameList, backendPull := image.PullFromCmiiHarborByMap(backendMap, true)
frontendFullNameList, frontendPull := image.PullFromCmiiHarborByMap(frontendMap, true)
srsFullNameList, srsPull := image.PullFromCmiiHarborByMap(srsMap, true)
realCmiiImageName = append(realCmiiImageName, backendFullNameList...)
realCmiiImageName = append(realCmiiImageName, frontendFullNameList...)
realCmiiImageName = append(realCmiiImageName, srsFullNameList...)
// compress image
if shouldGzip {
for imageName, tag := range backendMap {
if !image.SaveToTarGZ(imageName+":"+tag, OfflineImageGzipFolderPrefix+projectName+"/app/") {
errorGzipImageList = append(errorGzipImageList, image2.CmiiHarborPrefix+imageName+":"+tag)
}
}
for imageName, tag := range frontendMap {
if !image.SaveToTarGZ(imageName+":"+tag, OfflineImageGzipFolderPrefix+projectName+"/app/") {
errorGzipImageList = append(errorGzipImageList, image2.CmiiHarborPrefix+imageName+":"+tag)
}
}
for imageName, tag := range srsMap {
if !image.SaveToTarGZ(imageName+":"+tag, OfflineImageGzipFolderPrefix+projectName+"/app/") {
errorGzipImageList = append(errorGzipImageList, image2.CmiiHarborPrefix+imageName+":"+tag)
}
}
}
// upload to harbor
// clean up images
errorPullImageList = append(errorPullImageList, backendPull...)
errorPullImageList = append(errorPullImageList, frontendPull...)
errorPullImageList = append(errorPullImageList, srsPull...)
return errorPullImageList, errorGzipImageList, realCmiiImageName
}
// DownloadCompressUploadFromVersion 根据版本下载全部的CMII镜像
func DownloadCompressUploadFromVersion(cmiiVersion string, shouldGzip bool, shouldOss bool) (errorPullImageList, errorGzipImageList, realCmiiImageName []string) {
// generate a project folder
err := os.MkdirAll(OfflineImageGzipFolderPrefix+cmiiVersion, os.ModeDir)
if err != nil {
if !errors.Is(err, os.ErrExist) {
log.ErrorF("[Download_Compress_Upload_From_Demo] - create folder of %s error %s", OfflineImageGzipFolderPrefix+cmiiVersion, err.Error())
return errorPullImageList, errorGzipImageList, realCmiiImageName
}
}
backendMap := CmiiBackendAppMap
frontendMap := CmiiFrontendAppMap
for app := range backendMap {
backendMap[app] = cmiiVersion
}
for app := range frontendMap {
frontendMap[app] = cmiiVersion
}
realCmiiImageName = append(realCmiiImageName, image.ConvertCMiiImageMapToList(backendMap)...)
realCmiiImageName = append(realCmiiImageName, image.ConvertCMiiImageMapToList(frontendMap)...)
for key, value := range CmiiSrsAppMap {
var app *CmiiDeploymentInterface
if strings.Contains(value, "deployment") {
app = CmiiOperator.DeploymentOneInterface(demo, key)
if app != nil {
realCmiiImageName = append(realCmiiImageName, app.Image)
}
} else if strings.Contains(value, "state") {
app = CmiiOperator.StatefulSetOneInterface(demo, key)
if app != nil {
for _, imageName := range app.ContainerImageMap {
realCmiiImageName = append(realCmiiImageName, imageName)
}
}
}
}
utils.BeautifulPrintListWithTitle(realCmiiImageName, "Cmii Version Image => "+cmiiVersion)
// do work
if shouldGzip {
errorPullImageList, errorGzipImageList = image.PullFromListAndCompressSplit(realCmiiImageName, OfflineImageGzipFolderPrefix+cmiiVersion)
} else {
errorPullImageList = image.PullFromFullNameList(realCmiiImageName)
}
return errorPullImageList, errorGzipImageList, realCmiiImageName
}
func DownloadCompressUploadDependency(shouldGzip bool, shouldOss bool) (errorPullImageList, errorGzipImageList []string) {
err := os.MkdirAll(OfflineImageGzipFolderPrefix, os.ModeDir)
if err != nil {
if !errors.Is(err, os.ErrExist) {
log.ErrorF("[FetchDependencyRepos] - create folder of %s error %s", OfflineImageGzipFolderPrefix, err.Error())
}
}
// pull middleware images
errorPullImageList, errorGzipImageList = image.PullFromListAndCompressSplit(image.MiddlewareAmd64, OfflineImageGzipFolderPrefix+"middle/")
// pull rke images
pull, gzipImageList := image.PullFromListAndCompressSplit(image.Rancher1204Amd64, OfflineImageGzipFolderPrefix+"rke/")
// result
return append(errorPullImageList, pull...), append(errorGzipImageList, gzipImageList...)
}
func LoadSplitCmiiGzipImageToTargetHarbor(projectName, targetHarborHost string) (errorLoadImageNameList, errorPushImageNameList []string) {
// list folder
projectGzipFolder := OfflineImageGzipFolderPrefix + projectName
errorLoadImageNameList = append(errorLoadImageNameList, image.LoadFromFolderPath(projectGzipFolder)...)
// read from json
errorPushImageNameList = append(errorPushImageNameList, image.TagFromListAndPushToCHarbor(image.Cmii520DemoImageList, targetHarborHost)...)
// re-tag
// push
// todo clean host and harbor
// check harbor exits
return errorLoadImageNameList, errorPushImageNameList
}
func LoadSplitDepGzipImageToTargetHarbor(targetHarborHost string) (errorLoadImageNameList []string, errorPushImageNameList []string) {
//middle := OfflineImageGzipFolderPrefix + "middle/"
//rke := OfflineImageGzipFolderPrefix + "rke/"
//errorLoadImageNameList = append(errorLoadImageNameList, ImageLoadFromFolderPath(middle)...)
//errorLoadImageNameList = append(errorLoadImageNameList, ImageLoadFromFolderPath(rke)...)
errorPushImageNameList = append(errorPushImageNameList, image.TagFromListAndPushToCHarbor(image.MiddlewareAmd64, targetHarborHost)...)
errorPushImageNameList = append(errorPushImageNameList, image.TagFromListAndPushToCHarbor(image.Rancher1204Amd64, targetHarborHost)...)
return errorLoadImageNameList, errorPushImageNameList
}