@@ -3,13 +3,14 @@ package cache
3
3
import (
4
4
"context"
5
5
"fmt"
6
- "io"
6
+ "io/fs "
7
7
"net/http"
8
8
"os"
9
9
"path/filepath"
10
10
"sync"
11
11
12
12
catalogd "github.com/operator-framework/catalogd/api/core/v1alpha1"
13
+ "github.com/operator-framework/operator-registry/alpha/declcfg"
13
14
14
15
"github.com/operator-framework/operator-controller/internal/catalogmetadata/client"
15
16
)
@@ -66,7 +67,7 @@ type filesystemCache struct {
66
67
// resources that have been successfully reconciled, unpacked, and are being served.
67
68
// These requirements help ensure that we can rely on status conditions to determine
68
69
// 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 ) {
70
71
if catalog == nil {
71
72
return nil , fmt .Errorf ("error: provided catalog must be non-nil" )
72
73
}
@@ -80,25 +81,23 @@ func (fsc *filesystemCache) FetchCatalogContents(ctx context.Context, catalog *c
80
81
}
81
82
82
83
cacheDir := filepath .Join (fsc .cachePath , catalog .Name )
83
- cacheFilePath := filepath .Join (cacheDir , "data.json" )
84
-
85
84
fsc .mutex .RLock ()
86
85
if data , ok := fsc .cacheDataByCatalogName [catalog .Name ]; ok {
87
86
if catalog .Status .ResolvedSource .Image .ResolvedRef == data .ResolvedRef {
88
87
fsc .mutex .RUnlock ()
89
- return os .Open ( cacheFilePath )
88
+ return os .DirFS ( cacheDir ), nil
90
89
}
91
90
}
92
91
fsc .mutex .RUnlock ()
93
92
94
93
req , err := http .NewRequestWithContext (ctx , http .MethodGet , catalog .Status .ContentURL , nil )
95
94
if err != nil {
96
- return nil , fmt .Errorf ("error forming request: %s " , err )
95
+ return nil , fmt .Errorf ("error forming request: %v " , err )
97
96
}
98
97
99
98
resp , err := fsc .client .Do (req )
100
99
if err != nil {
101
- return nil , fmt .Errorf ("error performing request: %s " , err )
100
+ return nil , fmt .Errorf ("error performing request: %v " , err )
102
101
}
103
102
defer resp .Body .Close ()
104
103
@@ -117,34 +116,49 @@ func (fsc *filesystemCache) FetchCatalogContents(ctx context.Context, catalog *c
117
116
// the cached contents
118
117
if data , ok := fsc .cacheDataByCatalogName [catalog .Name ]; ok {
119
118
if data .ResolvedRef == catalog .Status .ResolvedSource .Image .Ref {
120
- return os .Open ( cacheFilePath )
119
+ return os .DirFS ( cacheDir ), nil
121
120
}
122
121
}
123
122
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 ))
129
124
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 )
131
126
}
132
127
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
135
150
}
136
151
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 )
139
154
}
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 )
143
157
}
144
158
145
159
fsc .cacheDataByCatalogName [catalog .Name ] = cacheData {
146
160
ResolvedRef : catalog .Status .ResolvedSource .Image .ResolvedRef ,
147
161
}
148
162
149
- return file , nil
163
+ return os . DirFS ( cacheDir ) , nil
150
164
}
0 commit comments