Skip to content

Conversation

apostasie
Copy link
Contributor

@apostasie apostasie commented Aug 8, 2024

The motivation for this comes from #2942 - with some discussion in #3279

Restricting names to what the filesystem can do is very limiting.
Furthermore, user-controlled strings being used directly as paths components on the filesystem gives me the creeps.

This proposal here moves away from storing volumes inside volume_root/volume_name to volume_root/digest(volume_name).

It is fully backward compatible: if a volume exists with the legacy layout, it will still be usable.

It is NOT entirely forward compatible though: although existing volumes will keep working even with older versions even after having been used by newer version, this is not true for entirely new volumes:

  • for the older version, newly created volumes will have their name appear as a digest
  • legacy volumes that have been touched by the new version will have a doppelganger which will appear with a name that is the digest

What do you folks think?

cc @AkihiroSuda and @Shubhranshu153

FWIW docker IS using names as path components, and their regexp is: [a-zA-Z0-9][a-zA-Z0-9_.-]
They do enforce a limitation at max 254 characters as far as I can tell.

validateRegExp = regexp.MustCompile("^[a-zA-Z0-9_+:/-]{1,256}$")
)

func validateName(name string) error {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Purely provisional ^ - to be replaced by whatever we deem right.
I do not quite care what this does exactly, as this PR technically should free us from any limitations on names.

@@ -105,19 +123,63 @@ func (vs *volumeStore) Unlock() error {
return nil
}

func (vs *volumeStore) legacyEnsureLink(name string) error {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we have a legacy volume, calling this method will add the name inside volFilePath and create a symlink from legacyVolPath (with name) to volPath (with digest).

func (vs *volumeStore) Get(name string, size bool) (*native.Volume, error) {
if err := identifiers.Validate(name); err != nil {
return nil, fmt.Errorf("malformed volume name %q: %w", name, err)
func (vs *volumeStore) Get(nameOrDigest string, size bool) (*native.Volume, error) {
Copy link
Contributor Author

@apostasie apostasie Aug 8, 2024

Choose a reason for hiding this comment

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

Given how List is working, Get will now be able to retrieve from either name or digest (although this is not a feature).

@apostasie apostasie marked this pull request as ready for review August 8, 2024 02:57
@Shubhranshu153
Copy link
Contributor

From what i tested it doesnt seem docker is controlling it, rather the mkdir is failing for volume create

docker volume create --name ksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkk
Error response from daemon: create ksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkk: error while creating volume root path '/local/docker/volumes/ ksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkk': mkdir /local/docker/volumes/ksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkkksafnlksnaslknglksanglknglkkkk: file name too long

for other identifier names like containers i am able to give a pretty long name. (> 255 chars)

having a sha256 as identifier i feel needs to be a 2 way hash rather compression otherwise it would be difficult to list it out. Not sure if we need to complicate it.

@apostasie
Copy link
Contributor Author

apostasie commented Aug 8, 2024

for other identifier names like containers i am able to give a pretty long name. (> 255 chars)

Our NameStore implementation also uses the filesystem, so, same thing here: we need to rewrite it (or get rid of it) if we want to open it up.

having a sha256 as identifier i feel needs to be a 2 way hash rather compression otherwise it would be difficult to list it out. Not sure if we need to complicate it.

VolumeStore.Get was already reading a data file (for labels) - just adding the name was trivial.
As for List, it does call Get, so.
The extra complexity here is having to deal with the legacy format transparently.

I do not see how we could lift our length limit with a two way hash. Wouldn't that make our length limit variable, dependent on how well we can compress?

Signed-off-by: apostasie <spam_blackhole@farcloser.world>
@AkihiroSuda
Copy link
Member

Thanks, but I feel this is overengineering and hard to test

@AkihiroSuda
Copy link
Member

Something bad may happen when a legacy volume exists with hexadecimal name?

@apostasie
Copy link
Contributor Author

apostasie commented Aug 8, 2024

Something bad may happen when a legacy volume exists with hexadecimal name?

It would fail digest.Parse(), and be treated as "legacy" name.

The only case where we could possibly run into trouble is if someone has been using as a volume name a valid digest prefixed by sha256 (eg: nerdctl volume create sha256_b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c).

If this is a concern, we could certainly adapt the new layout to be over 76 characters long. Eg:

nerdctl volume create my_volume_name
# ===> on the filesystem: volume_sha256_93ff9de5cd31a50432dd2e39012e53ae78dd9a7ccb520c04f93828873813fef8

Since legacy identifiers cannot be over 76 chars, that would do it.

@apostasie
Copy link
Contributor Author

Thanks, but I feel this is overengineering and hard to test

Ok, that's fine.

@apostasie apostasie closed this Aug 8, 2024
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

Successfully merging this pull request may close these issues.

3 participants