[Question] getting image labels via library/API
tcurdt opened this issue · comments
Question
I am trying to use regclient
as library from my own code base.
I am trying to implement the same as regctl image inspect ghcr.io/aquasecurity/trivy:latest
and then extract the labels.
I've looked at the tests and the cmd implementation and so far came up with:
getRef, err := ref.New("ghcr.io/aquasecurity/trivy:latest")
if err != nil {
return fmt.Errorf("Failed creating getRef: %v", err)
}
mGet, err := rc.ManifestGet(ctx, getRef)
if err != nil {
return fmt.Errorf("Failed running ManifestGet: %v", err)
}
if manifest.GetMediaType(mGet) != types.MediaTypeDocker2Manifest {
// Unexpected media type: application/vnd.docker.distribution.manifest.list.v2+json
// return fmt.Errorf("Unexpected media type: %s", manifest.GetMediaType(mGet))
}
fmt.Printf("isList=%@\n", mGet.IsList())
plat := platform.Local()
desc, err := manifest.GetPlatformDesc(mGet, &plat)
if err != nil {
fmt.Printf("%@\n", err)
}
m, err := rc.ManifestGet(ctx, getRef, regclient.WithManifestDesc(*desc))
body, _ := m.RawBody()
fmt.Printf("m=%@\n", string(body))
if err != nil {
fmt.Printf("%@\n", err)
}
How to get to the labels?
It seems like the first call gets a list?
And the platform is used as a filter?
But how do I get from the manifest to the labels? The body looks just like this:
m=%!@(string={
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 2000,
"digest": "sha256:529604a42cb643b098561eb59dda41d2fe3b29913570b2f6a3a1d3ab3d77af10"
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 3333033,
"digest": "sha256:2c03dbb20264f09924f9eab176da44e5421e74a78b09531d3c63448a7baa7c59"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 5291926,
"digest": "sha256:51824a6a03669e32e86dcbd1ebfbf9e579efb981c14c0b6f7c0b991e7471ac71"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 50297857,
"digest": "sha256:4571becd293d30590e1330e7206f8c6c1e863fb359b579178ebed9ae7708bd95"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 4234,
"digest": "sha256:c47530373cb2bc40aa641c7bc66434f4bbb33b3a4dccba81fd652229c117fa7f"
}
]
})
How to pass credentials?
Also not sure yet how to provide registry credentials. (Hence the public image)
I would appreciate some pointers nudging me in the right direction.
Version
github.com/regclient/regclient v0.5.6
Environment
Currently running on macOS on arm
Anything else
Labels are part of the image config.
To go from the manifest the config, you need to convert it to an image manifest, get the config blob, and convert that to an OCI config structure. That's done in regctl
at:
Lines 1213 to 1225 in a25d343
For auth, you would create the rc
with the WithConfigHost
option:
https://pkg.go.dev/github.com/regclient/regclient#WithConfigHost
The config.Host
would need a Name, User, and Pass defined (unless using a credential helper):
https://pkg.go.dev/github.com/regclient/regclient@v0.5.6/config#Host
If the registry is logged in using Docker, you can import the credentials from that using WithDockerCreds
:
https://pkg.go.dev/github.com/regclient/regclient#WithDockerCreds
I'm going to leave this open for a bit because documentation in the Go Docs could use more details and examples to make this easier to figure out.
Thanks! Seems like I got it working!
So this is the correct way? or did I miss something?
(I stripped the error handling for the overview)
ctx := context.Background()
rc := regclient.New(
regclient.WithConfigHost(hosts...),
)
r, err := ref.New("ghcr.io/foo/bar:latest")
m, err := rc.ManifestGet(ctx, r)
plat := platform.Local()
desc, err := manifest.GetPlatformDesc(m, &plat)
m, err = rc.ManifestGet(ctx, r, regclient.WithManifestDesc(*desc))
mi, ok := m.(manifest.Imager)
cd, err := mi.GetConfig()
blobConfig, err := rc.BlobGetOCIConfig(ctx, r, cd)
body, err := blobConfig.RawBody()
var imageConfig OCIConfig
err = yaml.Unmarshal(body, &imageConfig)
fmt.Println(imageConfig.Config.Labels["org.opencontainers.image.revision"])
rc.BlobGetOCIConfig
already unmarshals the blob for you, so you can call GetConfig to get access to the data structure directly:
https://pkg.go.dev/github.com/regclient/regclient@v0.5.6/types/blob#BOCIConfig.GetConfig
I kind of suspected I something like that :)
Thanks for the help!
Works!