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

[release/1.5] cherry-pick: Enable image config labels in ctr and CRI container creation #6024

Merged
merged 1 commit into from Sep 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions cmd/ctr/commands/run/run.go
Expand Up @@ -247,3 +247,16 @@ func fullID(ctx context.Context, c containerd.Container) string {
}
return fmt.Sprintf("%s-%s", ns, id)
}

// buildLabel builds the labels from command line labels and the image labels
func buildLabels(cmdLabels, imageLabels map[string]string) map[string]string {
labels := make(map[string]string)
for k, v := range imageLabels {
labels[k] = v
}
// labels from the command line will override image and the initial image config labels
for k, v := range cmdLabels {
labels[k] = v
}
return labels
}
6 changes: 5 additions & 1 deletion cmd/ctr/commands/run/run_unix.go
Expand Up @@ -94,8 +94,8 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
spec containerd.NewContainerOpts
)

cOpts = append(cOpts, containerd.WithContainerLabels(commands.LabelArgs(context.StringSlice("label"))))
if config {
cOpts = append(cOpts, containerd.WithContainerLabels(commands.LabelArgs(context.StringSlice("labels"))))
opts = append(opts, oci.WithSpecFromFile(context.String("config")))
} else {
var (
Expand All @@ -116,6 +116,7 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
return nil, err
}
opts = append(opts, oci.WithRootFSPath(rootfs))
cOpts = append(cOpts, containerd.WithContainerLabels(commands.LabelArgs(context.StringSlice("labels"))))
} else {
snapshotter := context.String("snapshotter")
var image containerd.Image
Expand All @@ -142,9 +143,12 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
return nil, err
}
}
labels := buildLabels(commands.LabelArgs(context.StringSlice("label")), image.Labels())
opts = append(opts, oci.WithImageConfig(image))
cOpts = append(cOpts,
containerd.WithImage(image),
containerd.WithImageConfigLabels(image),
containerd.WithAdditionalContainerLabels(labels),
containerd.WithSnapshotter(snapshotter))
if uidmap, gidmap := context.String("uidmap"), context.String("gidmap"); uidmap != "" && gidmap != "" {
uidMap, err := parseIDMapping(uidmap)
Expand Down
12 changes: 8 additions & 4 deletions cmd/ctr/commands/run/run_windows.go
Expand Up @@ -51,6 +51,7 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
if config {
id = context.Args().First()
opts = append(opts, oci.WithSpecFromFile(context.String("config")))
cOpts = append(cOpts, containerd.WithContainerLabels(commands.LabelArgs(context.StringSlice("label"))))
} else {
var (
ref = context.Args().First()
Expand Down Expand Up @@ -88,9 +89,13 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
}
}
opts = append(opts, oci.WithImageConfig(image))
cOpts = append(cOpts, containerd.WithImage(image))
cOpts = append(cOpts, containerd.WithSnapshotter(snapshotter))
cOpts = append(cOpts, containerd.WithNewSnapshot(id, image))
labels := buildLabels(commands.LabelArgs(context.StringSlice("label")), image.Labels())
cOpts = append(cOpts,
containerd.WithImage(image),
containerd.WithImageConfigLabels(image),
containerd.WithSnapshotter(snapshotter),
containerd.WithNewSnapshot(id, image),
containerd.WithAdditionalContainerLabels(labels))

if len(args) > 0 {
opts = append(opts, oci.WithProcessArgs(args...))
Expand Down Expand Up @@ -124,7 +129,6 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
}
}

