Skip to content

Commit bf5fac6

Browse files
joelanfordgrokspawn
authored andcommitted
refactor FBC caching (#1051)
This commit improves maintainability and extensibility of the FBC caching used to serve the GRPC API. It: - introduces a new cache package and interface, which defines primitives for checking cache integrity, building the cache, and loading the cache. - moves the existing registry.Querier to an implementation of the cache interface, called cache.JSON This refactor also resolves two outstanding issues: 1. The current code contains a bug that causes panics when certain failures occur loading the cache. 2. The current code is hardcoded to always rebuild the cache if it is unreadable or its digest doesn't contain the expected value. This commit: 1. Refactors and removes the cases the led to the panic situation 2. Adds a new flag, --cache-enforce-integrity, that causes `opm serve` to exit with a failure if the cache is unreadable or its digest doesn't contain the expected value. This is useful in production contexts when one always expects the cache to be pre-populated correctly. Signed-off-by: Joe Lanford <[email protected]> Upstream-repository: operator-registry Upstream-commit: 562cf9c9bc649f1df2bbae26f8b543529499b60f
1 parent c62913d commit bf5fac6

File tree

26 files changed

+1727
-1501
lines changed

26 files changed

+1727
-1501
lines changed

staging/operator-registry/cmd/opm/serve/serve.go

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"context"
66
"errors"
77
"fmt"
8+
"io"
89
"net"
910
"net/http"
1011
endpoint "net/http/pprof"
@@ -19,17 +20,18 @@ import (
1920

2021
"github.com/operator-framework/operator-registry/pkg/api"
2122
health "github.com/operator-framework/operator-registry/pkg/api/grpc_health_v1"
23+
"github.com/operator-framework/operator-registry/pkg/cache"
2224
"github.com/operator-framework/operator-registry/pkg/lib/dns"
2325
"github.com/operator-framework/operator-registry/pkg/lib/graceful"
2426
"github.com/operator-framework/operator-registry/pkg/lib/log"
25-
"github.com/operator-framework/operator-registry/pkg/registry"
2627
"github.com/operator-framework/operator-registry/pkg/server"
2728
)
2829

2930
type serve struct {
30-
configDir string
31-
cacheDir string
32-
cacheOnly bool
31+
configDir string
32+
cacheDir string
33+
cacheOnly bool
34+
cacheEnforceIntegrity bool
3335

3436
port string
3537
terminationLog string
@@ -59,15 +61,19 @@ startup. Changes made to the declarative config after the this command starts
5961
will not be reflected in the served content.
6062
`,
6163
Args: cobra.ExactArgs(1),
62-
PreRunE: func(_ *cobra.Command, args []string) error {
64+
PreRun: func(_ *cobra.Command, args []string) {
6365
s.configDir = args[0]
6466
if s.debug {
6567
logger.SetLevel(logrus.DebugLevel)
6668
}
67-
return nil
6869
},
69-
RunE: func(cmd *cobra.Command, _ []string) error {
70-
return s.run(cmd.Context())
70+
Run: func(cmd *cobra.Command, _ []string) {
71+
if !cmd.Flags().Changed("cache-enforce-integrity") {
72+
s.cacheEnforceIntegrity = s.cacheDir != "" && !s.cacheOnly
73+
}
74+
if err := s.run(cmd.Context()); err != nil {
75+
logger.Fatal(err)
76+
}
7177
},
7278
}
7379

@@ -77,6 +83,7 @@ will not be reflected in the served content.
7783
cmd.Flags().StringVar(&s.pprofAddr, "pprof-addr", "", "address of startup profiling endpoint (addr:port format)")
7884
cmd.Flags().StringVar(&s.cacheDir, "cache-dir", "", "if set, sync and persist server cache directory")
7985
cmd.Flags().BoolVar(&s.cacheOnly, "cache-only", false, "sync the serve cache and exit without serving")
86+
cmd.Flags().BoolVar(&s.cacheEnforceIntegrity, "cache-enforce-integrity", false, "exit with error if cache is not present or has been invalidated. (default: true when --cache-dir is set and --cache-only is false, false otherwise), ")
8087
return cmd
8188
}
8289

@@ -102,11 +109,38 @@ func (s *serve) run(ctx context.Context) error {
102109

103110
s.logger = s.logger.WithFields(logrus.Fields{"configs": s.configDir, "port": s.port})
104111

105-
store, err := registry.NewQuerierFromFS(os.DirFS(s.configDir), s.cacheDir)
106-
defer store.Close()
112+
if s.cacheDir == "" && s.cacheEnforceIntegrity {
113+
return fmt.Errorf("--cache-dir must be specified with --cache-enforce-integrity")
114+
}
115+
116+
if s.cacheDir == "" {
117+
s.cacheDir, err = os.MkdirTemp("", "opm-serve-cache-")
118+
if err != nil {
119+
return err
120+
}
121+
defer os.RemoveAll(s.cacheDir)
122+
}
123+
124+
store, err := cache.New(s.cacheDir)
107125
if err != nil {
108126
return err
109127
}
128+
if storeCloser, ok := store.(io.Closer); ok {
129+
defer storeCloser.Close()
130+
}
131+
if s.cacheEnforceIntegrity {
132+
if err := store.CheckIntegrity(os.DirFS(s.configDir)); err != nil {
133+
return err
134+
}
135+
if err := store.Load(); err != nil {
136+
return err
137+
}
138+
} else {
139+
if err := cache.LoadOrRebuild(store, os.DirFS(s.configDir)); err != nil {
140+
return err
141+
}
142+
}
143+
110144
if s.cacheOnly {
111145
return nil
112146
}

staging/operator-registry/go.mod

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ require (
5959
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
6060
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect
6161
github.com/alessio/shellescape v1.4.1 // indirect
62-
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e // indirect
62+
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed // indirect
6363
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
6464
github.com/beorn7/perks v1.0.1 // indirect
6565
github.com/blang/semver v3.5.1+incompatible // indirect
@@ -93,7 +93,8 @@ require (
9393
github.com/gogo/protobuf v1.3.2 // indirect
9494
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
9595
github.com/golang/protobuf v1.5.2 // indirect
96-
github.com/google/cel-go v0.10.1 // indirect
96+
github.com/golang/snappy v0.0.3 // indirect
97+
github.com/google/cel-go v0.12.4 // indirect
9798
github.com/google/gnostic v0.5.7-v3refs // indirect
9899
github.com/google/gofuzz v1.1.0 // indirect
99100
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
@@ -107,7 +108,7 @@ require (
107108
github.com/josharian/intern v1.0.0 // indirect
108109
github.com/json-iterator/go v1.1.12 // indirect
109110
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
110-
github.com/klauspost/compress v1.11.13 // indirect
111+
github.com/klauspost/compress v1.12.3 // indirect
111112
github.com/mailru/easyjson v0.7.6 // indirect
112113
github.com/mattn/go-isatty v0.0.12 // indirect
113114
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
@@ -154,7 +155,7 @@ require (
154155
golang.org/x/tools v0.1.12 // indirect
155156
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
156157
google.golang.org/appengine v1.6.7 // indirect
157-
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac // indirect
158+
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect
158159
gopkg.in/inf.v0 v0.9.1 // indirect
159160
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
160161
gopkg.in/warnings.v0 v0.1.2 // indirect

staging/operator-registry/go.sum

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,9 @@ github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVK
8787
github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
8888
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
8989
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
90-
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e h1:GCzyKMDDjSGnlpl3clrdAK7I1AaVoaiKDOYkUzChZzg=
9190
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
91+
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed h1:ue9pVfIcP+QMEjfgo/Ez4ZjNZfonGgR6NgjMaJMu1Cg=
92+
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
9293
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
9394
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
9495
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
@@ -147,7 +148,6 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht
147148
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
148149
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
149150
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
150-
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
151151
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
152152
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
153153
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
@@ -251,7 +251,6 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y
251251
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
252252
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
253253
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
254-
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
255254
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
256255
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
257256
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
@@ -376,12 +375,15 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
376375
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
377376
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
378377
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
378+
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
379+
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
379380
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
380381
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
381382
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
382383
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
383-
github.com/google/cel-go v0.10.1 h1:MQBGSZGnDwh7T/un+mzGKOMz3x+4E/GDPprWjDL+1Jg=
384384
github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w=
385+
github.com/google/cel-go v0.12.4 h1:YINKfuHZ8n72tPOqSPZBwGiDpew2CJS48mdM5W8LZQU=
386+
github.com/google/cel-go v0.12.4/go.mod h1:Av7CU6r6X3YmcHR9GXqVDaEJYfEtSxl6wvIjUQTriCw=
385387
github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA=
386388
github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
387389
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
@@ -519,8 +521,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
519521
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
520522
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
521523
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
522-
github.com/klauspost/compress v1.11.13 h1:eSvu8Tmq6j2psUJqJrLcWH6K3w5Dwc+qipbaA6eVEN4=
523-
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
524+
github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU=
525+
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
524526
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
525527
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
526528
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -1264,8 +1266,8 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE
12641266
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
12651267
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
12661268
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
1267-
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac h1:qSNTkEN+L2mvWcLgJOR+8bdHX9rN/IdU3A1Ghpfb1Rg=
1268-
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
1269+
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I=
1270+
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
12691271
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
12701272
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
12711273
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -1291,7 +1293,7 @@ google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
12911293
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
12921294
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
12931295
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
1294-
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
1296+
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
12951297
google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
12961298
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
12971299
google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200709232328-d8193ee9cc3e h1:4BwkYybqoRhPKm97iNO3ACkxj26G0hC18CaO9QXOxto=
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package cache
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"io/fs"
8+
"os"
9+
"path/filepath"
10+
11+
"k8s.io/apimachinery/pkg/util/sets"
12+
13+
"github.com/operator-framework/operator-registry/pkg/api"
14+
"github.com/operator-framework/operator-registry/pkg/registry"
15+
)
16+
17+
type Cache interface {
18+
registry.GRPCQuery
19+
20+
CheckIntegrity(fbc fs.FS) error
21+
Build(fbc fs.FS) error
22+
Load() error
23+
}
24+
25+
func LoadOrRebuild(c Cache, fbc fs.FS) error {
26+
if err := c.CheckIntegrity(fbc); err != nil {
27+
if err := c.Build(fbc); err != nil {
28+
return err
29+
}
30+
}
31+
return c.Load()
32+
}
33+
34+
// New creates a new Cache. It chooses a cache implementation based
35+
// on the files it finds in the cache directory, with a preference for the
36+
// latest iteration of the cache implementation. It returns an error if
37+
// cacheDir exists and contains unexpected files.
38+
func New(cacheDir string) (Cache, error) {
39+
entries, err := os.ReadDir(cacheDir)
40+
if err != nil && !errors.Is(err, os.ErrNotExist) {
41+
return nil, fmt.Errorf("detect cache format: read cache directory: %v", err)
42+
}
43+
jsonCache := sets.NewString(jsonDir, jsonDigestFile)
44+
45+
found := sets.NewString()
46+
for _, e := range entries {
47+
found.Insert(e.Name())
48+
}
49+
50+
// Preference (and currently only supported) is the JSON-based cache implementation.
51+
if found.IsSuperset(jsonCache) || len(entries) == 0 {
52+
return NewJSON(cacheDir), nil
53+
}
54+
55+
// Anything else is unexpected.
56+
return nil, fmt.Errorf("cache directory has unexpected contents")
57+
}
58+
59+
func ensureEmptyDir(dir string, mode os.FileMode) error {
60+
if err := os.MkdirAll(dir, mode); err != nil {
61+
return err
62+
}
63+
entries, err := os.ReadDir(dir)
64+
if err != nil {
65+
return err
66+
}
67+
for _, entry := range entries {
68+
if err := os.RemoveAll(filepath.Join(dir, entry.Name())); err != nil {
69+
return err
70+
}
71+
}
72+
return nil
73+
}
74+
75+
func doesBundleProvide(ctx context.Context, c Cache, pkgName, chName, bundleName, group, version, kind string) (bool, error) {
76+
apiBundle, err := c.GetBundle(ctx, pkgName, chName, bundleName)
77+
if err != nil {
78+
return false, fmt.Errorf("get bundle %q: %v", bundleName, err)
79+
}
80+
for _, gvk := range apiBundle.ProvidedApis {
81+
if gvk.Group == group && gvk.Version == version && gvk.Kind == kind {
82+
return true, nil
83+
}
84+
}
85+
return false, nil
86+
}
87+
88+
type sliceBundleSender []*api.Bundle
89+
90+
func (s *sliceBundleSender) Send(b *api.Bundle) error {
91+
*s = append(*s, b)
92+
return nil
93+
}
94+
95+
func listBundles(ctx context.Context, c Cache) ([]*api.Bundle, error) {
96+
var bundleSender sliceBundleSender
97+
98+
err := c.SendBundles(ctx, &bundleSender)
99+
if err != nil {
100+
return nil, err
101+
}
102+
103+
return bundleSender, nil
104+
}

0 commit comments

Comments
 (0)