@@ -3,13 +3,14 @@ package cache
33import (
44 "context"
55 "fmt"
6- "io"
6+ "io/fs "
77 "net/http"
88 "os"
99 "path/filepath"
1010 "sync"
1111
1212 catalogd "github.com/operator-framework/catalogd/api/core/v1alpha1"
13+ "github.com/operator-framework/operator-registry/alpha/declcfg"
1314
1415 "github.com/operator-framework/operator-controller/internal/catalogmetadata/client"
1516)
@@ -66,7 +67,7 @@ type filesystemCache struct {
6667// resources that have been successfully reconciled, unpacked, and are being served.
6768// These requirements help ensure that we can rely on status conditions to determine
6869// when to issue a request to update the cached Catalog contents.
69- func (fsc * filesystemCache ) FetchCatalogContents (ctx context.Context , catalog * catalogd.ClusterCatalog ) (io. ReadCloser , error ) {
70+ func (fsc * filesystemCache ) FetchCatalogContents (ctx context.Context , catalog * catalogd.ClusterCatalog ) (fs. FS , error ) {
7071 if catalog == nil {
7172 return nil , fmt .Errorf ("error: provided catalog must be non-nil" )
7273 }
@@ -80,25 +81,23 @@ func (fsc *filesystemCache) FetchCatalogContents(ctx context.Context, catalog *c
8081 }
8182
8283 cacheDir := filepath .Join (fsc .cachePath , catalog .Name )
83- cacheFilePath := filepath .Join (cacheDir , "data.json" )
84-
8584 fsc .mutex .RLock ()
8685 if data , ok := fsc .cacheDataByCatalogName [catalog .Name ]; ok {
8786 if catalog .Status .ResolvedSource .Image .ResolvedRef == data .ResolvedRef {
8887 fsc .mutex .RUnlock ()
89- return os .Open ( cacheFilePath )
88+ return os .DirFS ( cacheDir ), nil
9089 }
9190 }
9291 fsc .mutex .RUnlock ()
9392
9493 req , err := http .NewRequestWithContext (ctx , http .MethodGet , catalog .Status .ContentURL , nil )
9594 if err != nil {
96- return nil , fmt .Errorf ("error forming request: %s " , err )
95+ return nil , fmt .Errorf ("error forming request: %v " , err )
9796 }
9897
9998 resp , err := fsc .client .Do (req )
10099 if err != nil {
101- return nil , fmt .Errorf ("error performing request: %s " , err )
100+ return nil , fmt .Errorf ("error performing request: %v " , err )
102101 }
103102 defer resp .Body .Close ()
104103
@@ -117,34 +116,49 @@ func (fsc *filesystemCache) FetchCatalogContents(ctx context.Context, catalog *c
117116 // the cached contents
118117 if data , ok := fsc .cacheDataByCatalogName [catalog .Name ]; ok {
119118 if data .ResolvedRef == catalog .Status .ResolvedSource .Image .Ref {
120- return os .Open ( cacheFilePath )
119+ return os .DirFS ( cacheDir ), nil
121120 }
122121 }
123122
124- if err = os .MkdirAll (cacheDir , os .ModePerm ); err != nil {
125- return nil , fmt .Errorf ("error creating cache directory for Catalog %q: %s" , catalog .Name , err )
126- }
127-
128- file , err := os .Create (cacheFilePath )
123+ tmpDir , err := os .MkdirTemp (fsc .cachePath , fmt .Sprintf (".%s-" , catalog .Name ))
129124 if err != nil {
130- return nil , fmt .Errorf ("error creating cache file for Catalog %q : %s" , catalog . Name , err )
125+ return nil , fmt .Errorf ("error creating temporary directory to unpack catalog metadata : %v" , err )
131126 }
132127
133- if _ , err := io .Copy (file , resp .Body ); err != nil {
134- return nil , fmt .Errorf ("error writing contents to cache file for Catalog %q: %s" , catalog .Name , err )
128+ if err := declcfg .WalkMetasReader (resp .Body , func (meta * declcfg.Meta , err error ) error {
129+ if err != nil {
130+ return fmt .Errorf ("error parsing catalog contents: %v" , err )
131+ }
132+ pkgName := meta .Package
133+ if meta .Schema == declcfg .SchemaPackage {
134+ pkgName = meta .Name
135+ }
136+ metaName := meta .Name
137+ if meta .Name == "" {
138+ metaName = meta .Schema
139+ }
140+ metaPath := filepath .Join (tmpDir , pkgName , meta .Schema , metaName + ".json" )
141+ if err := os .MkdirAll (filepath .Dir (metaPath ), os .ModePerm ); err != nil {
142+ return fmt .Errorf ("error creating directory for catalog metadata: %v" , err )
143+ }
144+ if err := os .WriteFile (metaPath , meta .Blob , os .ModePerm ); err != nil {
145+ return fmt .Errorf ("error writing catalog metadata to file: %v" , err )
146+ }
147+ return nil
148+ }); err != nil {
149+ return nil , err
135150 }
136151
137- if err = file . Sync ( ); err != nil {
138- return nil , fmt .Errorf ("error syncing contents to cache file for Catalog %q : %s" , catalog . Name , err )
152+ if err := os . RemoveAll ( cacheDir ); err != nil {
153+ return nil , fmt .Errorf ("error removing old cache directory : %v" , err )
139154 }
140-
141- if _ , err = file .Seek (0 , 0 ); err != nil {
142- return nil , fmt .Errorf ("error resetting offset for cache file reader for Catalog %q: %s" , catalog .Name , err )
155+ if err := os .Rename (tmpDir , cacheDir ); err != nil {
156+ return nil , fmt .Errorf ("error moving temporary directory to cache directory: %v" , err )
143157 }
144158
145159 fsc .cacheDataByCatalogName [catalog .Name ] = cacheData {
146160 ResolvedRef : catalog .Status .ResolvedSource .Image .ResolvedRef ,
147161 }
148162
149- return file , nil
163+ return os . DirFS ( cacheDir ) , nil
150164}
0 commit comments