Add support for passing sandbox annotations to runtime
Signed-off-by: Harshal Patil <harshal.patil@in.ibm.com>
This commit is contained in:
parent
8672929207
commit
effd82227c
@ -138,6 +138,12 @@ The explanation and default value of each configuration item are as follows:
|
|||||||
# runtime_type is the runtime type to use in containerd e.g. io.containerd.runtime.v1.linux
|
# runtime_type is the runtime type to use in containerd e.g. io.containerd.runtime.v1.linux
|
||||||
runtime_type = "io.containerd.runc.v1"
|
runtime_type = "io.containerd.runc.v1"
|
||||||
|
|
||||||
|
# pod_annotations is list of pod annotations passed to both pod sandbox as well as
|
||||||
|
# container OCI annotations. Pod_annotations also support golang supported
|
||||||
|
# regular expression - https://github.com/google/re2/wiki/Syntax.
|
||||||
|
# e.g. ["runc.com.github.containers.runc.*"]
|
||||||
|
pod_annotations = []
|
||||||
|
|
||||||
# "plugins.cri.containerd.runtimes.runc.options" is options specific to
|
# "plugins.cri.containerd.runtimes.runc.options" is options specific to
|
||||||
# "io.containerd.runc.v1". Its corresponding options type is:
|
# "io.containerd.runc.v1". Its corresponding options type is:
|
||||||
# https://github.com/containerd/containerd/blob/v1.2.0-rc.1/runtime/v2/runc/options/oci.pb.go#L39.
|
# https://github.com/containerd/containerd/blob/v1.2.0-rc.1/runtime/v2/runc/options/oci.pb.go#L39.
|
||||||
|
@ -31,6 +31,9 @@ type Runtime struct {
|
|||||||
// This only works for runtime type "io.containerd.runtime.v1.linux".
|
// This only works for runtime type "io.containerd.runtime.v1.linux".
|
||||||
// DEPRECATED: use Options instead. Remove when shim v1 is deprecated.
|
// DEPRECATED: use Options instead. Remove when shim v1 is deprecated.
|
||||||
Engine string `toml:"runtime_engine" json:"runtimeEngine"`
|
Engine string `toml:"runtime_engine" json:"runtimeEngine"`
|
||||||
|
// PodAnnotations is list of pod annotations passed to both pod sandbox as well as
|
||||||
|
// container OCI annotations.
|
||||||
|
PodAnnotations []string `toml:"pod_annotations" json:"PodAnnotations"`
|
||||||
// Root is the directory used by containerd for runtime state.
|
// Root is the directory used by containerd for runtime state.
|
||||||
// DEPRECATED: use Options instead. Remove when shim v1 is deprecated.
|
// DEPRECATED: use Options instead. Remove when shim v1 is deprecated.
|
||||||
// This only works for runtime type "io.containerd.runtime.v1.linux".
|
// This only works for runtime type "io.containerd.runtime.v1.linux".
|
||||||
|
@ -165,7 +165,14 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
|
|||||||
// Generate container runtime spec.
|
// Generate container runtime spec.
|
||||||
mounts := c.generateContainerMounts(sandboxID, config)
|
mounts := c.generateContainerMounts(sandboxID, config)
|
||||||
|
|
||||||
spec, err := c.generateContainerSpec(id, sandboxID, sandboxPid, config, sandboxConfig, &image.ImageSpec.Config, append(mounts, volumeMounts...))
|
ociRuntime, err := c.getSandboxRuntime(sandboxConfig, sandbox.Metadata.RuntimeHandler)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to get sandbox runtime")
|
||||||
|
}
|
||||||
|
logrus.Debugf("Use OCI %+v for sandbox %q and container %q", ociRuntime, sandboxID, id)
|
||||||
|
|
||||||
|
spec, err := c.generateContainerSpec(id, sandboxID, sandboxPid, config, sandboxConfig,
|
||||||
|
&image.ImageSpec.Config, append(mounts, volumeMounts...), ociRuntime.PodAnnotations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to generate container %q spec", id)
|
return nil, errors.Wrapf(err, "failed to generate container %q spec", id)
|
||||||
}
|
}
|
||||||
@ -310,7 +317,8 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxPid uint32, config *runtime.ContainerConfig,
|
func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxPid uint32, config *runtime.ContainerConfig,
|
||||||
sandboxConfig *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig, extraMounts []*runtime.Mount) (*runtimespec.Spec, error) {
|
sandboxConfig *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig, extraMounts []*runtime.Mount,
|
||||||
|
runtimePodAnnotations []string) (*runtimespec.Spec, error) {
|
||||||
// Creates a spec Generator with the default spec.
|
// Creates a spec Generator with the default spec.
|
||||||
spec, err := defaultRuntimeSpec(id)
|
spec, err := defaultRuntimeSpec(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -444,6 +452,11 @@ func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxP
|
|||||||
g.AddProcessAdditionalGid(uint32(group))
|
g.AddProcessAdditionalGid(uint32(group))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for pKey, pValue := range getPassthroughAnnotations(sandboxConfig.Annotations,
|
||||||
|
runtimePodAnnotations) {
|
||||||
|
g.AddAnnotation(pKey, pValue)
|
||||||
|
}
|
||||||
|
|
||||||
g.AddAnnotation(annotations.ContainerType, annotations.ContainerTypeContainer)
|
g.AddAnnotation(annotations.ContainerType, annotations.ContainerTypeContainer)
|
||||||
g.AddAnnotation(annotations.SandboxID, sandboxID)
|
g.AddAnnotation(annotations.SandboxID, sandboxID)
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ import (
|
|||||||
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
||||||
|
|
||||||
"github.com/containerd/cri/pkg/annotations"
|
"github.com/containerd/cri/pkg/annotations"
|
||||||
|
criconfig "github.com/containerd/cri/pkg/config"
|
||||||
ostesting "github.com/containerd/cri/pkg/os/testing"
|
ostesting "github.com/containerd/cri/pkg/os/testing"
|
||||||
"github.com/containerd/cri/pkg/util"
|
"github.com/containerd/cri/pkg/util"
|
||||||
)
|
)
|
||||||
@ -116,6 +117,7 @@ func getCreateContainerTestData() (*runtime.ContainerConfig, *runtime.PodSandbox
|
|||||||
Namespace: "test-sandbox-ns",
|
Namespace: "test-sandbox-ns",
|
||||||
Attempt: 2,
|
Attempt: 2,
|
||||||
},
|
},
|
||||||
|
Annotations: map[string]string{"c": "d"},
|
||||||
Linux: &runtime.LinuxPodSandboxConfig{
|
Linux: &runtime.LinuxPodSandboxConfig{
|
||||||
CgroupParent: "/test/cgroup/parent",
|
CgroupParent: "/test/cgroup/parent",
|
||||||
},
|
},
|
||||||
@ -193,7 +195,7 @@ func TestGeneralContainerSpec(t *testing.T) {
|
|||||||
config, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData()
|
config, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData()
|
||||||
c := newTestCRIService()
|
c := newTestCRIService()
|
||||||
testSandboxID := "sandbox-id"
|
testSandboxID := "sandbox-id"
|
||||||
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil)
|
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil, []string{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
specCheck(t, testID, testSandboxID, testPid, spec)
|
specCheck(t, testID, testSandboxID, testPid, spec)
|
||||||
}
|
}
|
||||||
@ -248,7 +250,7 @@ func TestContainerCapabilities(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
t.Logf("TestCase %q", desc)
|
t.Logf("TestCase %q", desc)
|
||||||
config.Linux.SecurityContext.Capabilities = test.capability
|
config.Linux.SecurityContext.Capabilities = test.capability
|
||||||
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil)
|
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil, []string{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
specCheck(t, testID, testSandboxID, testPid, spec)
|
specCheck(t, testID, testSandboxID, testPid, spec)
|
||||||
for _, include := range test.includes {
|
for _, include := range test.includes {
|
||||||
@ -275,7 +277,7 @@ func TestContainerSpecTty(t *testing.T) {
|
|||||||
c := newTestCRIService()
|
c := newTestCRIService()
|
||||||
for _, tty := range []bool{true, false} {
|
for _, tty := range []bool{true, false} {
|
||||||
config.Tty = tty
|
config.Tty = tty
|
||||||
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil)
|
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil, []string{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
specCheck(t, testID, testSandboxID, testPid, spec)
|
specCheck(t, testID, testSandboxID, testPid, spec)
|
||||||
assert.Equal(t, tty, spec.Process.Terminal)
|
assert.Equal(t, tty, spec.Process.Terminal)
|
||||||
@ -287,6 +289,92 @@ func TestContainerSpecTty(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPodAnnotationPassthroughContainerSpec(t *testing.T) {
|
||||||
|
testID := "test-id"
|
||||||
|
testSandboxID := "sandbox-id"
|
||||||
|
testPid := uint32(1234)
|
||||||
|
|
||||||
|
for desc, test := range map[string]struct {
|
||||||
|
configCriService func(*criService)
|
||||||
|
configChange func(*runtime.PodSandboxConfig)
|
||||||
|
specCheck func(*testing.T, *runtimespec.Spec)
|
||||||
|
}{
|
||||||
|
// Scenario 1 - containerd config allows "c" and podSpec defines "c" to be passed to OCI
|
||||||
|
"passthroughAnnotations scenario 1": {
|
||||||
|
configCriService: func(c *criService) {
|
||||||
|
c.config.Runtimes = make(map[string]criconfig.Runtime)
|
||||||
|
c.config.Runtimes["runc"] = criconfig.Runtime{
|
||||||
|
PodAnnotations: []string{"c"},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
|
||||||
|
assert.Equal(t, spec.Annotations["c"], "d")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Scenario 2 - containerd config allows only "c" but podSpec defines "c" and "d"
|
||||||
|
// Only annotation "c" will be injected in OCI annotations and "d" should be dropped.
|
||||||
|
"passthroughAnnotations scenario 2": {
|
||||||
|
configChange: func(c *runtime.PodSandboxConfig) {
|
||||||
|
c.Annotations["d"] = "e"
|
||||||
|
},
|
||||||
|
configCriService: func(c *criService) {
|
||||||
|
c.config.Runtimes = make(map[string]criconfig.Runtime)
|
||||||
|
c.config.Runtimes["runc"] = criconfig.Runtime{
|
||||||
|
PodAnnotations: []string{"c"},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
|
||||||
|
assert.Equal(t, spec.Annotations["c"], "d")
|
||||||
|
_, ok := spec.Annotations["d"]
|
||||||
|
assert.Equal(t, ok, false)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Scenario 3 - Let's test some wildcard support
|
||||||
|
// podSpec has following annotations
|
||||||
|
"passthroughAnnotations scenario 3": {
|
||||||
|
configChange: func(c *runtime.PodSandboxConfig) {
|
||||||
|
c.Annotations["t.f"] = "j"
|
||||||
|
c.Annotations["z.g"] = "o"
|
||||||
|
c.Annotations["y.ca"] = "b"
|
||||||
|
},
|
||||||
|
configCriService: func(c *criService) {
|
||||||
|
c.config.Runtimes = make(map[string]criconfig.Runtime)
|
||||||
|
c.config.Runtimes["runc"] = criconfig.Runtime{
|
||||||
|
PodAnnotations: []string{"t*", "z.*", "y.c*"},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
|
||||||
|
assert.Equal(t, spec.Annotations["t.f"], "j")
|
||||||
|
assert.Equal(t, spec.Annotations["z.g"], "o")
|
||||||
|
assert.Equal(t, spec.Annotations["y.ca"], "b")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
|
||||||
|
t.Logf("TestCase %q", desc)
|
||||||
|
c := newTestCRIService()
|
||||||
|
config, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData()
|
||||||
|
if test.configChange != nil {
|
||||||
|
test.configChange(sandboxConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
if test.configCriService != nil {
|
||||||
|
test.configCriService(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid,
|
||||||
|
config, sandboxConfig, imageConfig, nil, c.config.Runtimes["runc"].PodAnnotations)
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, spec)
|
||||||
|
specCheck(t, testID, testSandboxID, testPid, spec)
|
||||||
|
if test.specCheck != nil {
|
||||||
|
test.specCheck(t, spec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestContainerSpecReadonlyRootfs(t *testing.T) {
|
func TestContainerSpecReadonlyRootfs(t *testing.T) {
|
||||||
testID := "test-id"
|
testID := "test-id"
|
||||||
testSandboxID := "sandbox-id"
|
testSandboxID := "sandbox-id"
|
||||||
@ -295,7 +383,7 @@ func TestContainerSpecReadonlyRootfs(t *testing.T) {
|
|||||||
c := newTestCRIService()
|
c := newTestCRIService()
|
||||||
for _, readonly := range []bool{true, false} {
|
for _, readonly := range []bool{true, false} {
|
||||||
config.Linux.SecurityContext.ReadonlyRootfs = readonly
|
config.Linux.SecurityContext.ReadonlyRootfs = readonly
|
||||||
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil)
|
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil, []string{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
specCheck(t, testID, testSandboxID, testPid, spec)
|
specCheck(t, testID, testSandboxID, testPid, spec)
|
||||||
assert.Equal(t, readonly, spec.Root.Readonly)
|
assert.Equal(t, readonly, spec.Root.Readonly)
|
||||||
@ -332,7 +420,7 @@ func TestContainerSpecWithExtraMounts(t *testing.T) {
|
|||||||
Readonly: false,
|
Readonly: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, extraMounts)
|
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, extraMounts, []string{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
specCheck(t, testID, testSandboxID, testPid, spec)
|
specCheck(t, testID, testSandboxID, testPid, spec)
|
||||||
var mounts, sysMounts, devMounts []runtimespec.Mount
|
var mounts, sysMounts, devMounts []runtimespec.Mount
|
||||||
@ -398,7 +486,7 @@ func TestContainerAndSandboxPrivileged(t *testing.T) {
|
|||||||
sandboxConfig.Linux.SecurityContext = &runtime.LinuxSandboxSecurityContext{
|
sandboxConfig.Linux.SecurityContext = &runtime.LinuxSandboxSecurityContext{
|
||||||
Privileged: test.sandboxPrivileged,
|
Privileged: test.sandboxPrivileged,
|
||||||
}
|
}
|
||||||
_, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil)
|
_, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil, []string{})
|
||||||
if test.expectError {
|
if test.expectError {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
} else {
|
} else {
|
||||||
@ -867,7 +955,7 @@ func TestPidNamespace(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
t.Logf("TestCase %q", desc)
|
t.Logf("TestCase %q", desc)
|
||||||
config.Linux.SecurityContext.NamespaceOptions = &runtime.NamespaceOption{Pid: test.pidNS}
|
config.Linux.SecurityContext.NamespaceOptions = &runtime.NamespaceOption{Pid: test.pidNS}
|
||||||
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil)
|
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil, []string{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Contains(t, spec.Linux.Namespaces, test.expected)
|
assert.Contains(t, spec.Linux.Namespaces, test.expected)
|
||||||
}
|
}
|
||||||
@ -1065,7 +1153,7 @@ func TestMaskedAndReadonlyPaths(t *testing.T) {
|
|||||||
sandboxConfig.Linux.SecurityContext = &runtime.LinuxSandboxSecurityContext{
|
sandboxConfig.Linux.SecurityContext = &runtime.LinuxSandboxSecurityContext{
|
||||||
Privileged: test.privileged,
|
Privileged: test.privileged,
|
||||||
}
|
}
|
||||||
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil)
|
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil, []string{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if !test.privileged { // specCheck presumes an unprivileged container
|
if !test.privileged { // specCheck presumes an unprivileged container
|
||||||
specCheck(t, testID, testSandboxID, testPid, spec)
|
specCheck(t, testID, testSandboxID, testPid, spec)
|
||||||
@ -1110,7 +1198,7 @@ func TestHostname(t *testing.T) {
|
|||||||
sandboxConfig.Linux.SecurityContext = &runtime.LinuxSandboxSecurityContext{
|
sandboxConfig.Linux.SecurityContext = &runtime.LinuxSandboxSecurityContext{
|
||||||
NamespaceOptions: &runtime.NamespaceOption{Network: test.networkNs},
|
NamespaceOptions: &runtime.NamespaceOption{Network: test.networkNs},
|
||||||
}
|
}
|
||||||
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil)
|
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil, []string{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
specCheck(t, testID, testSandboxID, testPid, spec)
|
specCheck(t, testID, testSandboxID, testPid, spec)
|
||||||
assert.Contains(t, spec.Process.Env, test.expectedEnv)
|
assert.Contains(t, spec.Process.Env, test.expectedEnv)
|
||||||
@ -1121,7 +1209,7 @@ func TestDisableCgroup(t *testing.T) {
|
|||||||
config, sandboxConfig, imageConfig, _ := getCreateContainerTestData()
|
config, sandboxConfig, imageConfig, _ := getCreateContainerTestData()
|
||||||
c := newTestCRIService()
|
c := newTestCRIService()
|
||||||
c.config.DisableCgroup = true
|
c.config.DisableCgroup = true
|
||||||
spec, err := c.generateContainerSpec("test-id", "sandbox-id", 1234, config, sandboxConfig, imageConfig, nil)
|
spec, err := c.generateContainerSpec("test-id", "sandbox-id", 1234, config, sandboxConfig, imageConfig, nil, []string{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Log("resource limit should not be set")
|
t.Log("resource limit should not be set")
|
||||||
|
@ -626,3 +626,20 @@ func getTaskStatus(ctx context.Context, task containerd.Task) (containerd.Status
|
|||||||
}
|
}
|
||||||
return status, nil
|
return status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getPassthroughAnnotations filters requested pod annotations by comparing
|
||||||
|
// against permitted annotations for the given runtime.
|
||||||
|
func getPassthroughAnnotations(podAnnotations map[string]string,
|
||||||
|
runtimePodAnnotations []string) (passthroughAnnotations map[string]string) {
|
||||||
|
passthroughAnnotations = make(map[string]string)
|
||||||
|
|
||||||
|
for podAnnotationKey, podAnnotationValue := range podAnnotations {
|
||||||
|
for _, r := range runtimePodAnnotations {
|
||||||
|
match, _ := regexp.MatchString(r, podAnnotationKey)
|
||||||
|
if match {
|
||||||
|
passthroughAnnotations[podAnnotationKey] = podAnnotationValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return passthroughAnnotations
|
||||||
|
}
|
||||||
|
@ -406,3 +406,40 @@ func TestCustomGenerator(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPassThroughAnnotationsFilter(t *testing.T) {
|
||||||
|
for desc, test := range map[string]struct {
|
||||||
|
podAnnotations map[string]string
|
||||||
|
runtimePodAnnotations []string
|
||||||
|
passthroughAnnotations map[string]string
|
||||||
|
}{
|
||||||
|
// Scenario 1 - containerd config allows "c" and podSpec defines "c" to be passed to OCI
|
||||||
|
"scenario1": {
|
||||||
|
podAnnotations: map[string]string{"c": "d"},
|
||||||
|
runtimePodAnnotations: []string{"c"},
|
||||||
|
passthroughAnnotations: map[string]string{"c": "d"},
|
||||||
|
},
|
||||||
|
// Scenario 2 - containerd config allows only "c" but podSpec defines "c" and "d"
|
||||||
|
// Only annotation "c" will be injected in OCI annotations and "d" should be dropped.
|
||||||
|
"scenario2": {
|
||||||
|
podAnnotations: map[string]string{"c": "d", "d": "e"},
|
||||||
|
runtimePodAnnotations: []string{"c"},
|
||||||
|
passthroughAnnotations: map[string]string{"c": "d"},
|
||||||
|
},
|
||||||
|
// Scenario 3 - Let's test some wildcard support
|
||||||
|
// podSpec has following annotations
|
||||||
|
"scenario3": {
|
||||||
|
podAnnotations: map[string]string{"t.f": "j",
|
||||||
|
"z.g": "o",
|
||||||
|
"y.ca": "b"},
|
||||||
|
runtimePodAnnotations: []string{"t*", "z.*", "y.c*"},
|
||||||
|
passthroughAnnotations: map[string]string{"t.f": "j",
|
||||||
|
"z.g": "o",
|
||||||
|
"y.ca": "b"},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Logf("TestCase %q", desc)
|
||||||
|
passthroughAnnotations := getPassthroughAnnotations(test.podAnnotations, test.runtimePodAnnotations)
|
||||||
|
assert.Equal(t, test.passthroughAnnotations, passthroughAnnotations)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -147,7 +147,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create sandbox container.
|
// Create sandbox container.
|
||||||
spec, err := c.generateSandboxContainerSpec(id, config, &image.ImageSpec.Config, sandbox.NetNSPath)
|
spec, err := c.generateSandboxContainerSpec(id, config, &image.ImageSpec.Config, sandbox.NetNSPath, ociRuntime.PodAnnotations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to generate sandbox container spec")
|
return nil, errors.Wrap(err, "failed to generate sandbox container spec")
|
||||||
}
|
}
|
||||||
@ -340,7 +340,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *criService) generateSandboxContainerSpec(id string, config *runtime.PodSandboxConfig,
|
func (c *criService) generateSandboxContainerSpec(id string, config *runtime.PodSandboxConfig,
|
||||||
imageConfig *imagespec.ImageConfig, nsPath string) (*runtimespec.Spec, error) {
|
imageConfig *imagespec.ImageConfig, nsPath string, runtimePodAnnotations []string) (*runtimespec.Spec, error) {
|
||||||
// Creates a spec Generator with the default spec.
|
// Creates a spec Generator with the default spec.
|
||||||
// TODO(random-liu): [P1] Compare the default settings with docker and containerd default.
|
// TODO(random-liu): [P1] Compare the default settings with docker and containerd default.
|
||||||
spec, err := defaultRuntimeSpec(id)
|
spec, err := defaultRuntimeSpec(id)
|
||||||
@ -452,6 +452,11 @@ func (c *criService) generateSandboxContainerSpec(id string, config *runtime.Pod
|
|||||||
}
|
}
|
||||||
g.SetProcessOOMScoreAdj(adj)
|
g.SetProcessOOMScoreAdj(adj)
|
||||||
|
|
||||||
|
for pKey, pValue := range getPassthroughAnnotations(config.Annotations,
|
||||||
|
runtimePodAnnotations) {
|
||||||
|
g.AddAnnotation(pKey, pValue)
|
||||||
|
}
|
||||||
|
|
||||||
g.AddAnnotation(annotations.ContainerType, annotations.ContainerTypeSandbox)
|
g.AddAnnotation(annotations.ContainerType, annotations.ContainerTypeSandbox)
|
||||||
g.AddAnnotation(annotations.SandboxID, id)
|
g.AddAnnotation(annotations.SandboxID, id)
|
||||||
g.AddAnnotation(annotations.SandboxLogDir, config.GetLogDirectory())
|
g.AddAnnotation(annotations.SandboxLogDir, config.GetLogDirectory())
|
||||||
|
@ -86,6 +86,7 @@ func TestGenerateSandboxContainerSpec(t *testing.T) {
|
|||||||
testID := "test-id"
|
testID := "test-id"
|
||||||
nsPath := "test-cni"
|
nsPath := "test-cni"
|
||||||
for desc, test := range map[string]struct {
|
for desc, test := range map[string]struct {
|
||||||
|
configCriService func(*criService)
|
||||||
configChange func(*runtime.PodSandboxConfig)
|
configChange func(*runtime.PodSandboxConfig)
|
||||||
imageConfigChange func(*imagespec.ImageConfig)
|
imageConfigChange func(*imagespec.ImageConfig)
|
||||||
specCheck func(*testing.T, *runtimespec.Spec)
|
specCheck func(*testing.T, *runtimespec.Spec)
|
||||||
@ -157,6 +158,56 @@ func TestGenerateSandboxContainerSpec(t *testing.T) {
|
|||||||
assert.Contains(t, spec.Process.User.AdditionalGids, uint32(2222))
|
assert.Contains(t, spec.Process.User.AdditionalGids, uint32(2222))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// Scenario 1 - containerd config allows "c" and podSpec defines "c" to be passed to OCI
|
||||||
|
"passthroughAnnotations scenario 1": {
|
||||||
|
configCriService: func(c *criService) {
|
||||||
|
c.config.Runtimes = make(map[string]criconfig.Runtime)
|
||||||
|
c.config.Runtimes["runc"] = criconfig.Runtime{
|
||||||
|
PodAnnotations: []string{"c"},
|
||||||
|
}
|
||||||
|
}, //assert.Equal(t, passthroughAnnotations["c"], "d")
|
||||||
|
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
|
||||||
|
assert.Equal(t, spec.Annotations["c"], "d")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Scenario 2 - containerd config allows only "c" but podSpec defines "c" and "d"
|
||||||
|
// Only annotation "c" will be injected in OCI annotations and "d" should be dropped.
|
||||||
|
"passthroughAnnotations scenario 2": {
|
||||||
|
configChange: func(c *runtime.PodSandboxConfig) {
|
||||||
|
c.Annotations["d"] = "e"
|
||||||
|
},
|
||||||
|
configCriService: func(c *criService) {
|
||||||
|
c.config.Runtimes = make(map[string]criconfig.Runtime)
|
||||||
|
c.config.Runtimes["runc"] = criconfig.Runtime{
|
||||||
|
PodAnnotations: []string{"c"},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
|
||||||
|
assert.Equal(t, spec.Annotations["c"], "d")
|
||||||
|
_, ok := spec.Annotations["d"]
|
||||||
|
assert.Equal(t, ok, false)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Scenario 3 - Let's test some wildcard support
|
||||||
|
// podSpec has following annotations
|
||||||
|
"passthroughAnnotations scenario 3": {
|
||||||
|
configChange: func(c *runtime.PodSandboxConfig) {
|
||||||
|
c.Annotations["t.f"] = "j"
|
||||||
|
c.Annotations["z.g"] = "o"
|
||||||
|
c.Annotations["y.ca"] = "b"
|
||||||
|
},
|
||||||
|
configCriService: func(c *criService) {
|
||||||
|
c.config.Runtimes = make(map[string]criconfig.Runtime)
|
||||||
|
c.config.Runtimes["runc"] = criconfig.Runtime{
|
||||||
|
PodAnnotations: []string{"t*", "z.*", "y.c*"},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
|
||||||
|
assert.Equal(t, spec.Annotations["t.f"], "j")
|
||||||
|
assert.Equal(t, spec.Annotations["z.g"], "o")
|
||||||
|
assert.Equal(t, spec.Annotations["y.ca"], "b")
|
||||||
|
},
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
t.Logf("TestCase %q", desc)
|
t.Logf("TestCase %q", desc)
|
||||||
c := newTestCRIService()
|
c := newTestCRIService()
|
||||||
@ -164,10 +215,16 @@ func TestGenerateSandboxContainerSpec(t *testing.T) {
|
|||||||
if test.configChange != nil {
|
if test.configChange != nil {
|
||||||
test.configChange(config)
|
test.configChange(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if test.configCriService != nil {
|
||||||
|
test.configCriService(c)
|
||||||
|
}
|
||||||
|
|
||||||
if test.imageConfigChange != nil {
|
if test.imageConfigChange != nil {
|
||||||
test.imageConfigChange(imageConfig)
|
test.imageConfigChange(imageConfig)
|
||||||
}
|
}
|
||||||
spec, err := c.generateSandboxContainerSpec(testID, config, imageConfig, nsPath)
|
spec, err := c.generateSandboxContainerSpec(testID, config, imageConfig, nsPath,
|
||||||
|
c.config.Runtimes["runc"].PodAnnotations)
|
||||||
if test.expectErr {
|
if test.expectErr {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Nil(t, spec)
|
assert.Nil(t, spec)
|
||||||
@ -355,6 +412,7 @@ options timeout:1
|
|||||||
c.os.(*ostesting.FakeOS).HostnameFn = func() (string, error) {
|
c.os.(*ostesting.FakeOS).HostnameFn = func() (string, error) {
|
||||||
return realhostname, nil
|
return realhostname, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := &runtime.PodSandboxConfig{
|
cfg := &runtime.PodSandboxConfig{
|
||||||
Hostname: test.hostname,
|
Hostname: test.hostname,
|
||||||
DnsConfig: test.dnsConfig,
|
DnsConfig: test.dnsConfig,
|
||||||
@ -773,7 +831,7 @@ func TestSandboxDisableCgroup(t *testing.T) {
|
|||||||
config, imageConfig, _ := getRunPodSandboxTestData()
|
config, imageConfig, _ := getRunPodSandboxTestData()
|
||||||
c := newTestCRIService()
|
c := newTestCRIService()
|
||||||
c.config.DisableCgroup = true
|
c.config.DisableCgroup = true
|
||||||
spec, err := c.generateSandboxContainerSpec("test-id", config, imageConfig, "test-cni")
|
spec, err := c.generateSandboxContainerSpec("test-id", config, imageConfig, "test-cni", []string{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Log("resource limit should not be set")
|
t.Log("resource limit should not be set")
|
||||||
|
Loading…
Reference in New Issue
Block a user