Skip to content
This repository was archived by the owner on Mar 3, 2025. It is now read-only.

Store(local dir) and Serve(http server) FBC#135

Closed
anik120 wants to merge 10 commits intooperator-framework:mainfrom
anik120:storage-implementation
Closed

Store(local dir) and Serve(http server) FBC#135
anik120 wants to merge 10 commits intooperator-framework:mainfrom
anik120:storage-implementation

Conversation

@anik120
Copy link
Copy Markdown
Member

@anik120 anik120 commented Aug 3, 2023

closes #113

Comment thread pkg/util/fs.go Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Aug 3, 2023

Codecov Report

Merging #135 (e59cdff) into main (a8f7196) will decrease coverage by 1.07%.
The diff coverage is 53.84%.

@@            Coverage Diff             @@
##             main     #135      +/-   ##
==========================================
- Coverage   78.01%   76.94%   -1.07%     
==========================================
  Files           2        2              
  Lines         282      295      +13     
==========================================
+ Hits          220      227       +7     
- Misses         39       42       +3     
- Partials       23       26       +3     
Files Changed Coverage Δ
pkg/controllers/core/catalog_controller.go 76.79% <53.84%> (-1.07%) ⬇️

Comment thread pkg/storage/localdir.go Outdated
@anik120 anik120 force-pushed the storage-implementation branch from afffbe6 to 1c21eb3 Compare August 3, 2023 19:19
Comment thread pkg/storage/localdir.go Outdated
Comment thread pkg/storage/localdir.go Outdated
Comment thread pkg/storage/localdir.go Outdated
Comment thread pkg/storage/localdir.go Outdated
Comment thread pkg/storage/localdir.go Outdated
Comment thread pkg/util/tar.go Outdated
Comment thread pkg/util/tar.go Outdated
@anik120 anik120 changed the title Implement rukpak storage interface WIP: Implement rukpak storage interface Aug 3, 2023
@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 3, 2023
@anik120
Copy link
Copy Markdown
Member Author

anik120 commented Aug 3, 2023

@ncdc it's a WIP PR 😄

