diff --git a/pkg/server/container_create.go b/pkg/server/container_create.go index 23444f242..eab069ddb 100644 --- a/pkg/server/container_create.go +++ b/pkg/server/container_create.go @@ -139,12 +139,12 @@ func (c *criContainerdService) CreateContainer(ctx context.Context, r *runtime.C // Create container volumes mounts. // TODO(random-liu): Add cri-containerd integration test for image volume. - volumeMounts := c.generateVolumeMounts(containerRootDir, config.GetMounts(), image.Config) + volumeMounts := c.generateVolumeMounts(containerRootDir, config.GetMounts(), &image.ImageSpec.Config) // Generate container runtime spec. mounts := c.generateContainerMounts(getSandboxRootDir(c.config.RootDir, sandboxID), config) - spec, err := c.generateContainerSpec(id, sandboxPid, config, sandboxConfig, image.Config, append(mounts, volumeMounts...)) + spec, err := c.generateContainerSpec(id, sandboxPid, config, sandboxConfig, &image.ImageSpec.Config, append(mounts, volumeMounts...)) if err != nil { return nil, fmt.Errorf("failed to generate container %q spec: %v", id, err) } diff --git a/pkg/server/container_stop.go b/pkg/server/container_stop.go index 9c7260096..1a56a570b 100644 --- a/pkg/server/container_stop.go +++ b/pkg/server/container_stop.go @@ -80,11 +80,11 @@ func (c *criContainerdService) stopContainer(ctx context.Context, container cont // an error here. return fmt.Errorf("failed to get image metadata %q: %v", container.ImageRef, err) } - if image.Config.StopSignal != "" { - stopSignal, err = signal.ParseSignal(image.Config.StopSignal) + if image.ImageSpec.Config.StopSignal != "" { + stopSignal, err = signal.ParseSignal(image.ImageSpec.Config.StopSignal) if err != nil { return fmt.Errorf("failed to parse stop signal %q: %v", - image.Config.StopSignal, err) + image.ImageSpec.Config.StopSignal, err) } } glog.V(2).Infof("Stop container %q with signal %v", id, stopSignal) diff --git a/pkg/server/helpers.go b/pkg/server/helpers.go index b26878623..aae516f18 100644 --- a/pkg/server/helpers.go +++ b/pkg/server/helpers.go @@ -308,10 +308,10 @@ func loadCgroup(cgroupPath string) (cgroups.Cgroup, error) { // imageInfo is the information about the image got from containerd. type imageInfo struct { - id string - chainID imagedigest.Digest - size int64 - config imagespec.ImageConfig + id string + chainID imagedigest.Digest + size int64 + imagespec imagespec.Image } // getImageInfo gets image info from containerd. @@ -344,10 +344,10 @@ func getImageInfo(ctx context.Context, image containerd.Image) (*imageInfo, erro } return &imageInfo{ - id: id, - chainID: chainID, - size: size, - config: ociimage.Config, + id: id, + chainID: chainID, + size: size, + imagespec: ociimage, }, nil } diff --git a/pkg/server/image_list.go b/pkg/server/image_list.go index 322a62536..f6bbd090d 100644 --- a/pkg/server/image_list.go +++ b/pkg/server/image_list.go @@ -47,7 +47,7 @@ func toCRIImage(image imagestore.Image) *runtime.Image { RepoDigests: image.RepoDigests, Size_: uint64(image.Size), } - uid, username := getUserFromImage(image.Config.User) + uid, username := getUserFromImage(image.ImageSpec.Config.User) if uid != nil { runtimeImage.Uid = &runtime.Int64Value{Value: *uid} } diff --git a/pkg/server/image_list_test.go b/pkg/server/image_list_test.go index 631aad6a5..81286a2a9 100644 --- a/pkg/server/image_list_test.go +++ b/pkg/server/image_list_test.go @@ -37,8 +37,10 @@ func TestListImages(t *testing.T) { RepoTags: []string{"tag-a-1", "tag-b-1"}, RepoDigests: []string{"digest-a-1", "digest-b-1"}, Size: 1000, - Config: &imagespec.ImageConfig{ - User: "root", + ImageSpec: imagespec.Image{ + Config: imagespec.ImageConfig{ + User: "root", + }, }, }, { @@ -47,8 +49,10 @@ func TestListImages(t *testing.T) { RepoTags: []string{"tag-a-2", "tag-b-2"}, RepoDigests: []string{"digest-a-2", "digest-b-2"}, Size: 2000, - Config: &imagespec.ImageConfig{ - User: "1234:1234", + ImageSpec: imagespec.Image{ + Config: imagespec.ImageConfig{ + User: "1234:1234", + }, }, }, { @@ -57,8 +61,10 @@ func TestListImages(t *testing.T) { RepoTags: []string{"tag-a-3", "tag-b-3"}, RepoDigests: []string{"digest-a-3", "digest-b-3"}, Size: 3000, - Config: &imagespec.ImageConfig{ - User: "nobody", + ImageSpec: imagespec.Image{ + Config: imagespec.ImageConfig{ + User: "nobody", + }, }, }, } diff --git a/pkg/server/image_load.go b/pkg/server/image_load.go index 5a3f54668..4ebae480e 100644 --- a/pkg/server/image_load.go +++ b/pkg/server/image_load.go @@ -61,13 +61,14 @@ func (c *criContainerdService) LoadImage(ctx context.Context, r *api.LoadImageRe 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, + ID: id, + RepoTags: []string{repoTag}, + ChainID: info.chainID.String(), + Size: info.size, + ImageSpec: info.imagespec, + Image: image, } if err := c.imageStore.Add(img); err != nil { diff --git a/pkg/server/image_pull.go b/pkg/server/image_pull.go index 43ee706a4..0f0675da8 100644 --- a/pkg/server/image_pull.go +++ b/pkg/server/image_pull.go @@ -137,11 +137,11 @@ func (c *criContainerdService) PullImage(ctx context.Context, r *runtime.PullIma glog.V(4).Infof("Pulled image %q with image id %q, repo tag %q, repo digest %q", imageRef, imageID, repoTag, repoDigest) img := imagestore.Image{ - ID: imageID, - ChainID: info.chainID.String(), - Size: info.size, - Config: &info.config, - Image: image, + ID: imageID, + ChainID: info.chainID.String(), + Size: info.size, + ImageSpec: info.imagespec, + Image: image, } if repoDigest != "" { img.RepoDigests = []string{repoDigest} diff --git a/pkg/server/image_status.go b/pkg/server/image_status.go index b8e9afe36..8160d89df 100644 --- a/pkg/server/image_status.go +++ b/pkg/server/image_status.go @@ -17,10 +17,15 @@ limitations under the License. package server import ( + "encoding/json" "fmt" + "github.com/golang/glog" "golang.org/x/net/context" "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" + + imagestore "github.com/kubernetes-incubator/cri-containerd/pkg/store/image" + imagespec "github.com/opencontainers/image-spec/specs-go/v1" ) // ImageStatus returns the status of the image, returns nil if the image isn't present. @@ -37,18 +42,62 @@ func (c *criContainerdService) ImageStatus(ctx context.Context, r *runtime.Image } // TODO(random-liu): [P0] Make sure corresponding snapshot exists. What if snapshot // doesn't exist? + + runtimeImage := toCRIRuntimeImage(image) + info, err := c.toCRIImageInfo(ctx, image, r.GetVerbose()) + if err != nil { + return nil, fmt.Errorf("failed to generate image info: %v", err) + } + + return &runtime.ImageStatusResponse{ + Image: runtimeImage, + Info: info, + }, nil +} + +// toCRIRuntimeImage converts internal image object to CRI runtime.Image. +func toCRIRuntimeImage(image *imagestore.Image) *runtime.Image { runtimeImage := &runtime.Image{ Id: image.ID, RepoTags: image.RepoTags, RepoDigests: image.RepoDigests, Size_: uint64(image.Size), } - uid, username := getUserFromImage(image.Config.User) + uid, username := getUserFromImage(image.ImageSpec.Config.User) if uid != nil { runtimeImage.Uid = &runtime.Int64Value{Value: *uid} } runtimeImage.Username = username - // TODO(mikebrow): write a ImageMetadata to runtime.Image converter - return &runtime.ImageStatusResponse{Image: runtimeImage}, nil + return runtimeImage +} + +// TODO (mikebrow): discuss moving this struct and / or constants for info map for some or all of these fields to CRI +type verboseImageInfo struct { + ChainID string `json:"chainID"` + ImageSpec imagespec.Image `json:"imageSpec"` +} + +// toCRIImageInfo converts internal image object information to CRI image status response info map. +func (c *criContainerdService) toCRIImageInfo(ctx context.Context, image *imagestore.Image, verbose bool) (map[string]string, error) { + if !verbose { + return nil, nil + } + + info := make(map[string]string) + + imi := &verboseImageInfo{ + ChainID: image.ChainID, + ImageSpec: image.ImageSpec, + } + + m, err := json.Marshal(imi) + if err == nil { + info["info"] = string(m) + } else { + glog.Errorf("failed to marshal info %v: %v", imi, err) + info["info"] = err.Error() + } + + return info, nil } diff --git a/pkg/server/image_status_test.go b/pkg/server/image_status_test.go index 41b45ec4b..d55404d7b 100644 --- a/pkg/server/image_status_test.go +++ b/pkg/server/image_status_test.go @@ -36,8 +36,10 @@ func TestImageStatus(t *testing.T) { RepoTags: []string{"a", "b"}, RepoDigests: []string{"c", "d"}, Size: 1234, - Config: &imagespec.ImageConfig{ - User: "user:group", + ImageSpec: imagespec.Image{ + Config: imagespec.ImageConfig{ + User: "user:group", + }, }, } expected := &runtime.Image{ diff --git a/pkg/server/restart.go b/pkg/server/restart.go index fdfdd45b8..942147c19 100644 --- a/pkg/server/restart.go +++ b/pkg/server/restart.go @@ -365,11 +365,11 @@ func loadImages(ctx context.Context, cImages []containerd.Image, continue } image := imagestore.Image{ - ID: id, - ChainID: info.chainID.String(), - Size: info.size, - Config: &info.config, - Image: i, + ID: id, + ChainID: info.chainID.String(), + Size: info.size, + ImageSpec: info.imagespec, + Image: i, } // Recover repo digests and repo tags. for _, i := range imgs { diff --git a/pkg/server/sandbox_run.go b/pkg/server/sandbox_run.go index 832b28664..456b6b25c 100644 --- a/pkg/server/sandbox_run.go +++ b/pkg/server/sandbox_run.go @@ -123,7 +123,7 @@ func (c *criContainerdService) RunPodSandbox(ctx context.Context, r *runtime.Run } // Create sandbox container. - spec, err := c.generateSandboxContainerSpec(id, config, image.Config, sandbox.NetNSPath) + spec, err := c.generateSandboxContainerSpec(id, config, &image.ImageSpec.Config, sandbox.NetNSPath) if err != nil { return nil, fmt.Errorf("failed to generate sandbox container spec: %v", err) } diff --git a/pkg/store/image/image.go b/pkg/store/image/image.go index 093a42fa3..ad38cf139 100644 --- a/pkg/store/image/image.go +++ b/pkg/store/image/image.go @@ -40,8 +40,9 @@ type Image struct { ChainID string // Size is the compressed size of the image. Size int64 - // Config is the oci image config of the image. - Config *imagespec.ImageConfig + // ImageSpec is the oci image structure which describes basic information about the image. + ImageSpec imagespec.Image + // Containerd image reference Image containerd.Image } diff --git a/pkg/store/image/image_test.go b/pkg/store/image/image_test.go index 3502a3340..1d538f5e5 100644 --- a/pkg/store/image/image_test.go +++ b/pkg/store/image/image_test.go @@ -20,7 +20,6 @@ import ( "strings" "testing" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" assertlib "github.com/stretchr/testify/assert" "github.com/kubernetes-incubator/cri-containerd/pkg/store" @@ -34,7 +33,6 @@ func TestImageStore(t *testing.T) { RepoTags: []string{"tag-1"}, RepoDigests: []string{"digest-1"}, Size: 10, - Config: &imagespec.ImageConfig{}, }, { ID: "sha256:2123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", @@ -42,7 +40,6 @@ func TestImageStore(t *testing.T) { RepoTags: []string{"tag-2abcd"}, RepoDigests: []string{"digest-2abcd"}, Size: 20, - Config: &imagespec.ImageConfig{}, }, { ID: "sha256:3123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", @@ -50,7 +47,6 @@ func TestImageStore(t *testing.T) { RepoDigests: []string{"digest-4a333"}, ChainID: "test-chain-id-4a333", Size: 30, - Config: &imagespec.ImageConfig{}, }, { ID: "sha256:4123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", @@ -58,7 +54,6 @@ func TestImageStore(t *testing.T) { RepoDigests: []string{"digest-4abcd"}, ChainID: "test-chain-id-4abcd", Size: 40, - Config: &imagespec.ImageConfig{}, }, } assert := assertlib.New(t)