@@ -43,7 +43,7 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||
|
||||
customopts "github.com/kubernetes-incubator/cri-containerd/pkg/opts"
|
||||
customopts "github.com/kubernetes-incubator/cri-containerd/pkg/containerd/opts"
|
||||
cio "github.com/kubernetes-incubator/cri-containerd/pkg/server/io"
|
||||
containerstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/container"
|
||||
"github.com/kubernetes-incubator/cri-containerd/pkg/util"
|
||||
|
||||
@@ -41,6 +41,7 @@ import (
|
||||
|
||||
"github.com/kubernetes-incubator/cri-containerd/pkg/store"
|
||||
imagestore "github.com/kubernetes-incubator/cri-containerd/pkg/store/image"
|
||||
"github.com/kubernetes-incubator/cri-containerd/pkg/util"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -187,35 +188,6 @@ func criContainerStateToString(state runtime.ContainerState) string {
|
||||
return runtime.ContainerState_name[int32(state)]
|
||||
}
|
||||
|
||||
// normalizeImageRef normalizes the image reference following the docker convention. This is added
|
||||
// mainly for backward compatibility.
|
||||
// The reference returned can only be either tagged or digested. For reference contains both tag
|
||||
// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@
|
||||
// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as
|
||||
// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa.
|
||||
func normalizeImageRef(ref string) (reference.Named, error) {
|
||||
named, err := reference.ParseNormalizedNamed(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := named.(reference.NamedTagged); ok {
|
||||
if canonical, ok := named.(reference.Canonical); ok {
|
||||
// The reference is both tagged and digested, only
|
||||
// return digested.
|
||||
newNamed, err := reference.WithName(canonical.Name())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newCanonical, err := reference.WithDigest(newNamed, canonical.Digest())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newCanonical, nil
|
||||
}
|
||||
}
|
||||
return reference.TagNameOnly(named), nil
|
||||
}
|
||||
|
||||
// getRepoDigestAngTag returns image repoDigest and repoTag of the named image reference.
|
||||
func getRepoDigestAndTag(namedRef reference.Named, digest imagedigest.Digest, schema1 bool) (string, string) {
|
||||
var repoTag, repoDigest string
|
||||
@@ -237,7 +209,7 @@ func (c *criContainerdService) localResolve(ctx context.Context, ref string) (*i
|
||||
_, err := imagedigest.Parse(ref)
|
||||
if err != nil {
|
||||
// ref is not image id, try to resolve it locally.
|
||||
normalized, err := normalizeImageRef(ref)
|
||||
normalized, err := util.NormalizeImageRef(ref)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid image reference %q: %v", ref, err)
|
||||
}
|
||||
|
||||
@@ -19,70 +19,11 @@ package server
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/containerd/containerd/reference"
|
||||
imagedigest "github.com/opencontainers/go-digest"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNormalizeImageRef(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
input string
|
||||
expect string
|
||||
}{
|
||||
{ // has nothing
|
||||
input: "busybox",
|
||||
expect: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{ // only has tag
|
||||
input: "busybox:latest",
|
||||
expect: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{ // only has digest
|
||||
input: "busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582",
|
||||
expect: "docker.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582",
|
||||
},
|
||||
{ // only has path
|
||||
input: "library/busybox",
|
||||
expect: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{ // only has hostname
|
||||
input: "docker.io/busybox",
|
||||
expect: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{ // has no tag
|
||||
input: "docker.io/library/busybox",
|
||||
expect: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{ // has no path
|
||||
input: "docker.io/busybox:latest",
|
||||
expect: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{ // has no hostname
|
||||
input: "library/busybox:latest",
|
||||
expect: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{ // full reference
|
||||
input: "docker.io/library/busybox:latest",
|
||||
expect: "docker.io/library/busybox:latest",
|
||||
},
|
||||
{ // gcr reference
|
||||
input: "gcr.io/library/busybox",
|
||||
expect: "gcr.io/library/busybox:latest",
|
||||
},
|
||||
{ // both tag and digest
|
||||
input: "gcr.io/library/busybox:latest@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582",
|
||||
expect: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582",
|
||||
},
|
||||
} {
|
||||
t.Logf("TestCase %q", test.input)
|
||||
normalized, err := normalizeImageRef(test.input)
|
||||
assert.NoError(t, err)
|
||||
output := normalized.String()
|
||||
assert.Equal(t, test.expect, output)
|
||||
_, err = reference.Parse(output)
|
||||
assert.NoError(t, err, "%q should be containerd supported reference", output)
|
||||
}
|
||||
}
|
||||
"github.com/kubernetes-incubator/cri-containerd/pkg/util"
|
||||
)
|
||||
|
||||
// TestGetUserFromImage tests the logic of getting image uid or user name of image user.
|
||||
func TestGetUserFromImage(t *testing.T) {
|
||||
@@ -154,7 +95,7 @@ func TestGetRepoDigestAndTag(t *testing.T) {
|
||||
},
|
||||
} {
|
||||
t.Logf("TestCase %q", desc)
|
||||
named, err := normalizeImageRef(test.ref)
|
||||
named, err := util.NormalizeImageRef(test.ref)
|
||||
assert.NoError(t, err)
|
||||
repoDigest, repoTag := getRepoDigestAndTag(named, digest, test.schema1)
|
||||
assert.Equal(t, test.expectedRepoDigest, repoDigest)
|
||||
|
||||
78
pkg/server/image_load.go
Normal file
78
pkg/server/image_load.go
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
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 server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"golang.org/x/net/context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
api "github.com/kubernetes-incubator/cri-containerd/pkg/api/v1"
|
||||
"github.com/kubernetes-incubator/cri-containerd/pkg/containerd/importer"
|
||||
imagestore "github.com/kubernetes-incubator/cri-containerd/pkg/store/image"
|
||||
)
|
||||
|
||||
// LoadImage loads a image into containerd.
|
||||
func (c *criContainerdService) LoadImage(ctx context.Context, r *api.LoadImageRequest) (*api.LoadImageResponse, error) {
|
||||
path := r.GetFilePath()
|
||||
if !filepath.IsAbs(path) {
|
||||
return nil, fmt.Errorf("path %q is not an absolute path", path)
|
||||
}
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open file: %v", err)
|
||||
}
|
||||
repoTags, err := importer.Import(ctx, c.client.ContentStore(), c.client.ImageService(), f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to import image: %v", err)
|
||||
}
|
||||
for _, repoTag := range repoTags {
|
||||
image, err := c.client.GetImage(ctx, repoTag)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get image %q: %v", repoTag, err)
|
||||
}
|
||||
if err := image.Unpack(ctx, c.config.ContainerdConfig.Snapshotter); err != nil {
|
||||
glog.Warningf("Failed to unpack image %q: %v", repoTag, err)
|
||||
// Do not fail image importing. Unpack will be retried when container creation.
|
||||
}
|
||||
info, err := getImageInfo(ctx, image, c.client.ContentStore())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get image %q info: %v", repoTag, err)
|
||||
}
|
||||
id := info.id
|
||||
|
||||
if err := c.createImageReference(ctx, id, image.Target()); err != nil {
|
||||
return nil, fmt.Errorf("failed to create image reference %q: %v", id, err)
|
||||
}
|
||||
img := imagestore.Image{
|
||||
ID: id,
|
||||
RepoTags: []string{repoTag},
|
||||
ChainID: info.chainID.String(),
|
||||
Size: info.size,
|
||||
Config: &info.config,
|
||||
Image: image,
|
||||
}
|
||||
|
||||
if err := c.imageStore.Add(img); err != nil {
|
||||
return nil, fmt.Errorf("failed to add image %q into store: %v", id, err)
|
||||
}
|
||||
glog.V(4).Infof("Imported image with id %q, repo tag %q", id, repoTag)
|
||||
}
|
||||
return &api.LoadImageResponse{Images: repoTags}, nil
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||
|
||||
imagestore "github.com/kubernetes-incubator/cri-containerd/pkg/store/image"
|
||||
"github.com/kubernetes-incubator/cri-containerd/pkg/util"
|
||||
)
|
||||
|
||||
// For image management:
|
||||
@@ -75,7 +76,7 @@ import (
|
||||
// PullImage pulls an image with authentication config.
|
||||
func (c *criContainerdService) PullImage(ctx context.Context, r *runtime.PullImageRequest) (*runtime.PullImageResponse, error) {
|
||||
imageRef := r.GetImage().GetImage()
|
||||
namedRef, err := normalizeImageRef(imageRef)
|
||||
namedRef, err := util.NormalizeImageRef(imageRef)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse image reference %q: %v", imageRef, err)
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import (
|
||||
"github.com/golang/glog"
|
||||
"golang.org/x/net/context"
|
||||
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||
|
||||
api "github.com/kubernetes-incubator/cri-containerd/pkg/api/v1"
|
||||
)
|
||||
|
||||
// instrumentedService wraps service and logs each operation.
|
||||
@@ -316,3 +318,15 @@ func (in *instrumentedService) ListContainerStats(ctx context.Context, r *runtim
|
||||
}()
|
||||
return in.criContainerdService.ListContainerStats(ctx, r)
|
||||
}
|
||||
|
||||
func (in *instrumentedService) LoadImage(ctx context.Context, r *api.LoadImageRequest) (res *api.LoadImageResponse, err error) {
|
||||
glog.V(4).Infof("LoadImage from file %q", r.GetFilePath())
|
||||
defer func() {
|
||||
if err != nil {
|
||||
glog.Errorf("LoadImage failed, error: %v", err)
|
||||
} else {
|
||||
glog.V(4).Infof("LoadImage returns images %+v", res.GetImages())
|
||||
}
|
||||
}()
|
||||
return in.criContainerdService.LoadImage(ctx, r)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||
|
||||
customopts "github.com/kubernetes-incubator/cri-containerd/pkg/opts"
|
||||
customopts "github.com/kubernetes-incubator/cri-containerd/pkg/containerd/opts"
|
||||
sandboxstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/sandbox"
|
||||
"github.com/kubernetes-incubator/cri-containerd/pkg/util"
|
||||
)
|
||||
|
||||
@@ -41,6 +41,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/kubelet/server/streaming"
|
||||
|
||||
"github.com/kubernetes-incubator/cri-containerd/cmd/cri-containerd/options"
|
||||
api "github.com/kubernetes-incubator/cri-containerd/pkg/api/v1"
|
||||
osinterface "github.com/kubernetes-incubator/cri-containerd/pkg/os"
|
||||
"github.com/kubernetes-incubator/cri-containerd/pkg/registrar"
|
||||
containerstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/container"
|
||||
@@ -62,6 +63,7 @@ type CRIContainerdService interface {
|
||||
Stop()
|
||||
runtime.RuntimeServiceServer
|
||||
runtime.ImageServiceServer
|
||||
api.CRIContainerdServiceServer
|
||||
}
|
||||
|
||||
// criContainerdService implements CRIContainerdService.
|
||||
@@ -167,8 +169,10 @@ func NewCRIContainerdService(config options.Config) (CRIContainerdService, error
|
||||
|
||||
// Create the grpc server and register runtime and image services.
|
||||
c.server = grpc.NewServer()
|
||||
runtime.RegisterRuntimeServiceServer(c.server, newInstrumentedService(c))
|
||||
runtime.RegisterImageServiceServer(c.server, newInstrumentedService(c))
|
||||
instrumented := newInstrumentedService(c)
|
||||
runtime.RegisterRuntimeServiceServer(c.server, instrumented)
|
||||
runtime.RegisterImageServiceServer(c.server, instrumented)
|
||||
api.RegisterCRIContainerdServiceServer(c.server, instrumented)
|
||||
|
||||
return newInstrumentedService(c), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user