Address run/create performance issues

Fixed the logic where we observed different performance
results when running an image by its fqname vs a shortname. In
the case of the latter, we resolve the name without using the
network.

Signed-off-by: baude <bbaude@redhat.com>

Closes: #37
Approved by: rhatdan
This commit is contained in:
baude
2017-11-13 12:40:21 -06:00
committed by Atomic Bot
parent 7df3221232
commit 5cfd7a313f
4 changed files with 97 additions and 16 deletions

View File

@ -135,6 +135,7 @@ var createCommand = cli.Command{
func createCmd(c *cli.Context) error {
// TODO should allow user to create based off a directory on the host not just image
// Need CLI support for this
var imageName string
if err := validateFlags(c, createFlags); err != nil {
return err
}
@ -151,7 +152,8 @@ func createCmd(c *cli.Context) error {
// Deal with the image after all the args have been checked
createImage := runtime.NewImage(createConfig.image)
if !createImage.HasImageLocal() {
createImage.LocalName, _ = createImage.GetLocalImageName()
if createImage.LocalName == "" {
// The image wasnt found by the user input'd name or its fqname
// Pull the image
fmt.Printf("Trying to pull %s...", createImage.PullName)
@ -163,7 +165,11 @@ func createCmd(c *cli.Context) error {
return err
}
defer runtime.Shutdown(false)
imageName, err := createImage.GetFQName()
if createImage.LocalName != "" {
imageName = createImage.LocalName
} else {
imageName, err = createImage.GetFQName()
}
if err != nil {
return err
}

View File

@ -22,6 +22,7 @@ var runCommand = cli.Command{
}
func runCmd(c *cli.Context) error {
var imageName string
if err := validateFlags(c, createFlags); err != nil {
return err
}
@ -37,8 +38,8 @@ func runCmd(c *cli.Context) error {
}
createImage := runtime.NewImage(createConfig.image)
if !createImage.HasImageLocal() {
createImage.LocalName, _ = createImage.GetLocalImageName()
if createImage.LocalName == "" {
// The image wasnt found by the user input'd name or its fqname
// Pull the image
fmt.Printf("Trying to pull %s...", createImage.PullName)
@ -52,7 +53,11 @@ func runCmd(c *cli.Context) error {
defer runtime.Shutdown(false)
logrus.Debug("spec is ", runtimeSpec)
imageName, err := createImage.GetFQName()
if createImage.LocalName != "" {
imageName = createImage.LocalName
} else {
imageName, err = createImage.GetFQName()
}
if err != nil {
return err
}

View File

@ -127,6 +127,7 @@ type Image struct {
Transport string
beenDecomposed bool
PullName string
LocalName string
}
// NewImage creates a new image object based on its name
@ -139,9 +140,21 @@ func (r *Runtime) NewImage(name string) Image {
// GetImageID returns the image ID of the image
func (k *Image) GetImageID() (string, error) {
// If the ID field is already populated, then
// return it.
if k.ID != "" {
return k.ID, nil
}
// If we have the name of the image locally, then
// get the image and returns its ID
if k.LocalName != "" {
img, err := k.runtime.GetImage(k.LocalName)
if err == nil {
return img.ID, nil
}
}
// If neither the ID is known and no local name
// is know, we search it out.
image, _ := k.GetFQName()
img, err := k.runtime.GetImage(image)
if err != nil {
@ -270,26 +283,73 @@ func (k *Image) Decompose() error {
return nil
}
// HasImageLocal returns a bool true if the image is already pulled
func (k *Image) HasImageLocal() bool {
func getTags(nameInput string) (reference.NamedTagged, bool, error) {
inputRef, err := reference.Parse(nameInput)
if err != nil {
return nil, false, errors.Wrapf(err, "unable to obtain tag from input name")
}
tagged, isTagged := inputRef.(reference.NamedTagged)
return tagged, isTagged, nil
}
// GetLocalImageName returns the name of the image if it is local.
// It will return an empty string and error if not found.
func (k *Image) GetLocalImageName() (string, error) {
_, err := k.runtime.GetImage(k.Name)
if err == nil {
return true
if err != nil {
return "", errors.Wrapf(err, "unable to obtain local image")
}
localImages, err := k.runtime.GetImages(&ImageFilterParams{})
if err != nil {
return "", errors.Wrapf(err, "unable to obtain local image")
}
_, isTagged, err := getTags(k.Name)
if err != nil {
return "", err
}
for _, image := range localImages {
for _, name := range image.Names {
imgRef, err := reference.Parse(name)
if err != nil {
continue
}
var imageName string
imageNameOnly := reference.Path(imgRef.(reference.Named))
if isTagged {
imageNameTag, _, err := getTags(name)
if err != nil {
continue
}
imageName = fmt.Sprintf("%s:%s", imageNameOnly, imageNameTag.Tag())
} else {
imageName = imageNameOnly
}
if imageName == k.Name {
return name, nil
}
imageSplit := strings.Split(imageName, "/")
baseName := imageSplit[len(imageSplit)-1]
if baseName == k.Name {
return name, nil
}
}
}
fqname, _ := k.GetFQName()
_, err = k.runtime.GetImage(fqname)
if err == nil {
return true
}
return false
return fqname, nil
}
// HasLatest determines if we have the latest image local
func (k *Image) HasLatest() (bool, error) {
if !k.HasImageLocal() {
localName, err := k.GetLocalImageName()
if err != nil {
return false, err
}
if localName == "" {
return false, nil
}
fqname, err := k.GetFQName()
if err != nil {
return false, err

View File

@ -1,8 +1,10 @@
package libpod
import (
"fmt"
"os"
"path/filepath"
"time"
)
// WriteFile writes a provided string to a provided path
@ -32,3 +34,11 @@ func StringInSlice(s string, sl []string) bool {
}
return false
}
// FuncTimer helps measure the execution time of a function
// For debug purposes, do not leave in code
// used like defer FuncTimer("foo")
func FuncTimer(funcName string) {
elapsed := time.Since(time.Now())
fmt.Printf("%s executed in %d ms\n", funcName, elapsed)
}