Add windows implmenetation
Signed-off-by: Lantao Liu <lantaol@google.com>
This commit is contained in:
@@ -17,14 +17,183 @@ limitations under the License.
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||
|
||||
"github.com/containerd/cri/pkg/config"
|
||||
"github.com/containerd/cri/pkg/containerd/opts"
|
||||
)
|
||||
|
||||
func checkMount(t *testing.T, mounts []runtimespec.Mount, src, dest, typ string,
|
||||
contains, notcontains []string) {
|
||||
found := false
|
||||
for _, m := range mounts {
|
||||
if m.Source == src && m.Destination == dest {
|
||||
assert.Equal(t, m.Type, typ)
|
||||
for _, c := range contains {
|
||||
assert.Contains(t, m.Options, c)
|
||||
}
|
||||
for _, n := range notcontains {
|
||||
assert.NotContains(t, m.Options, n)
|
||||
}
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, found, "mount from %q to %q not found", src, dest)
|
||||
}
|
||||
|
||||
func TestGeneralContainerSpec(t *testing.T) {
|
||||
testID := "test-id"
|
||||
testPid := uint32(1234)
|
||||
containerConfig, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData()
|
||||
ociRuntime := config.Runtime{}
|
||||
c := newTestCRIService()
|
||||
testSandboxID := "sandbox-id"
|
||||
spec, err := c.containerSpec(testID, testSandboxID, testPid, "", containerConfig, sandboxConfig, imageConfig, nil, ociRuntime)
|
||||
require.NoError(t, err)
|
||||
specCheck(t, testID, testSandboxID, testPid, spec)
|
||||
}
|
||||
|
||||
func TestPodAnnotationPassthroughContainerSpec(t *testing.T) {
|
||||
testID := "test-id"
|
||||
testSandboxID := "sandbox-id"
|
||||
testPid := uint32(1234)
|
||||
|
||||
for desc, test := range map[string]struct {
|
||||
podAnnotations []string
|
||||
configChange func(*runtime.PodSandboxConfig)
|
||||
specCheck func(*testing.T, *runtimespec.Spec)
|
||||
}{
|
||||
"a passthrough annotation should be passed as an OCI annotation": {
|
||||
podAnnotations: []string{"c"},
|
||||
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
|
||||
assert.Equal(t, spec.Annotations["c"], "d")
|
||||
},
|
||||
},
|
||||
"a non-passthrough annotation should not be passed as an OCI annotation": {
|
||||
configChange: func(c *runtime.PodSandboxConfig) {
|
||||
c.Annotations["d"] = "e"
|
||||
},
|
||||
podAnnotations: []string{"c"},
|
||||
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
|
||||
assert.Equal(t, spec.Annotations["c"], "d")
|
||||
_, ok := spec.Annotations["d"]
|
||||
assert.False(t, ok)
|
||||
},
|
||||
},
|
||||
"passthrough annotations should support wildcard match": {
|
||||
configChange: func(c *runtime.PodSandboxConfig) {
|
||||
c.Annotations["t.f"] = "j"
|
||||
c.Annotations["z.g"] = "o"
|
||||
c.Annotations["z"] = "o"
|
||||
c.Annotations["y.ca"] = "b"
|
||||
c.Annotations["y"] = "b"
|
||||
},
|
||||
podAnnotations: []string{"t*", "z.*", "y.c*"},
|
||||
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
|
||||
t.Logf("%+v", spec.Annotations)
|
||||
assert.Equal(t, spec.Annotations["t.f"], "j")
|
||||
assert.Equal(t, spec.Annotations["z.g"], "o")
|
||||
assert.Equal(t, spec.Annotations["y.ca"], "b")
|
||||
_, ok := spec.Annotations["y"]
|
||||
assert.False(t, ok)
|
||||
_, ok = spec.Annotations["z"]
|
||||
assert.False(t, ok)
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(desc, func(t *testing.T) {
|
||||
c := newTestCRIService()
|
||||
containerConfig, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData()
|
||||
if test.configChange != nil {
|
||||
test.configChange(sandboxConfig)
|
||||
}
|
||||
|
||||
ociRuntime := config.Runtime{
|
||||
PodAnnotations: test.podAnnotations,
|
||||
}
|
||||
spec, err := c.containerSpec(testID, testSandboxID, testPid, "",
|
||||
containerConfig, sandboxConfig, imageConfig, nil, ociRuntime)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, spec)
|
||||
specCheck(t, testID, testSandboxID, testPid, spec)
|
||||
if test.specCheck != nil {
|
||||
test.specCheck(t, spec)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerSpecCommand(t *testing.T) {
|
||||
for desc, test := range map[string]struct {
|
||||
criEntrypoint []string
|
||||
criArgs []string
|
||||
imageEntrypoint []string
|
||||
imageArgs []string
|
||||
expected []string
|
||||
expectErr bool
|
||||
}{
|
||||
"should use cri entrypoint if it's specified": {
|
||||
criEntrypoint: []string{"a", "b"},
|
||||
imageEntrypoint: []string{"c", "d"},
|
||||
imageArgs: []string{"e", "f"},
|
||||
expected: []string{"a", "b"},
|
||||
},
|
||||
"should use cri entrypoint if it's specified even if it's empty": {
|
||||
criEntrypoint: []string{},
|
||||
criArgs: []string{"a", "b"},
|
||||
imageEntrypoint: []string{"c", "d"},
|
||||
imageArgs: []string{"e", "f"},
|
||||
expected: []string{"a", "b"},
|
||||
},
|
||||
"should use cri entrypoint and args if they are specified": {
|
||||
criEntrypoint: []string{"a", "b"},
|
||||
criArgs: []string{"c", "d"},
|
||||
imageEntrypoint: []string{"e", "f"},
|
||||
imageArgs: []string{"g", "h"},
|
||||
expected: []string{"a", "b", "c", "d"},
|
||||
},
|
||||
"should use image entrypoint if cri entrypoint is not specified": {
|
||||
criArgs: []string{"a", "b"},
|
||||
imageEntrypoint: []string{"c", "d"},
|
||||
imageArgs: []string{"e", "f"},
|
||||
expected: []string{"c", "d", "a", "b"},
|
||||
},
|
||||
"should use image args if both cri entrypoint and args are not specified": {
|
||||
imageEntrypoint: []string{"c", "d"},
|
||||
imageArgs: []string{"e", "f"},
|
||||
expected: []string{"c", "d", "e", "f"},
|
||||
},
|
||||
"should return error if both entrypoint and args are empty": {
|
||||
expectErr: true,
|
||||
},
|
||||
} {
|
||||
|
||||
config, _, imageConfig, _ := getCreateContainerTestData()
|
||||
config.Command = test.criEntrypoint
|
||||
config.Args = test.criArgs
|
||||
imageConfig.Entrypoint = test.imageEntrypoint
|
||||
imageConfig.Cmd = test.imageArgs
|
||||
|
||||
var spec runtimespec.Spec
|
||||
err := opts.WithProcessArgs(config, imageConfig)(context.Background(), nil, nil, &spec)
|
||||
if test.expectErr {
|
||||
assert.Error(t, err)
|
||||
continue
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, test.expected, spec.Process.Args, desc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVolumeMounts(t *testing.T) {
|
||||
testContainerRootDir := "test-container-root"
|
||||
for desc, test := range map[string]struct {
|
||||
@@ -95,3 +264,117 @@ func TestVolumeMounts(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerAnnotationPassthroughContainerSpec(t *testing.T) {
|
||||
testID := "test-id"
|
||||
testSandboxID := "sandbox-id"
|
||||
testPid := uint32(1234)
|
||||
|
||||
for desc, test := range map[string]struct {
|
||||
podAnnotations []string
|
||||
containerAnnotations []string
|
||||
podConfigChange func(*runtime.PodSandboxConfig)
|
||||
configChange func(*runtime.ContainerConfig)
|
||||
specCheck func(*testing.T, *runtimespec.Spec)
|
||||
}{
|
||||
"passthrough annotations from pod and container should be passed as an OCI annotation": {
|
||||
podConfigChange: func(p *runtime.PodSandboxConfig) {
|
||||
p.Annotations["pod.annotation.1"] = "1"
|
||||
p.Annotations["pod.annotation.2"] = "2"
|
||||
p.Annotations["pod.annotation.3"] = "3"
|
||||
},
|
||||
configChange: func(c *runtime.ContainerConfig) {
|
||||
c.Annotations["container.annotation.1"] = "1"
|
||||
c.Annotations["container.annotation.2"] = "2"
|
||||
c.Annotations["container.annotation.3"] = "3"
|
||||
},
|
||||
podAnnotations: []string{"pod.annotation.1"},
|
||||
containerAnnotations: []string{"container.annotation.1"},
|
||||
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
|
||||
assert.Equal(t, "1", spec.Annotations["container.annotation.1"])
|
||||
_, ok := spec.Annotations["container.annotation.2"]
|
||||
assert.False(t, ok)
|
||||
_, ok = spec.Annotations["container.annotation.3"]
|
||||
assert.False(t, ok)
|
||||
assert.Equal(t, "1", spec.Annotations["pod.annotation.1"])
|
||||
_, ok = spec.Annotations["pod.annotation.2"]
|
||||
assert.False(t, ok)
|
||||
_, ok = spec.Annotations["pod.annotation.3"]
|
||||
assert.False(t, ok)
|
||||
},
|
||||
},
|
||||
"passthrough annotations from pod and container should support wildcard": {
|
||||
podConfigChange: func(p *runtime.PodSandboxConfig) {
|
||||
p.Annotations["pod.annotation.1"] = "1"
|
||||
p.Annotations["pod.annotation.2"] = "2"
|
||||
p.Annotations["pod.annotation.3"] = "3"
|
||||
},
|
||||
configChange: func(c *runtime.ContainerConfig) {
|
||||
c.Annotations["container.annotation.1"] = "1"
|
||||
c.Annotations["container.annotation.2"] = "2"
|
||||
c.Annotations["container.annotation.3"] = "3"
|
||||
},
|
||||
podAnnotations: []string{"pod.annotation.*"},
|
||||
containerAnnotations: []string{"container.annotation.*"},
|
||||
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
|
||||
assert.Equal(t, "1", spec.Annotations["container.annotation.1"])
|
||||
assert.Equal(t, "2", spec.Annotations["container.annotation.2"])
|
||||
assert.Equal(t, "3", spec.Annotations["container.annotation.3"])
|
||||
assert.Equal(t, "1", spec.Annotations["pod.annotation.1"])
|
||||
assert.Equal(t, "2", spec.Annotations["pod.annotation.2"])
|
||||
assert.Equal(t, "3", spec.Annotations["pod.annotation.3"])
|
||||
},
|
||||
},
|
||||
"annotations should not pass through if no passthrough annotations are configured": {
|
||||
podConfigChange: func(p *runtime.PodSandboxConfig) {
|
||||
p.Annotations["pod.annotation.1"] = "1"
|
||||
p.Annotations["pod.annotation.2"] = "2"
|
||||
p.Annotations["pod.annotation.3"] = "3"
|
||||
},
|
||||
configChange: func(c *runtime.ContainerConfig) {
|
||||
c.Annotations["container.annotation.1"] = "1"
|
||||
c.Annotations["container.annotation.2"] = "2"
|
||||
c.Annotations["container.annotation.3"] = "3"
|
||||
},
|
||||
podAnnotations: []string{},
|
||||
containerAnnotations: []string{},
|
||||
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
|
||||
_, ok := spec.Annotations["container.annotation.1"]
|
||||
assert.False(t, ok)
|
||||
_, ok = spec.Annotations["container.annotation.2"]
|
||||
assert.False(t, ok)
|
||||
_, ok = spec.Annotations["container.annotation.3"]
|
||||
assert.False(t, ok)
|
||||
_, ok = spec.Annotations["pod.annotation.1"]
|
||||
assert.False(t, ok)
|
||||
_, ok = spec.Annotations["pod.annotation.2"]
|
||||
assert.False(t, ok)
|
||||
_, ok = spec.Annotations["pod.annotation.3"]
|
||||
assert.False(t, ok)
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(desc, func(t *testing.T) {
|
||||
c := newTestCRIService()
|
||||
containerConfig, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData()
|
||||
if test.configChange != nil {
|
||||
test.configChange(containerConfig)
|
||||
}
|
||||
if test.podConfigChange != nil {
|
||||
test.podConfigChange(sandboxConfig)
|
||||
}
|
||||
ociRuntime := config.Runtime{
|
||||
PodAnnotations: test.podAnnotations,
|
||||
ContainerAnnotations: test.containerAnnotations,
|
||||
}
|
||||
spec, err := c.containerSpec(testID, testSandboxID, testPid, "",
|
||||
containerConfig, sandboxConfig, imageConfig, nil, ociRuntime)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, spec)
|
||||
specCheck(t, testID, testSandboxID, testPid, spec)
|
||||
if test.specCheck != nil {
|
||||
test.specCheck(t, spec)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user