@@ -26,7 +26,10 @@ import (
2626
2727 "github.com/containerd/containerd/api/services/execution"
2828 "github.com/containerd/containerd/api/types/container"
29+ "github.com/containerd/containerd/api/types/mount"
30+ imagespec "github.com/opencontainers/image-spec/specs-go/v1"
2931 runtimespec "github.com/opencontainers/runtime-spec/specs-go"
32+ "github.com/opencontainers/runtime-tools/generate"
3033 "github.com/stretchr/testify/assert"
3134 "github.com/stretchr/testify/require"
3235 "golang.org/x/net/context"
@@ -38,7 +41,7 @@ import (
3841)
3942
4043func getStartContainerTestData () (* runtime.ContainerConfig , * runtime.PodSandboxConfig ,
41- func (* testing.T , string , uint32 , * runtimespec.Spec )) {
44+ * imagespec. ImageConfig , func (* testing.T , string , uint32 , * runtimespec.Spec )) {
4245 config := & runtime.ContainerConfig {
4346 Metadata : & runtime.ContainerMetadata {
4447 Name : "test-name" ,
@@ -92,11 +95,17 @@ func getStartContainerTestData() (*runtime.ContainerConfig, *runtime.PodSandboxC
9295 CgroupParent : "/test/cgroup/parent" ,
9396 },
9497 }
98+ imageConfig := & imagespec.ImageConfig {
99+ Env : []string {"ik1=iv1" , "ik2=iv2" },
100+ Entrypoint : []string {"/entrypoint" },
101+ Cmd : []string {"cmd" },
102+ WorkingDir : "/workspace" ,
103+ }
95104 specCheck := func (t * testing.T , id string , sandboxPid uint32 , spec * runtimespec.Spec ) {
96105 assert .Equal (t , relativeRootfsPath , spec .Root .Path )
97106 assert .Equal (t , []string {"test" , "command" , "test" , "args" }, spec .Process .Args )
98107 assert .Equal (t , "test-cwd" , spec .Process .Cwd )
99- assert .Contains (t , spec .Process .Env , "k1=v1" , "k2=v2" )
108+ assert .Contains (t , spec .Process .Env , "k1=v1" , "k2=v2" , "ik1=iv1" , "ik2=iv2" )
100109
101110 t .Logf ("Check bind mount" )
102111 found1 , found2 := false , false
@@ -159,27 +168,27 @@ func getStartContainerTestData() (*runtime.ContainerConfig, *runtime.PodSandboxC
159168 Path : getPIDNamespace (sandboxPid ),
160169 })
161170 }
162- return config , sandboxConfig , specCheck
171+ return config , sandboxConfig , imageConfig , specCheck
163172}
164173
165174func TestGeneralContainerSpec (t * testing.T ) {
166175 testID := "test-id"
167176 testPid := uint32 (1234 )
168- config , sandboxConfig , specCheck := getStartContainerTestData ()
177+ config , sandboxConfig , imageConfig , specCheck := getStartContainerTestData ()
169178 c := newTestCRIContainerdService ()
170- spec , err := c .generateContainerSpec (testID , testPid , config , sandboxConfig )
179+ spec , err := c .generateContainerSpec (testID , testPid , config , sandboxConfig , imageConfig )
171180 assert .NoError (t , err )
172181 specCheck (t , testID , testPid , spec )
173182}
174183
175184func TestContainerSpecTty (t * testing.T ) {
176185 testID := "test-id"
177186 testPid := uint32 (1234 )
178- config , sandboxConfig , specCheck := getStartContainerTestData ()
187+ config , sandboxConfig , imageConfig , specCheck := getStartContainerTestData ()
179188 c := newTestCRIContainerdService ()
180189 for _ , tty := range []bool {true , false } {
181190 config .Tty = tty
182- spec , err := c .generateContainerSpec (testID , testPid , config , sandboxConfig )
191+ spec , err := c .generateContainerSpec (testID , testPid , config , sandboxConfig , imageConfig )
183192 assert .NoError (t , err )
184193 specCheck (t , testID , testPid , spec )
185194 assert .Equal (t , tty , spec .Process .Terminal )
@@ -189,27 +198,90 @@ func TestContainerSpecTty(t *testing.T) {
189198func TestContainerSpecReadonlyRootfs (t * testing.T ) {
190199 testID := "test-id"
191200 testPid := uint32 (1234 )
192- config , sandboxConfig , specCheck := getStartContainerTestData ()
201+ config , sandboxConfig , imageConfig , specCheck := getStartContainerTestData ()
193202 c := newTestCRIContainerdService ()
194203 for _ , readonly := range []bool {true , false } {
195204 config .Linux .SecurityContext .ReadonlyRootfs = readonly
196- spec , err := c .generateContainerSpec (testID , testPid , config , sandboxConfig )
205+ spec , err := c .generateContainerSpec (testID , testPid , config , sandboxConfig , imageConfig )
197206 assert .NoError (t , err )
198207 specCheck (t , testID , testPid , spec )
199208 assert .Equal (t , readonly , spec .Root .Readonly )
200209 }
201210}
202211
212+ func TestContainerSpecCommand (t * testing.T ) {
213+ for desc , test := range map [string ]struct {
214+ criEntrypoint []string
215+ criArgs []string
216+ imageEntrypoint []string
217+ imageArgs []string
218+ expected []string
219+ expectErr bool
220+ }{
221+ "should use cri entrypoint if it's specified" : {
222+ criEntrypoint : []string {"a" , "b" },
223+ imageEntrypoint : []string {"c" , "d" },
224+ imageArgs : []string {"e" , "f" },
225+ expected : []string {"a" , "b" },
226+ },
227+ "should use cri entrypoint if it's specified even if it's empty" : {
228+ criEntrypoint : []string {},
229+ criArgs : []string {"a" , "b" },
230+ imageEntrypoint : []string {"c" , "d" },
231+ imageArgs : []string {"e" , "f" },
232+ expected : []string {"a" , "b" },
233+ },
234+ "should use cri entrypoint and args if they are specified" : {
235+ criEntrypoint : []string {"a" , "b" },
236+ criArgs : []string {"c" , "d" },
237+ imageEntrypoint : []string {"e" , "f" },
238+ imageArgs : []string {"g" , "h" },
239+ expected : []string {"a" , "b" , "c" , "d" },
240+ },
241+ "should use image entrypoint if cri entrypoint is not specified" : {
242+ criArgs : []string {"a" , "b" },
243+ imageEntrypoint : []string {"c" , "d" },
244+ imageArgs : []string {"e" , "f" },
245+ expected : []string {"c" , "d" , "a" , "b" },
246+ },
247+ "should use image args if both cri entrypoint and args are not specified" : {
248+ imageEntrypoint : []string {"c" , "d" },
249+ imageArgs : []string {"e" , "f" },
250+ expected : []string {"c" , "d" , "e" , "f" },
251+ },
252+ "should return error if both entrypoint and args are empty" : {
253+ expectErr : true ,
254+ },
255+ } {
256+
257+ config , _ , imageConfig , _ := getStartContainerTestData ()
258+ g := generate .New ()
259+ config .Command = test .criEntrypoint
260+ config .Args = test .criArgs
261+ imageConfig .Entrypoint = test .imageEntrypoint
262+ imageConfig .Cmd = test .imageArgs
263+ err := setOCIProcessArgs (& g , config , imageConfig )
264+ if test .expectErr {
265+ assert .Error (t , err )
266+ continue
267+ }
268+ assert .NoError (t , err )
269+ assert .Equal (t , test .expected , g .Spec ().Process .Args , desc )
270+ }
271+ }
272+
203273func TestStartContainer (t * testing.T ) {
204274 testID := "test-id"
205275 testSandboxID := "test-sandbox-id"
206276 testSandboxPid := uint32 (4321 )
207- config , sandboxConfig , specCheck := getStartContainerTestData ()
277+ testImageID := "sha256:c75bebcdd211f41b3a460c7bf82970ed6c75acaab9cd4c9a4e125b03ca113799"
278+ config , sandboxConfig , imageConfig , specCheck := getStartContainerTestData ()
208279 testMetadata := & metadata.ContainerMetadata {
209280 ID : testID ,
210281 Name : "test-name" ,
211282 SandboxID : testSandboxID ,
212283 Config : config ,
284+ ImageRef : testImageID ,
213285 CreatedAt : time .Now ().UnixNano (),
214286 }
215287 testSandboxMetadata := & metadata.SandboxMetadata {
@@ -222,10 +294,13 @@ func TestStartContainer(t *testing.T) {
222294 Pid : testSandboxPid ,
223295 Status : container .Status_RUNNING ,
224296 }
297+ testMounts := []* mount.Mount {{Type : "bind" , Source : "test-source" }}
225298 for desc , test := range map [string ]struct {
226299 containerMetadata * metadata.ContainerMetadata
227300 sandboxMetadata * metadata.SandboxMetadata
228301 sandboxContainerdContainer * container.Container
302+ imageMetadataErr bool
303+ snapshotMountsErr bool
229304 prepareFIFOErr error
230305 createContainerErr error
231306 startContainerErr error
@@ -288,6 +363,24 @@ func TestStartContainer(t *testing.T) {
288363 expectCalls : []string {"info" },
289364 expectErr : true ,
290365 },
366+ "should return error when image doesn't exist" : {
367+ containerMetadata : testMetadata ,
368+ sandboxMetadata : testSandboxMetadata ,
369+ sandboxContainerdContainer : testSandboxContainer ,
370+ imageMetadataErr : true ,
371+ expectStateChange : true ,
372+ expectCalls : []string {"info" },
373+ expectErr : true ,
374+ },
375+ "should return error when snapshot mounts fails" : {
376+ containerMetadata : testMetadata ,
377+ sandboxMetadata : testSandboxMetadata ,
378+ sandboxContainerdContainer : testSandboxContainer ,
379+ snapshotMountsErr : true ,
380+ expectStateChange : true ,
381+ expectCalls : []string {"info" },
382+ expectErr : true ,
383+ },
291384 "should return error when fail to open streaming pipes" : {
292385 containerMetadata : testMetadata ,
293386 sandboxMetadata : testSandboxMetadata ,
@@ -329,6 +422,7 @@ func TestStartContainer(t *testing.T) {
329422 c := newTestCRIContainerdService ()
330423 fake := c .containerService .(* servertesting.FakeExecutionClient )
331424 fakeOS := c .os .(* ostesting.FakeOS )
425+ fakeRootfsClient := c .rootfsService .(* servertesting.FakeRootfsClient )
332426 if test .containerMetadata != nil {
333427 assert .NoError (t , c .containerStore .Create (* test .containerMetadata ))
334428 }
@@ -338,6 +432,15 @@ func TestStartContainer(t *testing.T) {
338432 if test .sandboxContainerdContainer != nil {
339433 fake .SetFakeContainers ([]container.Container {* test .sandboxContainerdContainer })
340434 }
435+ if ! test .imageMetadataErr {
436+ assert .NoError (t , c .imageMetadataStore .Create (metadata.ImageMetadata {
437+ ID : testImageID ,
438+ Config : imageConfig ,
439+ }))
440+ }
441+ if ! test .snapshotMountsErr {
442+ fakeRootfsClient .SetFakeMounts (testID , testMounts )
443+ }
341444 // TODO(random-liu): Test behavior with different streaming config.
342445 fakeOS .OpenFifoFn = func (context.Context , string , int , os.FileMode ) (io.ReadWriteCloser , error ) {
343446 return nopReadWriteCloser {}, test .prepareFIFOErr
@@ -394,6 +497,7 @@ func TestStartContainer(t *testing.T) {
394497 calls := fake .GetCalledDetails ()
395498 createOpts , ok := calls [1 ].Argument .(* execution.CreateRequest )
396499 assert .True (t , ok , "2nd call should be create" )
500+ assert .Equal (t , testMounts , createOpts .Rootfs , "rootfs mounts should be correct" )
397501 // TODO(random-liu): Test other create options.
398502 spec := & runtimespec.Spec {}
399503 assert .NoError (t , json .Unmarshal (createOpts .Spec .Value , spec ))
0 commit comments