diff --git a/integration/image_load_test.go b/integration/image_load_test.go new file mode 100644 index 000000000..f6bf514ba --- /dev/null +++ b/integration/image_load_test.go @@ -0,0 +1,93 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package integration + +import ( + "golang.org/x/net/context" + "io/ioutil" + "os" + "os/exec" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" + + api "github.com/kubernetes-incubator/cri-containerd/pkg/api/v1" +) + +// Test to load an image from tarball. +func TestImageLoad(t *testing.T) { + testImage := "busybox:latest" + loadedImage := "docker.io/library/" + testImage + _, err := exec.LookPath("docker") + if err != nil { + t.Skip("Docker is not available: %v", err) + } + t.Logf("docker save image into tarball") + output, err := exec.Command("docker", "pull", testImage).CombinedOutput() + require.NoError(t, err, "output: %q", output) + tarF, err := ioutil.TempFile("", "image-load") + tar := tarF.Name() + require.NoError(t, err) + defer func() { + assert.NoError(t, os.RemoveAll(tar)) + }() + output, err = exec.Command("docker", "save", testImage, "-o", tar).CombinedOutput() + require.NoError(t, err, "output: %q", output) + + t.Logf("make sure no such image in cri-containerd") + img, err := imageService.ImageStatus(&runtime.ImageSpec{Image: testImage}) + require.NoError(t, err) + if img != nil { + require.NoError(t, imageService.RemoveImage(&runtime.ImageSpec{Image: testImage})) + } + + t.Logf("load image in cri-containerd") + res, err := criContainerdClient.LoadImage(context.Background(), &api.LoadImageRequest{FilePath: tar}) + require.NoError(t, err) + require.Equal(t, []string{loadedImage}, res.GetImages()) + + t.Logf("make sure image is loaded") + img, err = imageService.ImageStatus(&runtime.ImageSpec{Image: testImage}) + require.NoError(t, err) + require.NotNil(t, img) + require.Equal(t, []string{loadedImage}, img.RepoTags) + + t.Logf("create a container with the loaded image") + sbConfig := PodSandboxConfig("sandbox", Randomize("image-load")) + sb, err := runtimeService.RunPodSandbox(sbConfig) + require.NoError(t, err) + defer func() { + assert.NoError(t, runtimeService.StopPodSandbox(sb)) + assert.NoError(t, runtimeService.RemovePodSandbox(sb)) + }() + containerConfig := ContainerConfig( + "container", + testImage, + WithCommand("tail", "-f", "/dev/null"), + ) + // Rely on sandbox clean to do container cleanup. + cn, err := runtimeService.CreateContainer(sb, containerConfig, sbConfig) + require.NoError(t, err) + require.NoError(t, runtimeService.StartContainer(cn)) + + t.Logf("make sure container is running") + status, err := runtimeService.ContainerStatus(cn) + require.NoError(t, err) + require.Equal(t, runtime.ContainerState_CONTAINER_RUNNING, status.State) +} diff --git a/integration/test_utils.go b/integration/test_utils.go index 498c62c59..a58047ba4 100644 --- a/integration/test_utils.go +++ b/integration/test_utils.go @@ -26,21 +26,25 @@ import ( "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" "k8s.io/kubernetes/pkg/kubelet/remote" + api "github.com/kubernetes-incubator/cri-containerd/pkg/api/v1" + "github.com/kubernetes-incubator/cri-containerd/pkg/client" "github.com/kubernetes-incubator/cri-containerd/pkg/util" ) const ( - sock = "/var/run/cri-containerd.sock" - timeout = 1 * time.Minute - pauseImage = "gcr.io/google_containers/pause:3.0" // This is the same with default sandbox image. - k8sNamespace = "k8s.io" // This is the same with server.k8sContainerdNamespace. - containerdEndpoint = "/run/containerd/containerd.sock" + sock = "/var/run/cri-containerd.sock" + timeout = 1 * time.Minute + pauseImage = "gcr.io/google_containers/pause:3.0" // This is the same with default sandbox image. + k8sNamespace = "k8s.io" // This is the same with server.k8sContainerdNamespace. + containerdEndpoint = "/run/containerd/containerd.sock" + criContainerdEndpoint = "/var/run/cri-containerd.sock" ) var ( - runtimeService cri.RuntimeService - imageService cri.ImageManagerService - containerdClient *containerd.Client + runtimeService cri.RuntimeService + imageService cri.ImageManagerService + containerdClient *containerd.Client + criContainerdClient api.CRIContainerdServiceClient ) func init() { @@ -57,6 +61,10 @@ func init() { if err != nil { glog.Exitf("Failed to connect containerd: %v", err) } + criContainerdClient, err = client.NewCRIContainerdClient(criContainerdEndpoint, timeout) + if err != nil { + glog.Exitf("Failed to connect cri-containerd: %v", err) + } } // Opts sets specific information in pod sandbox config. @@ -70,7 +78,7 @@ func PodSandboxConfig(name, ns string, opts ...PodSandboxOpts) *runtime.PodSandb // Using random id as uuid is good enough for local // integration test. Uid: util.GenerateID(), - Namespace: ns, + Namespace: Randomize(ns), }, Linux: &runtime.LinuxPodSandboxConfig{}, } @@ -106,6 +114,14 @@ func WithResources(r *runtime.LinuxContainerResources) ContainerOpts { } } +// Add container command. +func WithCommand(c string, args ...string) ContainerOpts { + return func(cf *runtime.ContainerConfig) { + cf.Command = []string{c} + cf.Args = args + } +} + // ContainerConfig creates a container config given a name and image name // and additional container config options func ContainerConfig(name, image string, opts ...ContainerOpts) *runtime.ContainerConfig { @@ -143,3 +159,8 @@ func Eventually(f CheckFunc, period, timeout time.Duration) error { time.Sleep(period) } } + +// Randomize adds uuid after a string. +func Randomize(str string) string { + return str + "-" + util.GenerateID() +}