From 2a87d56171ea8e35839598488c059e7909f9d507 Mon Sep 17 00:00:00 2001 From: Yifan Gu Date: Wed, 13 May 2015 13:00:37 -0700 Subject: [PATCH] kubelet/rkt: Add getImageManifest() to retrive the image manifest for container. --- pkg/kubelet/rkt/image.go | 2 +- pkg/kubelet/rkt/rkt.go | 63 ++++++++++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/pkg/kubelet/rkt/image.go b/pkg/kubelet/rkt/image.go index 585b4de064d..25723838aa8 100644 --- a/pkg/kubelet/rkt/image.go +++ b/pkg/kubelet/rkt/image.go @@ -38,7 +38,7 @@ type image struct { // sha512-91e98d7f1679a097c878203c9659f2a26ae394656b3147963324c61fa3832f15 coreos.com/etcd:v2.0.9 // func (im *image) parseString(input string) error { - idName := strings.Split(input, "\t") + idName := strings.Split(strings.TrimSpace(input), "\t") if len(idName) != 2 { return fmt.Errorf("invalid image information from 'rkt images': %q", input) } diff --git a/pkg/kubelet/rkt/rkt.go b/pkg/kubelet/rkt/rkt.go index f91eb6eda82..8e4a2c251ec 100644 --- a/pkg/kubelet/rkt/rkt.go +++ b/pkg/kubelet/rkt/rkt.go @@ -349,12 +349,37 @@ func setApp(app *appctypes.App, c *api.Container) error { return setIsolators(app, c) } +// getImageManifest invokes 'rkt image cat-manifest' to retrive the image manifest +// for the image. +func (r *runtime) getImageManifest(image string) (*appcschema.ImageManifest, error) { + var manifest appcschema.ImageManifest + + // TODO(yifan): Assume docker images for now. + output, err := r.runCommand("image", "cat-manifest", "--quiet", dockerPrefix+image) + if err != nil { + return nil, err + } + if len(output) != 1 { + return nil, fmt.Errorf("no output") + } + return &manifest, json.Unmarshal([]byte(output[0]), &manifest) +} + // makePodManifest transforms a kubelet pod spec to the rkt pod manifest. // TODO(yifan): Use the RunContainerOptions generated by GenerateRunContainerOptions(). func (r *runtime) makePodManifest(pod *api.Pod) (*appcschema.PodManifest, error) { manifest := appcschema.BlankPodManifest() for _, c := range pod.Spec.Containers { + imgManifest, err := r.getImageManifest(c.Image) + if err != nil { + return nil, err + } + + if imgManifest.App == nil { + return nil, fmt.Errorf("no app section in image manifest for image: %q", c.Image) + } + img, err := r.getImageByName(c.Image) if err != nil { return nil, err @@ -364,22 +389,15 @@ func (r *runtime) makePodManifest(pod *api.Pod) (*appcschema.PodManifest, error) return nil, err } - // TODO(yifan): Override the image manifest's app and store it in the pod manifest. - // We need to get the image manifest. https://github.com/coreos/rkt/issues/850 - app := &appctypes.App{} - if err := setApp(app, &c); err != nil { - return nil, err - } - imageName, err := appctypes.NewACName(img.name) - if err != nil { + if err := setApp(imgManifest.App, &c); err != nil { return nil, err } manifest.Apps = append(manifest.Apps, appcschema.RuntimeApp{ // TODO(yifan): We should allow app name to be different with // image name. See https://github.com/coreos/rkt/pull/640. - Name: *imageName, + Name: imgManifest.Name, Image: appcschema.RuntimeImage{ID: *hash}, - App: app, + App: imgManifest.App, }) } @@ -1118,18 +1136,33 @@ func (r *runtime) listImages() ([]image, error) { } // getImageByName tries to find the image info with the given image name. -func (r *runtime) getImageByName(name string) (image, error) { - // TODO(yifan): Use rkt image cat-file when that is ready: - // https://github.com/coreos/rkt/pull/649 +func (r *runtime) getImageByName(imageName string) (image, error) { + // TODO(yifan): Print hash in rkt image? images, err := r.listImages() if err != nil { return image{}, err } + var name, version string + nameVersion := strings.Split(imageName, ":") + + // TODO(yifan): Currently the name cannot include "_", it is replaced + // by "-". See the issue in appc/spec: https://github.com/appc/spec/issues/406. + name, err = appctypes.SanitizeACName(nameVersion[0]) + if err != nil { + return image{}, err + } + + if len(nameVersion) == 2 { + version = nameVersion[1] + } + for _, img := range images { if img.name == name { - return img, nil + if version == "" || img.version == version { + return img, nil + } } } - return image{}, fmt.Errorf("cannot find the image %q", name) + return image{}, fmt.Errorf("cannot find the image %q", imageName) }