From 9c840494a27c07ea9994080a1f2cc92b7ffb6165 Mon Sep 17 00:00:00 2001 From: Tamer Tas Date: Tue, 2 Aug 2016 16:13:56 +0300 Subject: [PATCH 1/3] Create pkg/kubelet/rktshim package for rkt CRI integration --- pkg/kubelet/rktshim/doc.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 pkg/kubelet/rktshim/doc.go diff --git a/pkg/kubelet/rktshim/doc.go b/pkg/kubelet/rktshim/doc.go new file mode 100644 index 00000000000..9237d8b8fde --- /dev/null +++ b/pkg/kubelet/rktshim/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2016 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 rktshim is the package that contains the shim code for rkt to be used +// as the kubelet container runtime implementation that is integrated using the +// Container Runtime Interface. +package rktshim From f027b7a896cc61d31e56aac8ce67ad064111e59e Mon Sep 17 00:00:00 2001 From: Tamer Tas Date: Tue, 2 Aug 2016 15:54:25 +0300 Subject: [PATCH 2/3] Add ImageService stub for rkt CRI shim --- pkg/kubelet/rktshim/imagestore.go | 61 +++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 pkg/kubelet/rktshim/imagestore.go diff --git a/pkg/kubelet/rktshim/imagestore.go b/pkg/kubelet/rktshim/imagestore.go new file mode 100644 index 00000000000..9287498027d --- /dev/null +++ b/pkg/kubelet/rktshim/imagestore.go @@ -0,0 +1,61 @@ +/* +Copyright 2016 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 rktshim + +import ( + "errors" + + "k8s.io/kubernetes/pkg/kubelet/container" +) + +// TODO(tmrts): Move these errors to the container API for code re-use. +var ( + ErrImageNotFound = errors.New("rktshim: image not found") +) + +var _ container.ImageService = (*ImageStore)(nil) + +// ImageStore supports CRUD operations for images. +type ImageStore struct{} + +// TODO(tmrts): fill the image store configuration fields. +type ImageStoreConfig struct{} + +// NewImageStore creates an image storage that allows CRUD operations for images. +func NewImageStore(ImageStoreConfig) (container.ImageService, error) { + return &ImageStore{}, nil +} + +// List lists the images residing in the image store. +func (*ImageStore) List() ([]container.Image, error) { + panic("not implemented") +} + +// Pull pulls an image into the image store and uses the given authentication method. +func (*ImageStore) Pull(container.ImageSpec, container.AuthConfig, *container.PodSandboxConfig) error { + panic("not implemented") +} + +// Remove removes the image from the image store. +func (*ImageStore) Remove(container.ImageSpec) error { + panic("not implemented") +} + +// Status returns the status of the image. +func (*ImageStore) Status(container.ImageSpec) (container.Image, error) { + panic("not implemented") +} From 77777d558657ed1f8b81534c896d6c609af16d62 Mon Sep 17 00:00:00 2001 From: Tamer Tas Date: Tue, 2 Aug 2016 15:55:46 +0300 Subject: [PATCH 3/3] Test rkt CRI shim ImageStore --- pkg/kubelet/rktshim/imagestore_test.go | 205 +++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 pkg/kubelet/rktshim/imagestore_test.go diff --git a/pkg/kubelet/rktshim/imagestore_test.go b/pkg/kubelet/rktshim/imagestore_test.go new file mode 100644 index 00000000000..7170d36206e --- /dev/null +++ b/pkg/kubelet/rktshim/imagestore_test.go @@ -0,0 +1,205 @@ +/* +Copyright 2016 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 rktshim + +import ( + "fmt" + "reflect" + "testing" + + "k8s.io/kubernetes/pkg/kubelet/container" +) + +var ( + emptyImgStoreConfig = ImageStoreConfig{} + // TODO(tmrts): fill the pod configuration + testPodConfig *container.PodSandboxConfig = nil +) + +type imageTestCase struct { + Spec *container.ImageSpec + ExpectedStatus *container.Image +} + +func compareContainerImages(got, expected container.Image) error { + if got.ID != expected.ID { + return fmt.Errorf("mismatching IDs -> expected %q, got %q", got.ID, expected.ID) + } + + if !reflect.DeepEqual(got.RepoTags, expected.RepoTags) { + return fmt.Errorf("mismatching RepoTags -> expected %q, got %q", got.ID, expected.ID) + } + + if !reflect.DeepEqual(got.RepoDigests, expected.RepoDigests) { + return fmt.Errorf("mismatching RepoDigests -> expected %q, got %q", got.ID, expected.ID) + } + + if got.Size != expected.Size { + return fmt.Errorf("mismatching Sizes -> expected %q, got %q", got.ID, expected.ID) + } + + return nil +} + +var testImgSpecs = map[string]imageTestCase{ + "non-existent-image": { + &container.ImageSpec{ + Image: "XXXX_GIBBERISH_XXXX", + }, + nil, + }, + "busybox": { + &container.ImageSpec{ + Image: "busybox", + }, + &container.Image{ + ID: "", + RepoTags: []string{}, + RepoDigests: []string{}, + Size: 0, + }, + }, +} + +var testAuthConfig = map[string]container.AuthConfig{ + "no-auth": {}, +} + +func testNewImageStore(t *testing.T, cfg ImageStoreConfig) container.ImageService { + imgStore, err := NewImageStore(cfg) + if err != nil { + // TODO(tmrts): Implement stringer for rktshim.ImageStoreConfig for test readability. + t.Fatalf("rktshim.NewImageStore(%s) got error %q", cfg, err) + } + + return imgStore +} + +func TestPullsImageWithoutAuthentication(t *testing.T) { + t.SkipNow() + + imgStore := testNewImageStore(t, emptyImgStoreConfig) + + testImg := "busybox" + testImgSpec := *testImgSpecs[testImg].Spec + + if err := imgStore.Pull(testImgSpec, testAuthConfig["no-auth"], testPodConfig); err != nil { + t.Fatalf("rktshim.ImageStore.PullImage(%q) got error %q", testImg, err) + } +} + +func TestQueriesNonExistentImage(t *testing.T) { + t.SkipNow() + + imgStore := testNewImageStore(t, emptyImgStoreConfig) + + // New store shouldn't contain this image + testImg := "non-existent-image" + testImgSpec := *testImgSpecs[testImg].Spec + + if _, err := imgStore.Status(testImgSpec); err != ErrImageNotFound { + t.Errorf("rktshim.ImageStore.Status(%q) expected error %q, got %q", testImg, ErrImageNotFound, err) + } +} + +func TestQueriesExistentImage(t *testing.T) { + t.SkipNow() + + imgStore := testNewImageStore(t, emptyImgStoreConfig) + + testImg := "busybox" + testImgSpec := *testImgSpecs[testImg].Spec + expectedStatus := *testImgSpecs[testImg].ExpectedStatus + + imgStatus, err := imgStore.Status(testImgSpec) + if err != nil { + t.Fatalf("rktshim.ImageStore.Status(%q) got error %q", testImg, err) + } + + if err := compareContainerImages(imgStatus, expectedStatus); err != nil { + t.Errorf("rktshim.ImageStore.Status(%q) %v", testImg, err) + } +} + +func TestRemovesImage(t *testing.T) { + t.SkipNow() + + imgStore := testNewImageStore(t, emptyImgStoreConfig) + + testImg := "busybox" + testImgSpec := *testImgSpecs[testImg].Spec + + if err := imgStore.Pull(testImgSpec, testAuthConfig["no-auth"], testPodConfig); err != nil { + t.Fatalf("rktshim.ImageStore.Pull(%q) got error %q", testImg, err) + } + + if _, err := imgStore.Status(testImgSpec); err != nil { + t.Fatalf("rktshim.ImageStore.Status(%q) got error %q", testImg, err) + } + + if err := imgStore.Remove(testImgSpec); err != nil { + t.Fatalf("rktshim.ImageStore.Remove(%q) got error %q", testImg, err) + } + + if _, err := imgStore.Status(testImgSpec); err != ErrImageNotFound { + t.Fatalf("rktshim.ImageStore.Status(%q) expected error %q, got error %q", testImg, ErrImageNotFound, err) + } +} + +func TestRemovesNonExistentImage(t *testing.T) { + t.SkipNow() + + imgStore := testNewImageStore(t, emptyImgStoreConfig) + + testImg := "non-existent-image" + testImgSpec := *testImgSpecs[testImg].Spec + + if err := imgStore.Remove(testImgSpec); err != ErrImageNotFound { + t.Fatalf("rktshim.ImageStore.Remove(%q) expected error %q, got error %q", testImg, ErrImageNotFound, err) + } +} + +func TestListsImages(t *testing.T) { + t.SkipNow() + + imgStore := testNewImageStore(t, emptyImgStoreConfig) + + busyboxImg := "busybox" + busyboxImgSpec := *testImgSpecs[busyboxImg].Spec + if err := imgStore.Pull(busyboxImgSpec, testAuthConfig["no-auth"], testPodConfig); err != nil { + t.Fatalf("rktshim.ImageStore.Pull(%q) got error %q", busyboxImg, err) + } + + alpineImg := "alpine" + alpineImgSpec := *testImgSpecs[alpineImg].Spec + if err := imgStore.Pull(alpineImgSpec, testAuthConfig["no-auth"], testPodConfig); err != nil { + t.Fatalf("rktshim.ImageStore.Pull(%q) got error %q", alpineImg, err) + } + + imgs, err := imgStore.List() + if err != nil { + t.Fatalf("rktshim.ImageStore.List() got error %q", err) + } + + for _, img := range imgs { + expectedImg := *testImgSpecs[img.ID].ExpectedStatus + + if err := compareContainerImages(img, expectedImg); err != nil { + t.Errorf("rktshim.ImageStore.List() for %q, %v", img.ID, err) + } + } +}