-
Notifications
You must be signed in to change notification settings - Fork 34
Serve locally stored fbc content via an http server #148
Conversation
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #148 +/- ##
==========================================
- Coverage 79.10% 79.06% -0.04%
==========================================
Files 3 3
Lines 201 215 +14
==========================================
+ Hits 159 170 +11
- Misses 26 28 +2
- Partials 16 17 +1
☔ View full report in Codecov by Sentry. 📢 Have feedback on the report? Share it here. |
fe2259c
to
be7f1dc
Compare
pkg/storage/localdir.go
Outdated
@@ -45,3 +48,26 @@ func (s LocalDir) Store(catalog string, fsys fs.FS) error { | |||
func (s LocalDir) Delete(catalog string) error { | |||
return os.RemoveAll(filepath.Join(s.RootDir, catalog)) | |||
} | |||
|
|||
func (s LocalDir) StorageServerHandler() http.Handler { | |||
return http.StripPrefix(s.URL.Path, http.FileServer(http.FS(&filesOnlyFilesystem{os.DirFS(s.RootDir)}))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of calling os.DirFS()
can we pass a fs.FS
as a function parameter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume you're asking this for mocking purposes?
LocalDir
needs to write files into the OS filesystem at RootDir
and the whole point of moving this handler method into the LocalDir
struct is to share that context to make it easier to keep things aligned.
At best, we would need some sort of writable FS interface for RootDir
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doable, but what value does it bring, if not for unit tests (made a comment about unit tests below)? If we can think of a valuable unit test this'll need to be done anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume you're asking this for mocking purposes?
Mocking the filesystem to test the handler implementation to be more precise, but yes.
LocalDir needs to write files into the OS filesystem at RootDir and the whole point of moving this handler method into the LocalDir struct is to share that context to make it easier to keep things aligned
I think this is fair, but I feel we could probably do better than a call to os.DirFS()
to make it easier to test. That being said, I do think we could still create a temporary testing directory for unit testing purposes and inject it here so not a huge deal if we don't want to go into the effort of not using a direct os.DirFS()
call.
At best, we would need some sort of writable FS interface for RootDir
I do wish the standard fs
package had some way of having a writable FS interface, but if we wanted to completely abstract the use of the os
package this would be needed.
If we can think of a valuable unit test this'll need to be done anyway.
Unit tests for the http server:
/catalogs
returns a 404/catalogs/<catalogName>
returns a 404 (even if the directory exists)/catalogs/<catalogName>/all.json
returns 200 and expected JSON content
could also add unit tests specifically for the filesOnlyFilesystem
but I think that would be covered in the above tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For fs interfaces, please use afero if the stock fs.FS doesn't meet your need.
test/e2e/e2e_suite_test.go
Outdated
Expect(corev1.AddToScheme(scheme)).To(Succeed()) | ||
Expect(rbacv1.AddToScheme(scheme)).To(Succeed()) | ||
Expect(batchv1.AddToScheme(scheme)).To(Succeed()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like we should use the default scheme that includes these built-in types, rather than starting with an empty scheme and having to add built-in types one-by-one.
https://pkg.go.dev/k8s.io/[email protected]/kubernetes/scheme#Scheme
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do start with that, looks like it's the same in rukpak?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You do need to add non-core types to the runtime.Scheme()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I'm suggesting starting with scheme.Scheme
instead of runtime.NewScheme()
, because the former has all of the built-in types already added. Then all you have to worry about is adding the non-core types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(still adding to scheme)
test/e2e/unpack_test.go
Outdated
buf := new(bytes.Buffer) | ||
_, err = buf.ReadFrom(logReader) | ||
Expect(err).ToNot(HaveOccurred()) | ||
cfg, err := declcfg.LoadReader(buf) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason not to just do a string comparison of the raw FBC json?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we stick with LoadReader
, there's no need for the intermediate buffer. Just pass logReader
directly into declcfg.LoadReader
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reason to not to string comparison is how the information is laid out, ie lack of ordering guarantee.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Go's JSON encoder has ordering guarantees for field names. The previous code in operator-registry
would sort lists as well before sending them over the wire. Why wouldn't we want to add deterministic output to the set of expectations from the server?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lack of ordering guarantee
Can you explain further? The all.json
file is literally a file on disk and the written into the http response body. I don't see any possibility of non-determinism in the response.
test/e2e/unpack_test.go
Outdated
} | ||
rawMessage, err := json.Marshal(value{PackageName: "prometheus", Version: "0.47.0"}) | ||
Expect(err).To(Not(HaveOccurred())) | ||
expectedDeclCfg := declcfg.DeclarativeConfig{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use a golden fixture on disk and have an UPDATE=true
mode for tests to simply update the fixture?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no idea what you mean exactly.
However while trying to decipher your statement I realized that I should probably not make a config by hand here, and instead read the file from the test folder. If that's what you meant by your comment then +1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep - sorry for the nomenclature. "golden fixture" just means a file on disk in the repo that has the desired state. We check against it with a simple diff
and have a helper that, instead of checking and failing on a diff, updates the file, to facilitate easier development in the future.
@joelanford @everettraven @stevekuznetsov Latest update switches to using a separate server than the metrics server. Currently in progress: refactoring server related code in Storage to make it more unit test-able + unit tests. And the two unresolved comments from above. Pushing what I have till now to see what we can do as follow up to make it more iterative, since current sprint commitment is at risk: Work blocked on this PR: (note again that I am working on the unit tests related refactoring + unit tests in the background) |
7a5ea29
to
7ead78b
Compare
70cb262
to
91ca8b1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approving pending green e2e
Closes operator-framework#113 Signed-off-by: Anik <[email protected]>
Closes #113