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

daemon: allow setting OCI annotations on containers #45025

Merged
merged 2 commits into from Feb 24, 2023

Conversation

corhere
Copy link
Contributor

@corhere corhere commented Feb 17, 2023

- What I did

Allow API clients to set and retrieve OCI annotations on a container.

- How I did it

Added a field to HostConfig and plumbed it into the OCI spec generation code.

- How to verify it
Create a container with annotations and start it. Inspect the running container using ctr and verify that the annotations are listed in the container spec.

A new integration test verifies that annotations can be round-tripped through the Engine API.

- Description for the changelog

  • Annotations—arbitrary non-identifying metadata—can now be attached to containers on creation which will be passed to the runtime when the container is started.

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

@thaJeztah

This comment was marked as outdated.

@corhere

This comment was marked as outdated.

@thaJeztah

This comment was marked as outdated.

Copy link
Member

@AkihiroSuda AkihiroSuda left a comment

Choose a reason for hiding this comment

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

And does this mean that an image containing these labels will set them at runtime on the container?

Yes. This could arguably be a feature.

This looks like an attack vector.

Specifying annotations should require a new API/CLI like
docker run --annotation=com.example.foo=bar.
(similar to podman run --annotation)

@corhere corhere marked this pull request as draft February 17, 2023 13:50
@corhere corhere changed the title daemon: allow setting OCI annotations using container labels daemon: allow setting OCI annotations on containers Feb 17, 2023
@corhere corhere marked this pull request as ready for review February 17, 2023 20:30
Copy link
Member

@cpuguy83 cpuguy83 left a comment

Choose a reason for hiding this comment

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

SGTM

But need to update the API history doc and openapi yaml.

Signed-off-by: Cory Snider <csnider@mirantis.com>
Comment on lines 566 to 569
if hostConfig != nil && versions.LessThan(version, "1.43") {
// Ignore OCIAnnotations because it was added in API v1.43.
hostConfig.OCIAnnotations = nil
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm following past precedent by ignoring the field on create for older API versions but unconditionally including it in the /containers/{}/json response for all API versions.

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

("requesting changes" just to have a quick check per my comment - changes otherwise look good to me)

VolumeDriver string // Name of the volume driver used to mount volumes
VolumesFrom []string // List of volumes to take from other container
ConsoleSize [2]uint // Initial console size (height,width)
OCIAnnotations map[string]string `json:",omitempty"` // Annotations to pass along to OCI runtime
Copy link
Member

@thaJeztah thaJeztah Feb 22, 2023

Choose a reason for hiding this comment

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

Before we merge; quick check on the naming. Wondering if OCI prefix is needed in our API here. I get where we're coming from; mostly thinking along the lines of "(almost) every option we have in our API leads to <something> OCI spec.

So wondering if we should keep the abstraction - call it Annotations, and keep the fact that that (currently) gets passed on to the OCI to the description only.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm coming around to dropping the OCI prefix and adopting essentially the same semantics as Kubernetes Annotations. And by that I mean documenting that Engine API clients can also leverage annotations to attach and consume metadata on containers for their own purposes. Perhaps we should also follow their lead and enforce a particular syntax for annotation keys so that the namespace of an annotation is unambiguous. We could always loosen validation later but can't make it more restrictive.

Copy link
Member

Choose a reason for hiding this comment

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

Let's discuss / brainstorm in the call later Today (I also need to get my head around all of that). Quick comment;

  • Yes, I think Annotations could be useful for "our side" as well
  • I like namespaces / prefixes as they can definitely help prevent ambiguity (I think I may actually have been the one originally getting them into the "labels" definition 🤔 )
  • ^^^ w.r.t. namespaces: I always keep in the back of my mind that API !== UX; namespaces are awkward to use, but are (in most cases) not meant for humans. So if we decide to use namespaces, we can still make the UX "different" (docker run --foo=bar doing docker run --annotation=awkwardly-long-namespace.option=bar behind the scenes)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What I like about how K8s goes about namespacing annotations is that it makes namespace prefixes optional and reserves the no-namespace "namespace" for users.

Copy link
Member

Choose a reason for hiding this comment

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

Yup, that was part of my original suggestion for labels; no-namespace is for users; don't use them for automation as they can easily conflict. For automation / tools, always use a prefix

Copy link
Member

Choose a reason for hiding this comment

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

For those interested; here's the PR with all the fun (well, there's been multiple before that, but that's the one that made it, and that one is already 200+ comments 🤣)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Decisions from today's maintainer call:

  • Drop the OCI prefix from the field name
  • Any annotation which is valid per the OCI Runtime spec is permitted
    • Keys can be any JSON string except for the empty string
    • Values can be any JSON string, including the empty string
    • Keys and values can be arbitrarily long

Allow clients to set annotations on a container which will applied to
the container's OCI spec.

Signed-off-by: Cory Snider <csnider@mirantis.com>
Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@@ -305,6 +305,11 @@ func validateHostConfig(hostConfig *containertypes.HostConfig) error {
if !hostConfig.Isolation.IsValid() {
return errors.Errorf("invalid isolation '%s' on %s", hostConfig.Isolation, runtime.GOOS)
}
for k := range hostConfig.Annotations {
if k == "" {
return errors.Errorf("invalid Annotations: the empty string is not permitted as an annotation key")
Copy link
Member

Choose a reason for hiding this comment

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

I had a look if we should be using an errdefs.InvalidParameter() here (and noticed other errors didn't), but it looks like we wrap any errors returned here on the call sites, such as

moby/daemon/create.go

Lines 65 to 68 in 2f0e308

warnings, err := daemon.verifyContainerSettings(opts.params.HostConfig, opts.params.Config, false)
if err != nil {
return containertypes.CreateResponse{Warnings: warnings}, errdefs.InvalidParameter(err)
}

So in either case; it's good (currently) to not use an errdefs, but we could (should?) look at these at some points to assign error-types in these locations.

@thaJeztah thaJeztah added this to the v-next milestone Feb 24, 2023
@thaJeztah
Copy link
Member

@cpuguy83 LGTY? (I see there's a "change requested" from you, and didn't want to dismiss it)

Screenshot 2023-02-24 at 14 56 38

@AkihiroSuda
Copy link
Member

@corhere Do you have a PR for the CLI?

@corhere
Copy link
Contributor Author

corhere commented Mar 24, 2023

@AkihiroSuda no, I am not working on a CLI PR as my motivation is unblocking support for alternative runtimes in cri-dockerd.

@AkihiroSuda
Copy link
Member

Opened a PR for the CLI:

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.

None yet

6 participants