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

imagetools: Allow annotations for OCI image index #1965

Merged
merged 2 commits into from
Aug 8, 2023

Conversation

mqasimsarfraz
Copy link
Contributor

@mqasimsarfraz mqasimsarfraz commented Jul 20, 2023

Currently there isn't any way to add annotations to OCI image index for multi-arch. The use case is to have a description in "About this version" in GitHub. It will introduce an optional flag of --annotation to imagetools create to allow adding OCI annotations.

Related: #1171

Testing Done:

OCI Image Index (annotation added)

$ ./bin/build/buildx  imagetools create  -t ghcr.io/inspektor-gadget/inspektor-gadget:v0.18.1 ghcr.io/inspektor-gadget/inspektor-gadget:v0.18.1@sha256:c3780808973801b24c80f8b46835b882fe0d69c08a4460333f28143569665861 ghcr.io/inspektor-gadget/inspektor-gadget:v0.18.1@sha256:d6d5661b02002aa8035e035e9210e3476e0401a948a86fabf104f71c2cbe0efe  --dry-run --annotation index:org.opencontainers.image.description="I am a description"
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.index.v1+json",
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:c3780808973801b24c80f8b46835b882fe0d69c08a4460333f28143569665861",
      "size": 2963,
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:d6d5661b02002aa8035e035e9210e3476e0401a948a86fabf104f71c2cbe0efe",
      "size": 2962,
      "platform": {
        "architecture": "arm64",
        "os": "linux"
      }
    }
  ],
  "annotations": {
    "org.opencontainers.image.description": "I am a description"
  }
}

Manifest Descriptor

$ ./bin/build/buildx  imagetools create  -t ghcr.io/inspektor-gadget/inspektor-gadget:v0.18.1 ghcr.io/inspektor-gadget/inspektor-gadget:v0.18.1@sha256:c3780808973801b24c80f8b46835b882fe0d69c08a4460333f28143569665861 ghcr.io/inspektor-gadget/inspektor-gadget:v0.18.1@sha256:d6d5661b02002aa8035e035e9210e3476e0401a948a86fabf104f71c2cbe0efe  --dry-run --annotation manifest-descriptor:org.opencontainers.image.description="I am a description"
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.index.v1+json",
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:c3780808973801b24c80f8b46835b882fe0d69c08a4460333f28143569665861",
      "size": 2963,
      "annotations": {
        "org.opencontainers.image.description": "I am a description"
      },
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:d6d5661b02002aa8035e035e9210e3476e0401a948a86fabf104f71c2cbe0efe",
      "size": 2962,
      "annotations": {
        "org.opencontainers.image.description": "I am a description"
      },
      "platform": {
        "architecture": "arm64",
        "os": "linux"
      }
    }
  ]
}

Docker manifest list (noop)

$ /bin/build/buildx  imagetools create  -t hello-world hello-world hello-world  --dry-run --annotation org.opencontainers.image.description="I am a description"
...

Copy link

@eiffel-fl eiffel-fl left a comment

Choose a reason for hiding this comment

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

Thank you for it! I tested it and it works fine:

$ ./bin/build/buildx imagetools create -t ghcr.io/eiffel-fl/inspektor-gadget:vtest ghcr.io/inspektor-gadget/inspektor-gadget:v0.18.1@sha256:c3780808973801b24c80f8b46835b882fe0d69c08a4460333f28143569665861 ghcr.io/inspektor-gadget/inspektor-gadget:v0.18.1@sha256:d6d5661b02002aa8035e035e9210e3476e0401a948a86fabf104f71c2cbe0efe --annotations foo="bar"                                       
[+] Building 2.4s (1/1) FINISHED                                                                                                                                           
 => [internal] pushing ghcr.io/eiffel-fl/inspektor-gadget:vtest
$ ./bin/build/buildx imagetools inspect --raw ghcr.io/eiffel-fl/inspektor-gadget:vtest                    qasim/oci-annotations u=
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.index.v1+json",
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:c3780808973801b24c80f8b46835b882fe0d69c08a4460333f28143569665861",
      "size": 2963,
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:d6d5661b02002aa8035e035e9210e3476e0401a948a86fabf104f71c2cbe0efe",
      "size": 2962,
      "platform": {
        "architecture": "arm64",
        "os": "linux"
      }
    }
  ],
  "annotations": {
    "foo": "bar"
  }
}

I think we are OK regarding the rules, as the reversed domain name is only an advise and due to using map we cannot have two times the same key.

util/imagetools/create.go Outdated Show resolved Hide resolved
@mqasimsarfraz
Copy link
Contributor Author

@crazy-max @jedevc any thoughts on this? :)

@jedevc
Copy link
Collaborator

jedevc commented Jul 24, 2023

Hm, in general I think the idea for this is alright 🎉

However, I think we'd probably want to retain consistency with how buildkit sets annotations: https://github.com/moby/buildkit/blob/master/docs/annotations.md.

There's not really any strong consensus on how we'd expose this in buildx build, but imagetools should probably follow an identical setup to avoid confusion.

