Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only get images list once for caching #1758

Merged
merged 3 commits into from
Mar 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions docs/content/en/schemas/v1beta6.json
Original file line number Diff line number Diff line change
Expand Up @@ -1424,17 +1424,6 @@
"x-intellij-html-description": "<em>beta</em> describes how to do a build on the local docker daemon and optionally push to a repository."
},
"LocalDir": {
"properties": {
"initImage": {
"type": "string",
"description": "image used to run init container which mounts kaniko context.",
"x-intellij-html-description": "image used to run init container which mounts kaniko context."
}
},
"preferredOrder": [
"initImage"
],
"additionalProperties": false,
"description": "configures how Kaniko mounts sources directly via an `emptyDir` volume.",
"x-intellij-html-description": "configures how Kaniko mounts sources directly via an <code>emptyDir</code> volume."
},
Expand Down
11 changes: 11 additions & 0 deletions docs/content/en/schemas/v1beta7.json
Original file line number Diff line number Diff line change
Expand Up @@ -1424,6 +1424,17 @@
"x-intellij-html-description": "<em>beta</em> describes how to do a build on the local docker daemon and optionally push to a repository."
},
"LocalDir": {
"properties": {
"initImage": {
"type": "string",
"description": "image used to run init container which mounts kaniko context.",
"x-intellij-html-description": "image used to run init container which mounts kaniko context."
}
},
"preferredOrder": [
"initImage"
],
"additionalProperties": false,
"description": "configures how Kaniko mounts sources directly via an `emptyDir` volume.",
"x-intellij-html-description": "configures how Kaniko mounts sources directly via an <code>emptyDir</code> volume."
},
Expand Down
51 changes: 38 additions & 13 deletions pkg/skaffold/build/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"time"

skafconfig "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config"
"github.com/docker/docker/api/types"

"github.com/GoogleContainerTools/skaffold/cmd/skaffold/app/cmd/config"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/color"
Expand Down Expand Up @@ -64,6 +65,7 @@ type Cache struct {
artifactCache ArtifactCache
client docker.LocalDaemon
builder Builder
imageList []types.ImageSummary
cacheFile string
useCache bool
needsPush bool
Expand All @@ -74,11 +76,12 @@ var (
hashForArtifact = getHashForArtifact
localCluster = config.GetLocalCluster
remoteDigest = docker.RemoteDigest
newDockerCilent = docker.NewAPIClient
noCache = &Cache{}
)

// NewCache returns the current state of the cache
func NewCache(builder Builder, opts *skafconfig.SkaffoldOptions, needsPush bool) *Cache {
func NewCache(ctx context.Context, builder Builder, opts *skafconfig.SkaffoldOptions, needsPush bool) *Cache {
if !opts.CacheArtifacts {
return noCache
}
Expand All @@ -92,18 +95,23 @@ func NewCache(builder Builder, opts *skafconfig.SkaffoldOptions, needsPush bool)
logrus.Warnf("Error retrieving artifact cache, not using skaffold cache: %v", err)
return noCache
}
client, err := docker.NewAPIClient()
client, err := newDockerCilent()
if err != nil {
logrus.Warnf("Error retrieving local daemon client, not using skaffold cache: %v", err)
return noCache
}
imageList, err := client.ImageList(ctx, types.ImageListOptions{})
if err != nil {
logrus.Warn("Unable to get list of images from local docker daemon, won't be checked for cache.")
}
return &Cache{
artifactCache: cache,
cacheFile: cf,
useCache: opts.CacheArtifacts,
client: client,
builder: builder,
needsPush: needsPush,
imageList: imageList,
}
}

Expand Down Expand Up @@ -171,7 +179,7 @@ func (c *Cache) resolveCachedArtifact(ctx context.Context, out io.Writer, a *lat
color.Default.Fprintf(out, " - %s: ", a.ImageName)

if details.needsRebuild {
color.Red.Fprintln(out, "Not found. Rebuilding")
color.Red.Fprintln(out, "Not found. Rebuilding.")
return nil, nil
}

Expand All @@ -180,7 +188,7 @@ func (c *Cache) resolveCachedArtifact(ctx context.Context, out io.Writer, a *lat
color.Green.Fprint(out, ". Retagging")
}
if details.needsPush {
color.Green.Fprint(out, ". Pushing")
color.Green.Fprint(out, ". Pushing.")
}
color.Default.Fprintln(out)

Expand Down Expand Up @@ -239,7 +247,7 @@ func (c *Cache) retrieveCachedArtifactDetails(ctx context.Context, a *latest.Art
}, nil
}
// Check for a local image with the same digest as the image we want to build
prebuiltImage, err := c.retrievePrebuiltImage(ctx, imageDetails)
prebuiltImage, err := c.retrievePrebuiltImage(imageDetails)
if err != nil {
return nil, errors.Wrapf(err, "getting prebuilt image")
}
Expand All @@ -255,15 +263,32 @@ func (c *Cache) retrieveCachedArtifactDetails(ctx context.Context, a *latest.Art
}, nil
}

func (c *Cache) retrievePrebuiltImage(ctx context.Context, details ImageDetails) (string, error) {
img, err := c.client.FindTaggedImage(ctx, details.ID, details.Digest)
if err != nil {
return "", errors.Wrap(err, "unable to find tagged image")
}
if img == "" {
return img, errors.New("no prebuilt image")
func (c *Cache) retrievePrebuiltImage(details ImageDetails) (string, error) {
for _, r := range c.imageList {
if r.ID == details.ID && details.ID != "" {
if len(r.RepoTags) == 0 {
return "", nil
}
return r.RepoTags[0], nil
}
if details.Digest == "" {
continue
}
for _, d := range r.RepoDigests {
if getDigest(d) == details.Digest {
// Return a tagged version of this image, since we can't retag an image in the image@sha256: format
if len(r.RepoTags) > 0 {
return r.RepoTags[0], nil
}
}
}
}
return img, nil
return "", errors.New("no prebuilt image")
}

func getDigest(img string) string {
ref, _ := name.NewDigest(img, name.WeakValidation)
return ref.DigestStr()
}

func imageExistsRemotely(image, digest string) bool {
Expand Down
Loading