cOpts = append(cOpts, containerd.WithContainerLabels(commands.LabelArgs(context.StringSlice("label"))))
runtime := context.String("runtime")
var runtimeOpts interface{}
if runtime == "io.containerd.runhcs.v1" {
Expand Down
38 changes: 38 additions & 0 deletions container_opts.go
Expand Up @@ -18,14 +18,19 @@ package containerd

import (
"context"
"encoding/json"
"fmt"

"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/oci"
"github.com/containerd/containerd/snapshots"
"github.com/containerd/typeurl"
"github.com/gogo/protobuf/types"
"github.com/opencontainers/image-spec/identity"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -95,6 +100,39 @@ func WithContainerLabels(labels map[string]string) NewContainerOpts {
}
}

// WithImageConfigLabels sets the image config labels on the container.
// The existing labels are cleared as this is expected to be the first
// operation in setting up a container's labels. Use WithAdditionalContainerLabels
// to add/overwrite the existing image config labels.
func WithImageConfigLabels(image Image) NewContainerOpts {
return func(ctx context.Context, _ *Client, c *containers.Container) error {
ic, err := image.Config(ctx)
if err != nil {
return err
}
var (
ociimage v1.Image
config v1.ImageConfig
)
switch ic.MediaType {
case v1.MediaTypeImageConfig, images.MediaTypeDockerSchema2Config:
p, err := content.ReadBlob(ctx, image.ContentStore(), ic)
if err != nil {
return err
}

if err := json.Unmarshal(p, &ociimage); err != nil {
return err
}
config = ociimage.Config
default:
return fmt.Errorf("unknown image config media type %s", ic.MediaType)
}
c.Labels = config.Labels
return nil
}
}

// WithAdditionalContainerLabels adds the provided labels to the container
// The existing labels are preserved as long as they do not conflict with the added labels.
func WithAdditionalContainerLabels(labels map[string]string) NewContainerOpts {
Expand Down
2 changes: 1 addition & 1 deletion pkg/cri/server/container_create.go
Expand Up @@ -230,7 +230,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
return nil, errors.Wrap(err, "failed to get container spec opts")
}

containerLabels := buildLabels(config.Labels, containerKindContainer)
containerLabels := buildLabels(config.Labels, image.ImageSpec.Config.Labels, containerKindContainer)

runtimeOptions, err := getRuntimeOptions(sandboxInfo)
if err != nil {
Expand Down
6 changes: 5 additions & 1 deletion pkg/cri/server/helpers.go
Expand Up @@ -283,8 +283,12 @@ func filterLabel(k, v string) string {
}

// buildLabel builds the labels from config to be passed to containerd
func buildLabels(configLabels map[string]string, containerType string) map[string]string {
func buildLabels(configLabels, imageConfigLabels map[string]string, containerType string) map[string]string {
labels := make(map[string]string)
for k, v := range imageConfigLabels {
labels[k] = v
}
// labels from the CRI request (config) will override labels in the image config
for k, v := range configLabels {
labels[k] = v
}
Expand Down
9 changes: 7 additions & 2 deletions pkg/cri/server/helpers_test.go
Expand Up @@ -118,14 +118,19 @@ func TestGetRepoDigestAndTag(t *testing.T) {
}

func TestBuildLabels(t *testing.T) {
imageConfigLabels := map[string]string{
"a": "z",
"d": "y",
}
configLabels := map[string]string{
"a": "b",
"c": "d",
}
newLabels := buildLabels(configLabels, containerKindSandbox)
assert.Len(t, newLabels, 3)
newLabels := buildLabels(configLabels, imageConfigLabels, containerKindSandbox)
assert.Len(t, newLabels, 4)
assert.Equal(t, "b", newLabels["a"])
assert.Equal(t, "d", newLabels["c"])
assert.Equal(t, "y", newLabels["d"])
assert.Equal(t, containerKindSandbox, newLabels[containerKindLabel])

newLabels["a"] = "e"
Expand Down
2 changes: 1 addition & 1 deletion pkg/cri/server/sandbox_run.go
Expand Up @@ -192,7 +192,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
return nil, errors.Wrap(err, "failed to generate sanbdox container spec options")
}

sandboxLabels := buildLabels(config.Labels, containerKindSandbox)
sandboxLabels := buildLabels(config.Labels, image.ImageSpec.Config.Labels, containerKindSandbox)

runtimeOpts, err := generateRuntimeOptions(ociRuntime, c.config)
if err != nil {
Expand Down