Skip to content

Commit

Permalink
Merge pull request #140 from buildpack/feature/138-multiple-tags
Browse files Browse the repository at this point in the history
Allow for multiple tags
  • Loading branch information
ekcasey authored Jul 2, 2019
2 parents af8b715 + f49a44e commit a927d83
Show file tree
Hide file tree
Showing 92 changed files with 25,912 additions and 1,631 deletions.
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

0 comments on commit a927d83

Please sign in to comment.