From 5bbda8f8420cd390b83f7f57efd6f6e0af63af84 Mon Sep 17 00:00:00 2001 From: zhengkunwang <31820853+zhengkunwang223@users.noreply.github.com> Date: Fri, 11 Aug 2023 15:52:13 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E5=BA=94=E7=94=A8?= =?UTF-8?q?=E5=8D=87=E7=BA=A7=E9=95=9C=E5=83=8F=E6=8B=89=E5=8F=96=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E5=AF=BC=E8=87=B4=E5=BA=94=E7=94=A8=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E7=9A=84=E9=97=AE=E9=A2=98=20(#1921)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/service/app_utils.go | 38 ++++++++++++++++++++++++++++++++ backend/buserr/errors.go | 15 +++++++++++++ backend/i18n/lang/en.yaml | 1 + backend/i18n/lang/zh-Hant.yaml | 1 + backend/i18n/lang/zh.yaml | 1 + backend/utils/docker/compose.go | 22 ------------------ backend/utils/docker/docker.go | 28 +++++++++++++++++++++++ 7 files changed, 84 insertions(+), 22 deletions(-) diff --git a/backend/app/service/app_utils.go b/backend/app/service/app_utils.go index b86175834..b3bbb4224 100644 --- a/backend/app/service/app_utils.go +++ b/backend/app/service/app_utils.go @@ -341,6 +341,24 @@ func upgradeInstall(installId uint, detailId uint, backup bool) error { install.Version = detail.Version install.AppDetailId = detailId + images, err := getImages(install) + if err != nil { + upErr = err + return + } + dockerCli, err := composeV2.NewClient() + if err != nil { + upErr = err + return + } + + for _, image := range images { + if err = dockerCli.PullImage(image, true); err != nil { + upErr = buserr.WithNameAndErr("ErrDockerPullImage", "", err) + return + } + } + if out, err := compose.Down(install.GetComposePath()); err != nil { if out != "" { upErr = errors.New(out) @@ -398,6 +416,26 @@ func getContainerNames(install model.AppInstall) ([]string, error) { return containerNames, nil } +func getImages(install model.AppInstall) ([]string, error) { + envStr, err := coverEnvJsonToStr(install.Env) + if err != nil { + return nil, err + } + project, err := composeV2.GetComposeProject(install.Name, install.GetPath(), []byte(install.DockerCompose), []byte(envStr), true) + if err != nil { + return nil, err + } + imagesMap := make(map[string]struct{}) + for _, service := range project.AllServices() { + imagesMap[service.Image] = struct{}{} + } + var images []string + for k := range imagesMap { + images = append(images, k) + } + return images, nil +} + func coverEnvJsonToStr(envJson string) (string, error) { envMap := make(map[string]interface{}) _ = json.Unmarshal([]byte(envJson), &envMap) diff --git a/backend/buserr/errors.go b/backend/buserr/errors.go index 67a57dc1b..15fed1a8e 100644 --- a/backend/buserr/errors.go +++ b/backend/buserr/errors.go @@ -61,3 +61,18 @@ func WithMap(Key string, maps map[string]interface{}, err error) BusinessError { Err: err, } } + +func WithNameAndErr(Key string, name string, err error) BusinessError { + paramMap := map[string]interface{}{} + if name != "" { + paramMap["name"] = name + } + if err != nil { + paramMap["err"] = err.Error() + } + return BusinessError{ + Msg: Key, + Map: paramMap, + Err: err, + } +} diff --git a/backend/i18n/lang/en.yaml b/backend/i18n/lang/en.yaml index 66ccb7139..9f7734c64 100644 --- a/backend/i18n/lang/en.yaml +++ b/backend/i18n/lang/en.yaml @@ -45,6 +45,7 @@ ErrImagePullTimeOut: 'Image pull timeout' ErrContainerNotFound: '{{ .name }} container does not exist' ErrContainerMsg: '{{ .name }} container is abnormal, please check the log on the container page for details' ErrAppBackup: '{{ .name }} application backup failed err {{.err}}' +ErrImagePull: '{{ .name }} image pull failed err {{.err}}' #file ErrFileCanNotRead: "File can not read" diff --git a/backend/i18n/lang/zh-Hant.yaml b/backend/i18n/lang/zh-Hant.yaml index 1d9e4312d..76741de93 100644 --- a/backend/i18n/lang/zh-Hant.yaml +++ b/backend/i18n/lang/zh-Hant.yaml @@ -45,6 +45,7 @@ ErrImagePullTimeOut: "鏡像拉取超時" ErrContainerNotFound: '{{ .name }} 容器不存在' ErrContainerMsg: '{{ .name }} 容器異常,具體請在容器頁面查看日誌' ErrAppBackup: '{{ .name }} 應用備份失敗 err {{.err}}' +ErrImagePull: '{{ .name }} 鏡像拉取失敗 err {{.err}}' #file ErrFileCanNotRead: "此文件不支持預覽" diff --git a/backend/i18n/lang/zh.yaml b/backend/i18n/lang/zh.yaml index 5437b6f1c..81b43f24a 100644 --- a/backend/i18n/lang/zh.yaml +++ b/backend/i18n/lang/zh.yaml @@ -45,6 +45,7 @@ ErrImagePullTimeOut: '镜像拉取超时' ErrContainerNotFound: '{{ .name }} 容器不存在' ErrContainerMsg: '{{ .name }} 容器异常,具体请在容器页面查看日志' ErrAppBackup: '{{ .name }} 应用备份失败 err {{.err}}' +ErrImagePull: '镜像拉取失败 {{.err}}' #file ErrFileCanNotRead: "此文件不支持预览" diff --git a/backend/utils/docker/compose.go b/backend/utils/docker/compose.go index 730df21c1..c7a1c5a85 100644 --- a/backend/utils/docker/compose.go +++ b/backend/utils/docker/compose.go @@ -4,11 +4,7 @@ import ( "context" "github.com/compose-spec/compose-go/loader" "github.com/compose-spec/compose-go/types" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/flags" "github.com/docker/compose/v2/pkg/api" - "github.com/docker/compose/v2/pkg/compose" - "github.com/docker/docker/client" "github.com/joho/godotenv" "path" "regexp" @@ -21,24 +17,6 @@ type ComposeService struct { project *types.Project } -func NewComposeService(ops ...command.DockerCliOption) (*ComposeService, error) { - apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - if err != nil { - return nil, err - } - ops = append(ops, command.WithAPIClient(apiClient), command.WithDefaultContextStoreConfig()) - cli, err := command.NewDockerCli(ops...) - if err != nil { - return nil, err - } - cliOp := flags.NewClientOptions() - if err := cli.Initialize(cliOp); err != nil { - return nil, err - } - service := compose.NewComposeService(cli) - return &ComposeService{service, nil}, nil -} - func (s *ComposeService) SetProject(project *types.Project) { s.project = project for i, s := range project.Services { diff --git a/backend/utils/docker/docker.go b/backend/utils/docker/docker.go index 1c436c420..1d881a3da 100644 --- a/backend/utils/docker/docker.go +++ b/backend/utils/docker/docker.go @@ -72,6 +72,22 @@ func (c Client) DeleteImage(imageID string) error { return nil } +func (c Client) PullImage(imageName string, force bool) error { + if !force { + exist, err := c.CheckImageExist(imageName) + if err != nil { + return err + } + if exist { + return nil + } + } + if _, err := c.cli.ImagePull(context.Background(), imageName, types.ImagePullOptions{}); err != nil { + return err + } + return nil +} + func (c Client) GetImageIDByName(imageName string) (string, error) { filter := filters.NewArgs() filter.Add("reference", imageName) @@ -87,6 +103,18 @@ func (c Client) GetImageIDByName(imageName string) (string, error) { return "", nil } +func (c Client) CheckImageExist(imageName string) (bool, error) { + filter := filters.NewArgs() + filter.Add("reference", imageName) + list, err := c.cli.ImageList(context.Background(), types.ImageListOptions{ + Filters: filter, + }) + if err != nil { + return false, err + } + return len(list) > 0, nil +} + func (c Client) NetworkExist(name string) bool { var options types.NetworkListOptions options.Filters = filters.NewArgs(filters.Arg("name", name))