Skip to content

feat: async latest tag app check is update available #170

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/IceWhaleTech/CasaOS-AppManagement
go 1.21

require (
github.com/bluele/gcache v0.0.2
github.com/deepmap/oapi-codegen v1.12.4
github.com/docker/compose/v2 v2.23.3
github.com/docker/distribution v2.8.2+incompatible
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,8 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1U
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw=
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY=
Expand Down
54 changes: 37 additions & 17 deletions service/compose_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"time"

v1 "github.com/IceWhaleTech/CasaOS-AppManagement/service/v1"
"github.com/bluele/gcache"

"github.com/IceWhaleTech/CasaOS-AppManagement/codegen"
"github.com/IceWhaleTech/CasaOS-AppManagement/common"
Expand Down Expand Up @@ -189,6 +190,11 @@ func (a *ComposeApp) IsUpdateAvailable() bool {
return a.IsUpdateAvailableWith(storeComposeApp)
}

var latestIsUpdateAvailableCache = gcache.New(100).
LRU().
Expiration(1 * time.Hour).
Build()

func (a *ComposeApp) IsUpdateAvailableWith(storeComposeApp *ComposeApp) bool {
storeComposeAppStoreInfo, err := storeComposeApp.StoreInfo(false)
if err != nil || storeComposeAppStoreInfo == nil {
Expand All @@ -208,29 +214,43 @@ func (a *ComposeApp) IsUpdateAvailableWith(storeComposeApp *ComposeApp) bool {

// TODO to async the check for consist with the version tag app
if mainAppTag == "latest" {
// check image digest when tag is latest.
ctx := context.Background()
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
defer cli.Close()
isUpdateAvailable, err := latestIsUpdateAvailableCache.Get(mainAppImage)
if err != nil {
go func() {
// check image digest when tag is latest.
ctx := context.Background()
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
logger.Error("failed to create docker client", zap.Error(err))
}
defer cli.Close()

imageInfo, _, err := cli.ImageInspectWithRaw(ctx, mainAppImage)
imageInfo, _, err := cli.ImageInspectWithRaw(ctx, mainAppImage)

if err != nil {
logger.Error("failed to inspect image", zap.Error(err), zap.String("name", mainAppImage))
latestIsUpdateAvailableCache.Set(mainAppImage, false)
}
match, err := docker.CompareDigest(storeComposeApp.Services[0].Image, imageInfo.RepoDigests)
if err != nil {
logger.Error("failed to compare digest", zap.Error(err), zap.String("name", mainAppImage))
latestIsUpdateAvailableCache.Set(mainAppImage, false)
}
if match {
logger.Info("main app image tag is latest, thus no update available", zap.String("image", mainApp.Image))
latestIsUpdateAvailableCache.Set(mainAppImage, false)
} else {
logger.Info("main app image tag is latest, but digest is different, thus update is available", zap.String("image", mainApp.Image))
latestIsUpdateAvailableCache.Set(mainAppImage, true)
}
}()

if err != nil {
logger.Error("failed to inspect image", zap.Error(err), zap.String("name", mainAppImage))
return false
}
match, err := docker.CompareDigest(storeComposeApp.Services[0].Image, imageInfo.RepoDigests)
if err != nil {
logger.Error("failed to compare digest", zap.Error(err), zap.String("name", mainAppImage))
return false
}
if match {
logger.Info("main app image tag is latest, thus no update available", zap.String("image", mainApp.Image))
return false
} else {
logger.Info("main app image tag is latest, but digest is different, thus update is available", zap.String("image", mainApp.Image))
if isUpdateAvailable.(bool) {
return true
}
return false
}

storeMainApp := storeComposeApp.App(mainAppName)
Expand Down
Loading