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

Allow for multiple tags #140

Merged
merged 1 commit into from
Jul 2, 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
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Go parameters
GOCMD=go
GOCMD?=go
GOENV=GO111MODULE=on GOOS=linux GOARCH=amd64 CGO_ENABLED=0
GOBUILD=$(GOCMD) build -mod=vendor
GOTEST=$(GOCMD) test -mod=vendor
Expand All @@ -17,13 +17,17 @@ build:
$(GOENV) $(GOBUILD) -o ./out/$(ARCHIVE_NAME)/cacher -a ./cmd/cacher
$(GOENV) $(GOBUILD) -o ./out/$(ARCHIVE_NAME)/launcher -a ./cmd/launcher

imports:
$(GOCMD) install -mod=vendor golang.org/x/tools/cmd/goimports
test -z $$(goimports -l -w -local github.com/buildpack/lifecycle $$(find . -type f -name '*.go' -not -path "./vendor/*"))

format:
test -z $$($(GOCMD) fmt ./...)

vet:
$(GOCMD) vet $$($(GOCMD) list ./... | grep -v /testdata/)

test: format vet
test: format imports vet
$(GOTEST) -v ./...

clean:
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ A reference implementation of [Buildpack API v3](https://github.com/buildpack/sp

### Cache

* `retriever` - restores cache
* `restorer` - restores cache
* `cacher` - updates cache

## Notes

Cache implementations (`retriever` and `cacher`) are intended to be interchangable and platform-specific.
Cache implementations (`restorer` and `cacher`) are intended to be interchangeable and platform-specific.
A platform may choose not to deduplicate cache layers.

## Development
Expand Down
131 changes: 79 additions & 52 deletions analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,74 +11,101 @@ import (
)

type Analyzer struct {
Buildpacks []*Buildpack
AppDir string
LayersDir string
In []byte
Out, Err *log.Logger
UID int
GID int
AnalyzedPath string
AppDir string
Buildpacks []*Buildpack
GID, UID int
LayersDir string
Out, Err *log.Logger
SkipLayers bool
}

func (a *Analyzer) Analyze(image imgutil.Image) error {
func (a *Analyzer) Analyze(image imgutil.Image) (metadata.AnalyzedMetadata, error) {
imageID, err := a.getImageIdentifier(image)
if err != nil {
return metadata.AnalyzedMetadata{}, errors.Wrap(err, "retrieve image identifier")
}

data, err := metadata.GetAppMetadata(image)
if err != nil {
return err
return metadata.AnalyzedMetadata{}, err
}
for _, buildpack := range a.Buildpacks {
cache, err := readBuildpackLayersDir(a.LayersDir, *buildpack)
if err != nil {
return err
}

metadataLayers := data.MetadataForBuildpack(buildpack.ID).Layers
for _, cachedLayer := range cache.layers {
cacheType := cachedLayer.classifyCache(metadataLayers)
switch cacheType {
case cacheStaleNoMetadata:
a.Out.Printf("removing stale cached launch layer '%s', not in metadata \n", cachedLayer.Identifier())
if err := cachedLayer.remove(); err != nil {
return err
}
case cacheStaleWrongSHA:
a.Out.Printf("removing stale cached launch layer '%s'", cachedLayer.Identifier())
if err := cachedLayer.remove(); err != nil {
return err
}
case cacheMalformed:
a.Out.Printf("removing malformed cached layer '%s'", cachedLayer.Identifier())
if err := cachedLayer.remove(); err != nil {
return err
}
case cacheNotForLaunch:
a.Out.Printf("using cached layer '%s'", cachedLayer.Identifier())
case cacheValid:
a.Out.Printf("using cached launch layer '%s'", cachedLayer.Identifier())
a.Out.Printf("rewriting metadata for layer '%s'", cachedLayer.Identifier())
if err := cachedLayer.writeMetadata(metadataLayers); err != nil {
return err
if !a.SkipLayers {
for _, buildpack := range a.Buildpacks {
bpLayersDir, err := readBuildpackLayersDir(a.LayersDir, *buildpack)
if err != nil {
return metadata.AnalyzedMetadata{}, err
}

metadataLayers := data.MetadataForBuildpack(buildpack.ID).Layers
for _, cachedLayer := range bpLayersDir.layers {
cacheType := cachedLayer.classifyCache(metadataLayers)
switch cacheType {
case cacheStaleNoMetadata:
a.Out.Printf("Removing stale cached launch layer '%s', not in metadata \n", cachedLayer.Identifier())
if err := cachedLayer.remove(); err != nil {
return metadata.AnalyzedMetadata{}, err
}
case cacheStaleWrongSHA:
a.Out.Printf("Removing stale cached launch layer '%s'", cachedLayer.Identifier())
if err := cachedLayer.remove(); err != nil {
return metadata.AnalyzedMetadata{}, err
}
case cacheMalformed:
a.Out.Printf("Removing malformed cached layer '%s'", cachedLayer.Identifier())
if err := cachedLayer.remove(); err != nil {
return metadata.AnalyzedMetadata{}, err
}
case cacheNotForLaunch:
a.Out.Printf("Using cached layer '%s'", cachedLayer.Identifier())
case cacheValid:
a.Out.Printf("Using cached launch layer '%s'", cachedLayer.Identifier())
a.Out.Printf("Rewriting metadata for layer '%s'", cachedLayer.Identifier())
if err := cachedLayer.writeMetadata(metadataLayers); err != nil {
return metadata.AnalyzedMetadata{}, err
}
}
}
}

for lmd, data := range metadataLayers {
if !data.Build && !data.Cache {
layer := cache.newBPLayer(lmd)
a.Out.Printf("writing metadata for uncached layer '%s'", layer.Identifier())
if err := layer.writeMetadata(metadataLayers); err != nil {
return err
for lmd, data := range metadataLayers {
if !data.Build && !data.Cache {
layer := bpLayersDir.newBPLayer(lmd)
a.Out.Printf("Writing metadata for uncached layer '%s'", layer.Identifier())
if err := layer.writeMetadata(metadataLayers); err != nil {
return metadata.AnalyzedMetadata{}, err
}
}
}
}
} else {
a.Out.Printf("Skipping buildpack layer analysis")
}

// if analyzer is running as root it needs to fix the ownership of the layers dir
if current := os.Getuid(); err != nil {
return err
} else if current == 0 {
if current := os.Getuid(); current == 0 {
if err := recursiveChown(a.LayersDir, a.UID, a.GID); err != nil {
return errors.Wrapf(err, "chowning layers dir to '%d/%d'", a.UID, a.GID)
return metadata.AnalyzedMetadata{}, errors.Wrapf(err, "chowning layers dir to '%d/%d'", a.UID, a.GID)
}
}
return nil

return metadata.AnalyzedMetadata{
Image: imageID,
Metadata: data,
}, nil
}

func (a *Analyzer) getImageIdentifier(image imgutil.Image) (*metadata.ImageIdentifier, error) {
if !image.Found() {
a.Out.Printf("Image '%s' not found", image.Name())
return nil, nil
}
identifier, err := image.Identifier()
if err != nil {
return nil, err
}
a.Out.Printf("Analyzing image '%s'", identifier.String())
return &metadata.ImageIdentifier{
Reference: identifier.String(),
}, nil
}
Loading