Skip to content
This repository was archived by the owner on Mar 9, 2022. It is now read-only.

Commit 84a720e

Browse files
committed
Add integration test
Signed-off-by: Lantao Liu <[email protected]>
1 parent 18ecffc commit 84a720e

3 files changed

Lines changed: 200 additions & 0 deletions

File tree

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/*
2+
Copyright 2018 The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package integration
18+
19+
import (
20+
"golang.org/x/net/context"
21+
"testing"
22+
"time"
23+
24+
"github.com/containerd/containerd"
25+
"github.com/containerd/containerd/errdefs"
26+
"github.com/pkg/errors"
27+
"github.com/stretchr/testify/assert"
28+
"github.com/stretchr/testify/require"
29+
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
30+
)
31+
32+
// Test to test the CRI plugin should see image pulled into containerd directly.
33+
func TestContainerdImage(t *testing.T) {
34+
testImage := "docker.io/library/busybox:latest"
35+
ctx := context.Background()
36+
37+
t.Logf("make sure the test image doesn't exist in the cri plugin")
38+
i, err := imageService.ImageStatus(&runtime.ImageSpec{Image: testImage})
39+
require.NoError(t, err)
40+
if i != nil {
41+
require.NoError(t, imageService.RemoveImage(&runtime.ImageSpec{Image: testImage}))
42+
}
43+
44+
t.Logf("pull the image into containerd")
45+
_, err = containerdClient.Pull(ctx, testImage, containerd.WithPullUnpack)
46+
assert.NoError(t, err)
47+
defer func() {
48+
// Make sure the image is cleaned up in any case.
49+
if err := containerdClient.ImageService().Delete(ctx, testImage); err != nil {
50+
assert.True(t, errdefs.IsNotFound(err), err)
51+
}
52+
assert.NoError(t, imageService.RemoveImage(&runtime.ImageSpec{Image: testImage}))
53+
}()
54+
55+
t.Logf("the image should be seen by the cri plugin")
56+
var id string
57+
checkImage := func() (bool, error) {
58+
img, err := imageService.ImageStatus(&runtime.ImageSpec{Image: testImage})
59+
if err != nil {
60+
return false, err
61+
}
62+
if img == nil {
63+
t.Logf("Image %q not show up in the cri plugin yet", testImage)
64+
return false, nil
65+
}
66+
id = img.Id
67+
img, err = imageService.ImageStatus(&runtime.ImageSpec{Image: id})
68+
if err != nil {
69+
return false, err
70+
}
71+
if img == nil {
72+
// We always generate image id as a reference first, it must
73+
// be ready here.
74+
return false, errors.New("can't reference image by id")
75+
}
76+
if len(img.RepoTags) != 1 {
77+
// RepoTags must have been populated correctly.
78+
return false, errors.Errorf("unexpected repotags: %+v", img.RepoTags)
79+
}
80+
if img.RepoTags[0] != testImage {
81+
return false, errors.Errorf("unexpected repotag %q", img.RepoTags[0])
82+
}
83+
return true, nil
84+
}
85+
require.NoError(t, Eventually(checkImage, 100*time.Millisecond, 10*time.Second))
86+
require.NoError(t, Consistently(checkImage, 100*time.Millisecond, time.Second))
87+
defer func() {
88+
t.Logf("image should still be seen by id if only tag get deleted")
89+
if err := containerdClient.ImageService().Delete(ctx, testImage); err != nil {
90+
assert.True(t, errdefs.IsNotFound(err), err)
91+
}
92+
assert.NoError(t, Consistently(func() (bool, error) {
93+
img, err := imageService.ImageStatus(&runtime.ImageSpec{Image: id})
94+
if err != nil {
95+
return false, err
96+
}
97+
return img != nil, nil
98+
}, 100*time.Millisecond, time.Second))
99+
t.Logf("image should be removed from the cri plugin if all references get deleted")
100+
if err := containerdClient.ImageService().Delete(ctx, id); err != nil {
101+
assert.True(t, errdefs.IsNotFound(err), err)
102+
}
103+
assert.NoError(t, Eventually(func() (bool, error) {
104+
img, err := imageService.ImageStatus(&runtime.ImageSpec{Image: id})
105+
if err != nil {
106+
return false, err
107+
}
108+
return img == nil, nil
109+
}, 100*time.Millisecond, 10*time.Second))
110+
}()
111+
112+
t.Logf("the image should be marked as managed")
113+
imgByRef, err := containerdClient.GetImage(ctx, testImage)
114+
assert.NoError(t, err)
115+
assert.Equal(t, imgByRef.Labels()["io.cri-containerd.image"], "managed")
116+
117+
t.Logf("the image id should be created and managed")
118+
imgByID, err := containerdClient.GetImage(ctx, id)
119+
assert.NoError(t, err)
120+
assert.Equal(t, imgByID.Labels()["io.cri-containerd.image"], "managed")
121+
122+
t.Logf("should be able to start container with the image")
123+
sbConfig := PodSandboxConfig("sandbox", "containerd-image")
124+
sb, err := runtimeService.RunPodSandbox(sbConfig)
125+
require.NoError(t, err)
126+
defer func() {
127+
assert.NoError(t, runtimeService.StopPodSandbox(sb))
128+
assert.NoError(t, runtimeService.RemovePodSandbox(sb))
129+
}()
130+
131+
cnConfig := ContainerConfig(
132+
"test-container",
133+
id,
134+
WithCommand("top"),
135+
)
136+
cn, err := runtimeService.CreateContainer(sb, cnConfig, sbConfig)
137+
require.NoError(t, err)
138+
require.NoError(t, runtimeService.StartContainer(cn))
139+
checkContainer := func() (bool, error) {
140+
s, err := runtimeService.ContainerStatus(cn)
141+
if err != nil {
142+
return false, err
143+
}
144+
return s.GetState() == runtime.ContainerState_CONTAINER_RUNNING, nil
145+
}
146+
require.NoError(t, Eventually(checkContainer, 100*time.Millisecond, 10*time.Second))
147+
require.NoError(t, Consistently(checkContainer, 100*time.Millisecond, time.Second))
148+
}

integration/restart_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package integration
1818

1919
import (
20+
"sort"
2021
"testing"
2122
"time"
2223

@@ -128,6 +129,17 @@ func TestContainerdRestart(t *testing.T) {
128129
}
129130
}
130131

132+
t.Logf("Pull test images")
133+
for _, image := range []string{"busybox", "alpine"} {
134+
img, err := imageService.PullImage(&runtime.ImageSpec{image}, nil)
135+
require.NoError(t, err)
136+
defer func() {
137+
assert.NoError(t, imageService.RemoveImage(&runtime.ImageSpec{Image: img}))
138+
}()
139+
}
140+
imagesBeforeRestart, err := imageService.ListImages(nil)
141+
assert.NoError(t, err)
142+
131143
t.Logf("Kill containerd")
132144
require.NoError(t, KillProcess("containerd"))
133145
defer func() {
@@ -179,4 +191,24 @@ func TestContainerdRestart(t *testing.T) {
179191
assert.NoError(t, runtimeService.StopPodSandbox(s.id))
180192
assert.NoError(t, runtimeService.RemovePodSandbox(s.id))
181193
}
194+
195+
t.Logf("Should recover all images")
196+
imagesAfterRestart, err := imageService.ListImages(nil)
197+
assert.NoError(t, err)
198+
assert.Equal(t, len(imagesBeforeRestart), len(imagesAfterRestart))
199+
for _, i1 := range imagesBeforeRestart {
200+
found := false
201+
for _, i2 := range imagesAfterRestart {
202+
if i1.Id == i2.Id {
203+
sort.Strings(i1.RepoTags)
204+
sort.Strings(i1.RepoDigests)
205+
sort.Strings(i2.RepoTags)
206+
sort.Strings(i2.RepoDigests)
207+
assert.Equal(t, i1, i2)
208+
found = true
209+
break
210+
}
211+
}
212+
assert.True(t, found, "should find image %+v", i1)
213+
}
182214
}

integration/test_utils.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,26 @@ func Eventually(f CheckFunc, period, timeout time.Duration) error {
260260
}
261261
}
262262

263+
// Consistently makes sure that f consistently returns true without
264+
// error before timeout exceeds. If f returns error, Consistently
265+
// will return the same error immediately.
266+
func Consistently(f CheckFunc, period, timeout time.Duration) error {
267+
start := time.Now()
268+
for {
269+
ok, err := f()
270+
if !ok {
271+
return errors.New("get false")
272+
}
273+
if err != nil {
274+
return err
275+
}
276+
if time.Since(start) >= timeout {
277+
return nil
278+
}
279+
time.Sleep(period)
280+
}
281+
}
282+
263283
// Randomize adds uuid after a string.
264284
func Randomize(str string) string {
265285
return str + "-" + util.GenerateID()

0 commit comments

Comments
 (0)