Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Our APIs don't make it easy to integrate new systems into the CLI nor with each other #41

Open
djdv opened this issue Nov 27, 2023 · 0 comments

Comments

@djdv
Copy link
Owner

djdv commented Nov 27, 2023

A file system host API (e.g. FUSE) needs to implement the method Mount(fsys fs.FS) (io.Closer, error).
And a file system guest (e.g. IPFS) needs to implement MakeFS() (fs.FS, error).
These are simple enough, but there's more surrounding this that needs to be done to actually wire either system up to the CLI, as well as some issues regarding compatibility between a host and guest.


The mountpoint data (analogous to an entry within fstab but with a different format) is currently encoded into JSON containing a pair of sections for the guest and host settings (such as the mountpoint target, API options, etc.).
The marshalling and unmarshalling of this is currently required in multiple parts of the program.
The mount command translates arguments into the appropriate mountpoint format and sends that to the fs daemon.
The daemon command receives these and translates them into Go API calls (MakeFS utilizing the guest portion of the JSON and Mount utilizing the host section).
The unmount command receives a list of mountpoint data from the daemon, but needs to know how to decode the "mountpoint target" from them (which corresponds to the CLI argument provided).
Due to differences between APIs there is not currently a common key/field name nor format for a "mountpoint", so the unmount implementation requires a sort of map to handle this.

While this all works, none of the CLI portions are very good and they're certainly not obvious.
I.e. it's easy to add systems if you already know how to, but it's not easy to learn how to.
This could be resolved with good documentation and examples, but it would probably be better to look at the code and try to create better abstractions and APIs for this. So that some kind of special knowledge isn't required as much.

There's technically generic constraints already within the mount implementation, but they need to be refined into something better, and made obvious to developers. As-is there's too many ways to forget something, get a program that compiles and runs, but has unexpected behaviour. I.e. you might implement and wire up mounting, but forget to add the decoder to unmount; the program will function until you need to unmount a specific target (-all would still work however).


When it comes to host<->guest interactions, the Mount method accepts any fs.FS, but this does not mean it will work completely at runtime.
For example, the FUSE host implementation will currently accept any fs.FS and most operations (like listing directories) will work, however reading files will not, because the current implementation requires files to implement io.Seeker where fs.File does not.
(Trying to read from guest files which do not implement that will return an error from syscalls to read.)

Some sort of interface should be constructed to assure compatibility between guest fs.FS implementations and the host APIs.
So that a guest fs.FS can express what capabilities it has, and either be accepted or rejected by a host at the time of calling Mount.
This is not uncommon in file systems, for example ZFS has feature flags, APIs like Billy (in Go) have a capability map, etc.

That should cause less confusion when trying to develop and integrate guests and hosts with each other.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant