diff --git a/pkg/addon/cache.go b/pkg/addon/cache.go index aa25087ed..142b4b564 100644 --- a/pkg/addon/cache.go +++ b/pkg/addon/cache.go @@ -19,12 +19,12 @@ package addon import ( "context" "fmt" + "strings" "sync" "time" - "github.com/oam-dev/kubevela/pkg/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/log" + "github.com/oam-dev/kubevela/pkg/utils" ) // We have three addon layer here @@ -119,28 +119,27 @@ func (u *Cache) GetUIData(r Registry, addonName, version string) (*UIData, error // ListUIData will always list UIData from cache first, if not exist, read from source. func (u *Cache) ListUIData(r Registry) ([]*UIData, error) { var err error - listAddons := u.listCachedUIData(r.Name) - if listAddons != nil { - return listAddons, nil - } + var listAddons []*UIData if !IsVersionRegistry(r) { - addonMeta, err := u.ListAddonMeta(r) + listAddons = u.listCachedUIData(r.Name) + if listAddons != nil { + return listAddons, nil + } + listAddons, err = u.listUIDataAndCache(r) if err != nil { return nil, err } - listAddons, err = r.ListUIData(addonMeta, UIMetaOptions) - if err != nil { - return nil, fmt.Errorf("fail to get addons from registry %s, %w", r.Name, err) - } } else { - versionedRegistry := BuildVersionedRegistry(r.Name, r.Helm.URL) - listAddons, err = versionedRegistry.ListAddon() + listAddons = u.listVersionRegistryCachedUIData(r.Name) + if listAddons != nil { + return listAddons, nil + } + listAddons, err = u.listVersionRegistryUIDataAndCache(r) if err != nil { - log.Logger.Errorf("fail to get addons from registry %s for cache updating, %v", r.Name, err) return nil, err } } - u.putAddonUIData2Cache(r.Name, listAddons) + return listAddons, nil } @@ -175,6 +174,27 @@ func (u *Cache) listCachedUIData(name string) []*UIData { return d } +// listVersionRegistryCachedUIData will get cached addons from specified VersionRegistry in cache +func (u *Cache) listVersionRegistryCachedUIData(name string) []*UIData { + if u == nil { + return nil + } + u.mutex.RLock() + defer u.mutex.RUnlock() + d, ok := u.versionedUIData[name] + if !ok { + return nil + } + var uiDatas []*UIData + for version, uiData := range d { + if !strings.Contains(version, "-latest") { + uiDatas = append(uiDatas, uiData) + } + } + + return uiDatas +} + // getCachedAddonMeta will get cached registry meta from specified registry in cache func (u *Cache) getCachedAddonMeta(name string) map[string]SourceMeta { if u == nil { @@ -260,35 +280,51 @@ func (u *Cache) discoverAndRefreshRegistry() { for _, r := range registries { if !IsVersionRegistry(r) { - registryMeta, err := r.ListAddonMeta() + _, err = u.listUIDataAndCache(r) if err != nil { - log.Logger.Errorf("fail to list registry %s metadata, %v", r.Name, err) continue } - u.putAddonMeta2Cache(r.Name, registryMeta) - uiData, err := r.ListUIData(registryMeta, UIMetaOptions) - if err != nil { - log.Logger.Errorf("fail to get addons from registry %s for cache updating, %v", r.Name, err) - continue - } - u.putAddonUIData2Cache(r.Name, uiData) } else { - versionedRegistry := BuildVersionedRegistry(r.Name, r.Helm.URL) - uiDatas, err := versionedRegistry.ListAddon() + _, err = u.listVersionRegistryUIDataAndCache(r) if err != nil { - log.Logger.Errorf("fail to get addons from registry %s for cache updating, %v", r.Name, err) continue } - for _, addon := range uiDatas { - uiData, err := versionedRegistry.GetAddonUIData(context.Background(), addon.Name, addon.Version) - if err != nil { - log.Logger.Errorf("fail to get addon from registry %s, addon %s version %s for cache updating, %v", r.Name, addon.Name, addon.Version, err) - continue - } - u.putVersionedUIData2Cache(r.Name, addon.Name, addon.Version, uiData) - // we also no version key, if use get addonUIData without version will return this vale as latest data. - u.putVersionedUIData2Cache(r.Name, addon.Name, "latest", uiData) - } } } } + +func (u *Cache) listUIDataAndCache(r Registry) ([]*UIData, error) { + registryMeta, err := r.ListAddonMeta() + if err != nil { + log.Logger.Errorf("fail to list registry %s metadata, %v", r.Name, err) + return nil, err + } + u.putAddonMeta2Cache(r.Name, registryMeta) + uiData, err := r.ListUIData(registryMeta, UIMetaOptions) + if err != nil { + log.Logger.Errorf("fail to get addons from registry %s for cache updating, %v", r.Name, err) + return nil, err + } + u.putAddonUIData2Cache(r.Name, uiData) + return uiData, nil +} + +func (u *Cache) listVersionRegistryUIDataAndCache(r Registry) ([]*UIData, error) { + versionedRegistry := BuildVersionedRegistry(r.Name, r.Helm.URL) + uiDatas, err := versionedRegistry.ListAddon() + if err != nil { + log.Logger.Errorf("fail to get addons from registry %s for cache updating, %v", r.Name, err) + return nil, err + } + for _, addon := range uiDatas { + uiData, err := versionedRegistry.GetAddonUIData(context.Background(), addon.Name, addon.Version) + if err != nil { + log.Logger.Errorf("fail to get addon from versioned registry %s, addon %s version %s for cache updating, %v", r.Name, addon.Name, addon.Version, err) + continue + } + u.putVersionedUIData2Cache(r.Name, addon.Name, addon.Version, uiData) + // we also no version key, if use get addonUIData without version will return this vale as latest data. + u.putVersionedUIData2Cache(r.Name, addon.Name, "latest", uiData) + } + return uiDatas, nil +} diff --git a/pkg/addon/cache_test.go b/pkg/addon/cache_test.go index 44ab7e180..4e2816b78 100644 --- a/pkg/addon/cache_test.go +++ b/pkg/addon/cache_test.go @@ -31,3 +31,63 @@ func TestPutVersionedUIData2cache(t *testing.T) { assert.NotEmpty(t, u.versionedUIData["helm-repo"]["fluxcd-1.0.0"]) assert.Equal(t, u.versionedUIData["helm-repo"]["fluxcd-1.0.0"].Name, "fluxcd") } + +func TestPutAddonUIData2Cache(t *testing.T) { + uiData := UIData{Meta: Meta{Name: "fluxcd", Icon: "test.com/fluxcd.png", Version: "1.0.0"}} + addons := []*UIData{&uiData} + name := "helm-repo" + u := NewCache(nil) + u.putAddonUIData2Cache(name, addons) + assert.NotEmpty(t, u.uiData) + assert.Equal(t, u.uiData[name], addons) +} + +func TestListCachedUIData(t *testing.T) { + uiData := UIData{Meta: Meta{Name: "fluxcd", Icon: "test.com/fluxcd.png", Version: "1.0.0"}} + addons := []*UIData{&uiData} + name := "helm-repo" + u := NewCache(nil) + u.putAddonUIData2Cache(name, addons) + + assert.Equal(t, u.listCachedUIData(name), addons) +} + +func TestPutAddonMeta2Cache(t *testing.T) { + addonMeta := map[string]SourceMeta{ + "fluxcd": { + Name: "fluxcd", + Items: []Item{ + &OSSItem{ + tp: FileType, + path: "fluxcd/definitions/helm-release.yaml", + name: "helm-release.yaml", + }, + }, + }, + } + name := "helm-repo" + u := NewCache(nil) + u.putAddonMeta2Cache(name, addonMeta) + assert.NotEmpty(t, u.registryMeta) + assert.Equal(t, u.registryMeta[name], addonMeta) +} + +func TestGetCachedAddonMeta(t *testing.T) { + addonMeta := map[string]SourceMeta{ + "fluxcd": { + Name: "fluxcd", + Items: []Item{ + &OSSItem{ + tp: FileType, + path: "fluxcd/definitions/helm-release.yaml", + name: "helm-release.yaml", + }, + }, + }, + } + name := "helm-repo" + u := NewCache(nil) + u.putAddonMeta2Cache(name, addonMeta) + + assert.Equal(t, u.getCachedAddonMeta(name), addonMeta) +} diff --git a/test/e2e-multicluster-test/suite_test.go b/test/e2e-multicluster-test/suite_test.go index b54ba68d1..8ce394ce7 100644 --- a/test/e2e-multicluster-test/suite_test.go +++ b/test/e2e-multicluster-test/suite_test.go @@ -79,6 +79,8 @@ var _ = AfterSuite(func() { for _, app := range apps.Items { g.Expect(k8sClient.Delete(context.Background(), app.DeepCopy())).Should(Succeed()) } + err := k8sClient.List(context.Background(), apps) + g.Expect(err, nil) g.Expect(len(apps.Items)).Should(Equal(0)) }, 3*time.Minute).Should(Succeed()) Eventually(func(g Gomega) {