(I didn't think anyone had notifications on for new PRs for this repo yet, hence the skipping of the WIP tag 😮‍💨 )

@ncdc
Copy link
Copy Markdown
Member

ncdc commented Aug 3, 2023

Sorry, saw the notification come through so I started looking at it.

@anik120
Copy link
Copy Markdown
Member Author

anik120 commented Aug 3, 2023

@ncdc fyi this is just copy paste of https://github.com/operator-framework/rukpak/blob/main/pkg/storage/localdir.go (I was using this for a private conversation), but it looks like we should look into auditing this in rukpak based off of your suggestions

@anik120 anik120 force-pushed the storage-implementation branch 4 times, most recently from 046fd14 to a9c9482 Compare August 11, 2023 16:26
@anik120 anik120 force-pushed the storage-implementation branch 6 times, most recently from 7610d7c to ad474b3 Compare August 12, 2023 20:25
@anik120 anik120 changed the title WIP: Implement rukpak storage interface WIP: Store(local dir) and Serve(http server) FBC Aug 12, 2023
@anik120 anik120 force-pushed the storage-implementation branch from ad474b3 to baeb9be Compare August 14, 2023 13:45
@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Aug 14, 2023
@anik120 anik120 force-pushed the storage-implementation branch 2 times, most recently from 3496d8a to 4c0f6b6 Compare August 14, 2023 13:47
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Aug 14, 2023
Copy link
Copy Markdown

@stevekuznetsov stevekuznetsov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the difference between the server and the storage? Why do we need two separate concepts as opposed to one?

Comment thread pkg/catalogserver/server.go Outdated
Comment thread pkg/controllers/core/catalog_controller_test.go Outdated
Comment thread cmd/manager/main.go Outdated
Comment thread cmd/manager/main.go Outdated
Comment thread pkg/storage/storage.go Outdated
@anik120 anik120 force-pushed the storage-implementation branch 2 times, most recently from c512ed8 to bddb98c Compare August 14, 2023 21:25
@anik120 anik120 changed the title WIP: Store(local dir) and Serve(http server) FBC Store(local dir) and Serve(http server) FBC Aug 14, 2023
Comment thread cmd/manager/main.go Outdated
Comment thread cmd/manager/main.go Outdated
Comment thread pkg/controllers/core/catalog_controller.go Outdated
Comment thread pkg/storage/storage.go Outdated
- "--metrics-bind-address=127.0.0.1:8080"
- "--leader-elect"
- "--feature-gates=PackagesBundleMetadataAPIs=true,CatalogMetadataAPI=true"
- "--feature-gates=PackagesBundleMetadataAPIs=true,CatalogMetadataAPI=true,HTTPServer=false"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want the http server disabled by default? I figure we probably want all of them enabled so we can start the deprecation/removal process after a new release with these changes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still thinking this should probably be set to true by default so that all of the serving methods are available by default in the next release and we can remove the Package , BundleMetadata, and CatalogMetadata in the next+1 release. That being said that can be done in a follow up if we want and shouldn't block this PR

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we even have to wait for the next +1 release. We should be fine just removing those, and switching this to true. But yea let's leave that for a follow up

Comment thread pkg/catalogserver/server.go Outdated
Comment on lines +85 to +98
if features.CatalogdFeatureGate.Enabled(features.HTTPServer) && existingCatsrc.DeletionTimestamp.IsZero() && !controllerutil.ContainsFinalizer(&existingCatsrc, fbcDeletionFinalizer) {
controllerutil.AddFinalizer(&existingCatsrc, fbcDeletionFinalizer)
if err := r.Update(ctx, &existingCatsrc); err != nil {
return ctrl.Result{}, err
}
}
if features.CatalogdFeatureGate.Enabled(features.HTTPServer) && !existingCatsrc.DeletionTimestamp.IsZero() && controllerutil.ContainsFinalizer(&existingCatsrc, fbcDeletionFinalizer) {
if err := r.Storage.Delete(existingCatsrc.Name); err != nil {
return ctrl.Result{}, err
}
controllerutil.RemoveFinalizer(&existingCatsrc, fbcDeletionFinalizer)
err := r.Update(ctx, &existingCatsrc)
return ctrl.Result{}, err
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Based on our current code structure, would this logic be better suited in the reconcile() function below? IIUC any changes to the finalizer will be reflected when we issue the update requests at the end of this function. For consistency I would prefer we do our finalizer update logic where we also do the status updates.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to actually add the finalizer to the object before storing anything into the storage directory. Here's the problematic scenario:

  1. Lookup and get a copy of the object we're reconciling
  2. Add a finalizer to the copy (without actually updating it in etcd)
  3. Store the catalog data
  4. Send the object update, but get a failure on the update

Now, we've stored the data, but a finalizer isn't present to make sure it gets deleted when the object is deleted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But +1 on moving the finalizer logic to reconcile().

What we could do there is add the finalizer to the copy, but then just return immediately when we've added the finalizer, and let the existing diff-ing update logic here Reconcile handle the actual update call.

Comment thread pkg/catalogserver/server.go Outdated

if features.CatalogdFeatureGate.Enabled(features.HTTPServer) && existingCatsrc.DeletionTimestamp.IsZero() && !controllerutil.ContainsFinalizer(&existingCatsrc, fbcDeletionFinalizer) {
controllerutil.AddFinalizer(&existingCatsrc, fbcDeletionFinalizer)
if err := r.Update(ctx, &existingCatsrc); err != nil {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's almost always best to use Patch instead of Update. When using Update:

  1. If the running code has an older version of the go struct definition, and
  2. The CRD in the cluster contains new fields, and
  3. There are CRs that have the new fields populated, then
  4. When you issue an Update using the older client, the result is the new fields will be nulled out

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably orthogonal to this PR, given we already have some generic diff-then-update logic in the Reconcile() method. I propose we make a separate issue to change the existing Update calls to Patch.

}
if features.CatalogdFeatureGate.Enabled(features.HTTPServer) && !existingCatsrc.DeletionTimestamp.IsZero() && controllerutil.ContainsFinalizer(&existingCatsrc, fbcDeletionFinalizer) {
if err := r.Storage.Delete(existingCatsrc.Name); err != nil {
return ctrl.Result{}, err
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should set a condition on the Catalog here

return ctrl.Result{}, err
}
controllerutil.RemoveFinalizer(&existingCatsrc, fbcDeletionFinalizer)
err := r.Update(ctx, &existingCatsrc)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto re patch


if features.CatalogdFeatureGate.Enabled(features.HTTPServer) {
if err := r.Storage.Store(catalog.Name, fbc); err != nil {
return ctrl.Result{}, updateStatusUnpackFailing(&catalog.Status, fmt.Errorf("error storing fbc: %v", err))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should set a condition on the Catalog here

Comment thread pkg/storage/storage.go Outdated
}
}

func (s *Storage) Store(owner string, fbc *declcfg.DeclarativeConfig) error {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One other thing we glossed over - when a catalog is updated, we will call Store() again with the same name as before. I think the most seamless behavior here is:

  1. write contents to a new file
  2. move new file to the location of the old one
  3. don't touch the HTTP handlers

This will ensure zero-downtime for the callers.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is important.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've captured this as a follow up item. We need an entire story for handling updates to the content in the remote registry (ie what we currently call the polling strategy in v0), and for handling changes to the spec.image field of the CR.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the controller not handle update events for CatalogSource objects? Is there no place where this can slot in already?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. It's unimplemented. So far what we have is "creation and deletion once". We haven't gotten to updates at all.

@anik120 anik120 requested a review from a team as a code owner August 16, 2023 16:21
@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Aug 16, 2023
obsoletes operator-framework#113

Signed-off-by: Anik <anikbhattacharya93@gmail.com>
Signed-off-by: Anik <anikbhattacharya93@gmail.com>
Signed-off-by: Anik <anikbhattacharya93@gmail.com>
Signed-off-by: Anik <anikbhattacharya93@gmail.com>
Signed-off-by: Anik <anikbhattacharya93@gmail.com>
Signed-off-by: Anik <anikbhattacharya93@gmail.com>
@anik120 anik120 force-pushed the storage-implementation branch from 6e71f82 to 4e304f9 Compare August 16, 2023 16:34
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Aug 16, 2023
Signed-off-by: Anik <anikbhattacharya93@gmail.com>
Signed-off-by: Anik <anikbhattacharya93@gmail.com>
Comment thread cmd/manager/main.go Outdated
Comment thread cmd/manager/main.go Outdated
Expect(res).To(Equal(ctrl.Result{}))
Expect(err).ToNot(HaveOccurred())
})
It("the catalog should become available at addr/catalogs", func() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be done in a follow up, but should we also validate that the returned JSON stream from the catalog being stored matches what we expect? IIRC, the tests for the other methods of storing/serving validate that the actual content == expected content

Signed-off-by: Anik <anikbhattacharya93@gmail.com>
@anik120 anik120 force-pushed the storage-implementation branch from eee8ebd to 2d64104 Compare August 17, 2023 16:06
Copy link
Copy Markdown
Collaborator

@everettraven everettraven left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this looks good to me. Have one nit and a couple comments that I think would be nice to have addressed either as part of this PR or a follow-up.

Comment on lines +64 to +65
fs := http.FileServer(http.FS(os.DirFS(dir)))
return fs
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Can reduce this to a one liner:

Suggested change
fs := http.FileServer(http.FS(os.DirFS(dir)))
return fs
return http.FileServer(http.FS(os.DirFS(dir)))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also expect http.StripPath to enter into the equation somewhere.

The URL paths will come in with /catalogs/<catalogName>/all.json, but our http.FileSystem will only see <catalogName>/all.json, so we need to strip /catalogs from the path before the http.FileSystem sees the request.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the benefit of making the path /catalogs/catalogName/all.json? Why not just keep it simple to /catalogName.json?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original intention behind /catalogs/catalogName/all.json was to leave room for expanding the endpoints (files being served) if desired without impacting clients wanting everything. For example, if we wanted to expand via file serving for getting only all the bundles for the catalog we could add /catalogs/{catalogName}/bundles.json without changing the API for clients that always want to fetch everything. It becomes purely additive (and is IMO intuitive) to add new file based endpoints with that structure

- "--metrics-bind-address=127.0.0.1:8080"
- "--leader-elect"
- "--feature-gates=PackagesBundleMetadataAPIs=true,CatalogMetadataAPI=true"
- "--feature-gates=PackagesBundleMetadataAPIs=true,CatalogMetadataAPI=true,HTTPServer=false"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still thinking this should probably be set to true by default so that all of the serving methods are available by default in the next release and we can remove the Package , BundleMetadata, and CatalogMetadata in the next+1 release. That being said that can be done in a follow up if we want and shouldn't block this PR

Comment on lines +309 to +317
It("the catalog should become available at server endpoint", func() {
resp, err := httpclient.Do(httpRequest)
Expect(err).To(Not(HaveOccurred()))
defer resp.Body.Close()

catalogs, err := io.ReadAll(resp.Body)
Expect(err).To(Not(HaveOccurred()))
Expect(string(catalogs)).To(Equal(fmt.Sprintf(httpResponse, fmt.Sprintf("\n<a href=\"%s\">%s</a>", catalogKey.Name+".json", catalogKey.Name+".json"))))
})
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see this validate the response matches what we expect when we request the catalog contents rather than checking that there is a link to the file when visiting the index endpoint, but I'm okay with that being a follow-up.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we should test that this returns the content we want, if not, what are we confident that we've written here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread pkg/catalogserver/server.go
Comment thread pkg/catalogserver/server.go
}
// if the ShutdownTimeout is zero, wait forever to shutdown
// otherwise force shut down when timeout expires
sc := context.Background()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: sc and scc are opaque names that I'm not sure everyone will unpack (I struggled!)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How bout shutdownCtx and shutdownCancel?

req, err := http.NewRequest("GET", testServer.URL, nil)
Expect(err).To(Not(HaveOccurred()))
req.Header.Set("Accept", "text/html")
httpRequest = req
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a side-effect mutation to bring this up a scope? Why not create the request in the test closure that uses it?

Copy link
Copy Markdown
Member Author

@anik120 anik120 Aug 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

creating that request in multiple closures is just repeating the same code

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's wrong with that?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little bit less tongue-in-cheek: tests must be as independent as possible. The more that tests are intertwined, it's harder to break just one and grok all of it at once while reviewing changes. Repeating two or three lines of code is really not something we should be optimizing for.

Comment on lines +309 to +317
It("the catalog should become available at server endpoint", func() {
resp, err := httpclient.Do(httpRequest)
Expect(err).To(Not(HaveOccurred()))
defer resp.Body.Close()

catalogs, err := io.ReadAll(resp.Body)
Expect(err).To(Not(HaveOccurred()))
Expect(string(catalogs)).To(Equal(fmt.Sprintf(httpResponse, fmt.Sprintf("\n<a href=\"%s\">%s</a>", catalogKey.Name+".json", catalogKey.Name+".json"))))
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we should test that this returns the content we want, if not, what are we confident that we've written here?

Comment thread pkg/storage/storage.go Outdated
}
}

func (s *Storage) Store(owner string, fbc *declcfg.DeclarativeConfig) error {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is important.

Comment thread config/manager/manager.yaml Outdated
Expect(err).To(Not(HaveOccurred()))
//omitting trailing new line char from response
Expect(string(catalogs[:len(catalogs)-1])).To(Equal(catalogKey.Name))
Expect(string(catalogs)).To(Equal(fmt.Sprintf(httpResponse, fmt.Sprintf("\n<a href=\"%s\">%s</a>", catalogKey.Name+".json", catalogKey.Name+".json"))))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RFC does not mention anything about serving index.html pages for directory listings. I would expect this request to be a 404 Not Found response.

Copy link
Copy Markdown
Member

@joelanford joelanford Aug 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up for clarity. I would expect tests for (pseudocode):

  1. http.Get("<host>/catalogs/<catalogName>/all.json => response code 200 and valid FBC
  2. http.Get("<host>/catalogs/<catalogName>/non-exist.json => response code 404
  3. http.Get("<host>/catalogs/<catalogName>/ => response code 404
  4. http.Get("<host>/catalogs/ => response code 404

I am not sure this file is the right place for these tests. This file contains tests for what Reconcile does. In the case of catalog contents, Reconcile only stores the contents into the storage directory. So I would expect tests here to just assert that the expected files exist in the storage directory after Reconcile is called.

I think we should have unit tests in pkg/catalogserver that use httptest package.

And I think we should have an e2e test that actually queries the pod endpoint after a Catalog says it is unpacked.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Steve pointed out to me that we can probably get by without the Reconcile()-specific test that would assert on filesystem contents if we have an e2e. That would make it easier to make internal changes and still be assured they don't break users.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joelanford the catalogserver just starts a server. If the tests are moved to pkg/catalogserver then you'd have to simulate a Storage, at which point you're just duplicating work being done in the reconciler tests.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Steve pointed out to me that we can probably get by without the Reconcile()-specific test that would assert on filesystem contents if we have an e2e. That would make it easier to make internal changes and still be assured they don't break users.

I don't understand the difference between the e2e test being suggested here vs the Reconcile test. In fact the whole idea of this test set up was to avoid adding e2e tests unless we absolutely need them wasn't it?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is different than what http.FileServer does though. FileServer just serves up the entire directory, and there's not much configurability when it comes to access points.

I think that this is partially true. The http.FileServer is less flexible than rolling our own with http.ServeFile, but I think we can achieve what @joelanford suggested by doing something similar to rukpak's implementation that creates a filesystem wrapper that forces 404 not found on requests that would return a directory list

Copy link
Copy Markdown
Member Author

@anik120 anik120 Aug 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, we're onto something now.....

Again, rukpak is exposing an arbitrary list of arbitrary artifacts stored in the directory. Using that implementation to expose just FBC in our case is definitely overkill. The argument put forward for using http.FileServer was also something along the lines of "less configuration/less code required for standing up the server", but using that implementation to expose all.json is looking more like a long winded way of shoehorning everything in for http.FileServer.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know that I personally feel strongly about @joelanford requirements, but in any case the FilesOnlyFilesystrem is twenty lines of code you can import and re-use. You do not need to manage everything else that http.FileServer does for you.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. The requirements are from the RFC and I do agree with those requirements since they adhere to design best practices. We all +1-ed the requirements in the RFC too.
  2. FileServer is a wrapper around filehandler, and ServerHTTP ultimately calls serveFile.

ServeFile just takes the file name we pass as a parameter, splits the name into "dir name" and "file name", and uses those variables to call the exact same serveFile.

What is this "everything else" you're alluding to?

  1. I'm confused by rukpak's code. Could someone point me to where ServeHTTP is actually used? How are the files really exposed? I searched in the project and the only caller of this function is a test function

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither here nor there on the requirements. Importing the 20LoC or copy-pasting it is low cost.

As for what "everything else" is - I would recommend going a bit deeper there. From the management of which files are and are not served, to how how paths are cleaned and block traversal attacks, etc.

Signed-off-by: Anik <anikbhattacharya93@gmail.com>
@anik120
Copy link
Copy Markdown
Member Author

anik120 commented Aug 24, 2023

@stevekuznetsov @operator-framework/catalogd-maintainers closing this PR in favor of splitting it up into smaller PRs so that it's easier to review and get things moving along. Look out for a series of PRs that'll be based off of this PR, but with some additional stuff to address remaining open comments for the work being done in this PR. First one starts with #144 to store the FBC in a local Dir.
Second PR will be to introduce an http Handler.
A third PR will tie the first two PRs (and will contain integration tests)

@anik120 anik120 closed this Aug 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Serve locally stored fbc content via a server

6 participants