#1171 (comment) gets pretty close to an ideal syntax imo. With, that to annotate your multi-arch image, you'd instead have:

$ buildx imagetools create -t hello-world hello-world hello-world --dry-run --annotation index:org.opencontainers.image.description="I am a description"

Would this kind of syntax work for you? I think we need consistency through buildx, so maybe good to continue the discussion there.

@crazy-max
Copy link
Member

crazy-max commented Jul 24, 2023

For the sake of parity we should consider supporting labels as well in follow-up.

@mqasimsarfraz
Copy link
Contributor Author

in general I think the idea for this is alright tada

Great

Would this kind of syntax work for you? I think we need consistency through buildx.

Agreed, we should have consistency through buildx. Also, I was already thinking how can we give user a hint that these annotations are for index and not manifest/descriptor so using index: prefix works well for that. I will proceed the PR in this direction then!

@mqasimsarfraz
Copy link
Contributor Author

@jedevc I have updated the PR to use the new syntax with index:. I still kept the scope to index only. Please feel free to let me know if you think we should handle descriptors as well.

@tonistiigi
Copy link
Member

I've opened #1978 that you can use as a base for adding integration tests for checking the --annotation flag behavior.

@mqasimsarfraz
Copy link
Contributor Author

mqasimsarfraz commented Aug 1, 2023

I've opened #1978 that you can use as a base for adding integration tests for checking the --annotation flag behavior.

@tonistiigi great thanks. I updated the PR to include testImagetoolsAnnotation. Had to use oci-mediatypes=true to ensure we push an index and not a manifest list in the test.

tests/imagetools.go Outdated Show resolved Hide resolved
tests/imagetools.go Outdated Show resolved Hide resolved
util/imagetools/create.go Outdated Show resolved Hide resolved
util/imagetools/create.go Outdated Show resolved Hide resolved
tests/imagetools.go Outdated Show resolved Hide resolved
tests/imagetools.go Outdated Show resolved Hide resolved
tests/imagetools.go Show resolved Hide resolved
indexAnnotations := make(map[string]string)
manifestDescriptorAnnotations := make(map[string]string)
for k, v := range ann {
groups := annotationRegexp.FindStringSubmatch(k)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Instead of using a regexp here, wdyt about using https://github.com/moby/buildkit/blob/dd0053cdce470b1355fdb0bd5a8f2b0fc506d842/exporter/containerimage/exptypes/annotations.go#L85 instead?

Obviously, it's not perfect, since we'd need to add the annotation- prefix here, which might make the error message a bit odd, but we could always upstream a buildkit fix later that would rework the function to have the caller remove the prefix there (so we wouldn't have to do that).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Instead of using a regexp here, wdyt about using https://github.com/moby/buildkit/blob/dd0053cdce470b1355fdb0bd5a8f2b0fc506d842/exporter/containerimage/exptypes/annotations.go#L85 instead?

Initially I had the same idea but we are using : as a separator for type and annotation key compared to . expected here. So it needs more work than just appending annotation- prefix.

but we could always upstream a buildkit fix later that would rework the function

Does it make sense to make buildkit parser to also handle : separator. It sounded specific to buildx so I feel we should keep it here. wdyt?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Personally, I'd prefer the conversion to buildkit's form for now, so that we only have one source of truth for parsing these keys - I'm happy to follow up in buildkit to rework the logic to be a bit more reusable for this case.

I also just noticed (sorry), that we aren't handling platforms? manifest-descriptor supports a platform, and should only be attached to the descriptor for those platforms.

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 happy to follow up in buildkit to rework the logic to be a bit more reusable for this case.

Agreed. That should be the way moving forward. I added a comment regrading using buildkit once it supports our use-case here.

I also just noticed (sorry), that we aren't handling platforms?

Great Catch. Done.

Signed-off-by: Qasim Sarfraz <qasimsarfraz@microsoft.com>
Signed-off-by: Qasim Sarfraz <qasimsarfraz@microsoft.com>
Copy link
Collaborator

@jedevc jedevc 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 @mqasimsarfraz!

@mqasimsarfraz
Copy link
Contributor Author

Can you please merge this ? or do we have any open items against it? :)

mqasimsarfraz added a commit to mqasimsarfraz/inspektor-gadget that referenced this pull request Feb 14, 2024
We were using a specific version for docker buildx to have
support for adding annotaions ( docker/buildx#1965).
But it has been released into stable already so removing workaround.

Signed-off-by: Qasim Sarfraz <qasimsarfraz@microsoft.com>
mqasimsarfraz added a commit to inspektor-gadget/inspektor-gadget that referenced this pull request Feb 14, 2024
We were using a specific version for docker buildx to have
support for adding annotaions ( docker/buildx#1965).
But it has been released into stable already so removing workaround.

Signed-off-by: Qasim Sarfraz <qasimsarfraz@microsoft.com>
@crazy-max crazy-max mentioned this pull request Apr 5, 2024
35 tasks
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.

5 participants