Skip to content

volume/mounts: fix anonymous volume not being labeled#48754

Merged
thaJeztah merged 1 commit intomoby:masterfrom
thaJeztah:fix_anonymous_volumes_labels
Oct 25, 2024
Merged

volume/mounts: fix anonymous volume not being labeled#48754
thaJeztah merged 1 commit intomoby:masterfrom
thaJeztah:fix_anonymous_volumes_labels

Conversation

@thaJeztah
Copy link
Copy Markdown
Member

@thaJeztah thaJeztah commented Oct 25, 2024

volume/mounts: fix anonymous volume not being labeled

Parser.ParseMountRaw() labels anonymous volumes with a AnonymousLabel label (com.docker.volume.anonymous) label based on whether a volume has a name (named volume) or no name (anonymous) (see 1).

However both VolumesService.Create() (see 1) and Parser.ParseMountRaw() (see 2, 3) were generating a random name for anonymous volumes. The latter is called before VolumesService.Create() is called, resulting in such volumes not being labeled as anonymous.

Generating the name was originally done in Create (fc7b904), but duplicated in b3b7eb2 with the introduction of the new Mounts field in HostConfig. Duplicating this effort didn't have a real effect until (Create would just skip generating the name), until 618f26c introduced the AnonymousLabel in (v24.0.0, backported to v23.0.0).

Parsing generally should not fill in defaults / generate names, so this patch;

  • Removes generating volume names from Parser.ParseMountRaw()
  • Adds a debug-log entry to VolumesService.Create()
  • Touches up some logs to use structured logs for easier correlating logs

With this patch applied:

docker run --rm --mount=type=volume,target=/toto hello-world

DEBU[2024-10-24T22:50:36.359990376Z] creating anonymous volume                     volume-name=0cfd63d4df363571e7b3e9c04e37c74054cc16ff1d00d9a005232d83e92eda02
DEBU[2024-10-24T22:50:36.360069209Z] probing all drivers for volume                volume-name=0cfd63d4df363571e7b3e9c04e37c74054cc16ff1d00d9a005232d83e92eda02
DEBU[2024-10-24T22:50:36.360341209Z] Registering new volume reference              driver=local volume-name=0cfd63d4df363571e7b3e9c04e37c74054cc16ff1d00d9a005232d83e92eda02

- How to verify it

make TEST_FILTER='TestContainerVolumeAnonymous' TEST_SKIP_INTEGRATION_CLI=1 DOCKER_GRAPHDRIVER=vfs test-integration

=== RUN   TestContainerVolumeAnonymous
--- PASS: TestContainerVolumeAnonymous (0.02s)
PASS

DONE 1 tests in 1.225s

- Description for the changelog

Fix anonymous volumes being created through the `--mount` option not being marked as anonymous.

- A picture of a cute animal (not mandatory but encouraged)

`Parser.ParseMountRaw()` labels anonymous volumes with a `AnonymousLabel` label
(`com.docker.volume.anonymous`) label based on whether a volume has a name
(named volume) or no name (anonymous) (see [1]).

However both `VolumesService.Create()` (see [1]) and `Parser.ParseMountRaw()`
(see [2], [3]) were generating a random name for anonymous volumes. The latter
is called before `VolumesService.Create()` is called, resulting in such volumes
not being labeled as anonymous.

Generating the name was originally done in Create (fc7b904),
but duplicated in b3b7eb2 with the introduction
of the new Mounts field in HostConfig. Duplicating this effort didn't have a
real effect until (`Create` would just skip generating the name), until
618f26c introduced the `AnonymousLabel` in
(v24.0.0, backported to v23.0.0).

Parsing generally should not fill in defaults / generate names, so this patch;

- Removes generating volume names from  `Parser.ParseMountRaw()`
- Adds a debug-log entry to `VolumesService.Create()`
- Touches up some logs to use structured logs for easier correlating logs

With this patch applied:

    docker run --rm --mount=type=volume,target=/toto hello-world

    DEBU[2024-10-24T22:50:36.359990376Z] creating anonymous volume                     volume-name=0cfd63d4df363571e7b3e9c04e37c74054cc16ff1d00d9a005232d83e92eda02
    DEBU[2024-10-24T22:50:36.360069209Z] probing all drivers for volume                volume-name=0cfd63d4df363571e7b3e9c04e37c74054cc16ff1d00d9a005232d83e92eda02
    DEBU[2024-10-24T22:50:36.360341209Z] Registering new volume reference              driver=local volume-name=0cfd63d4df363571e7b3e9c04e37c74054cc16ff1d00d9a005232d83e92eda02

[1]: https://github.com/moby/moby/blob/032721ff75fe4a71a45b4a7a9b7e7c4c80c6431b/volume/service/service.go#L72-L83
[2]: https://github.com/moby/moby/blob/032721ff75fe4a71a45b4a7a9b7e7c4c80c6431b/volume/mounts/linux_parser.go#L330-L336
[3]: https://github.com/moby/moby/blob/032721ff75fe4a71a45b4a7a9b7e7c4c80c6431b/volume/mounts/windows_parser.go#L394-L400

Signed-off-by: Sebastiaan van Stijn <[email protected]>
@thaJeztah
Copy link
Copy Markdown
Member Author

@neersighted this one's for you (docker/compose#10833) 😄

Copy link
Copy Markdown
Contributor

@vvoland vvoland left a comment

Choose a reason for hiding this comment

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

LGTM; good catch!

@thaJeztah
Copy link
Copy Markdown
Member Author

good catch!

Thanks for @ndeloof for finding the discrepancy.

I initially thought the problem was here; with Daemon.registerMountPoints() adding volumeopts.WithCreateLabels();

moby/daemon/volumes.go

Lines 210 to 216 in d3c3a74

v, err = daemon.volumes.Create(ctx,
mp.Name,
mp.Driver,
volumeopts.WithCreateReference(container.ID),
volumeopts.WithCreateOptions(driverOpts),
volumeopts.WithCreateLabels(cfg.VolumeOptions.Labels),
)

And VolumeService.Create using opts.WithCreateLabel()

func (s *VolumesService) Create(ctx context.Context, name, driverName string, options ...opts.CreateOption) (*volumetypes.Volume, error) {
if name == "" {
name = stringid.GenerateRandomID()
options = append(options, opts.WithCreateLabel(AnonymousLabel, ""))
}

Because if they are applied in the reverse order, then volumeopts.WithCreateLabels() will overwrite the other label that's set; WithCreateLabel() merges, but WithCreateLabels() doesn't;

func WithCreateLabel(key, value string) CreateOption {
return func(cfg *CreateConfig) {
if cfg.Labels == nil {
cfg.Labels = map[string]string{}
}
cfg.Labels[key] = value
}
}

func WithCreateLabels(labels map[string]string) CreateOption {
return func(cfg *CreateConfig) {
cfg.Labels = labels
}
}

@thaJeztah
Copy link
Copy Markdown
Member Author

three LGTM's - works for me; thanks!

Comment thread volume/service/service.go
Comment on lines +76 to +78
log.G(ctx).WithField("volume-name", name).Error("Creating anonymous volume")
} else {
log.G(ctx).WithField("volume-name", name).Error("Creating named volume")
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.

Whoops; I left these as Error() log instead of Debug() 🙈

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

anonymous volumes created using --mount don't get AnonymousLabel set

4 participants