github.com/mgoltzsche/ctnr@v0.7.1-alpha/image/builder/buildcache.go (about)

     1  package builder
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  
     7  	exterrors "github.com/mgoltzsche/ctnr/pkg/errors"
     8  	"github.com/mgoltzsche/ctnr/pkg/fs/source"
     9  	"github.com/mgoltzsche/ctnr/pkg/log"
    10  	digest "github.com/opencontainers/go-digest"
    11  	"github.com/pkg/errors"
    12  )
    13  
    14  type ImageBuildCache interface {
    15  	GetCachedImageId(parent *digest.Digest, uniqHistoryEntry string) (digest.Digest, error)
    16  	PutCachedImageId(parent *digest.Digest, uniqHistoryEntry string, child digest.Digest) error
    17  	HttpHeaderCache(image *digest.Digest) source.HttpHeaderCache
    18  	// TODO: add HttpEtagCache
    19  }
    20  
    21  type noOpCache string
    22  
    23  func (_ noOpCache) GetCachedImageId(parent *digest.Digest, uniqHistoryEntry string) (d digest.Digest, err error) {
    24  	err = exterrors.Typed(errCacheKeyNotExist, "image build cache is disabled")
    25  	return
    26  }
    27  
    28  func (_ noOpCache) PutCachedImageId(parent *digest.Digest, uniqHistoryEntry string, child digest.Digest) error {
    29  	return nil
    30  }
    31  
    32  func (_ noOpCache) HttpHeaderCache(image *digest.Digest) source.HttpHeaderCache {
    33  	return source.NoopHttpHeaderCache("NoopHttpHeaderCache")
    34  }
    35  
    36  func NewNoOpCache() ImageBuildCache {
    37  	return noOpCache("image build cache disabled")
    38  }
    39  
    40  type imageBuildCache struct {
    41  	dir  string
    42  	warn log.FieldLogger
    43  }
    44  
    45  func NewImageBuildCache(dir string, warn log.FieldLogger) ImageBuildCache {
    46  	return &imageBuildCache{dir, warn}
    47  }
    48  
    49  func (s *imageBuildCache) GetCachedImageId(parent *digest.Digest, uniqHistoryEntry string) (child digest.Digest, err error) {
    50  	c := s.cache(parent, uniqHistoryEntry)
    51  	cached, err := c.Get(uniqHistoryEntry)
    52  	if err == nil {
    53  		if child, err = digest.Parse(cached); err == nil {
    54  			if err = child.Validate(); err != nil {
    55  				msg := fmt.Sprintf("invalid cache value %q found in %s: %s", child, c.file, err)
    56  				s.warn.Println(msg)
    57  				err = exterrors.Typed(errCacheKeyNotExist, msg)
    58  				child = digest.Digest("")
    59  			}
    60  		}
    61  	}
    62  	return child, errors.Wrap(err, "build cache: get imageId")
    63  }
    64  
    65  func (s *imageBuildCache) PutCachedImageId(parent *digest.Digest, uniqHistoryEntry string, child digest.Digest) (err error) {
    66  	c := s.cache(parent, uniqHistoryEntry)
    67  	err = c.Put(uniqHistoryEntry, child.String())
    68  	return errors.Wrap(err, "build cache: put imageId")
    69  }
    70  
    71  func (s *imageBuildCache) cache(image *digest.Digest, uniqHistoryEntry string) CacheFile {
    72  	var file string
    73  	d := digest.SHA256.FromString(uniqHistoryEntry)
    74  	warn := s.warn
    75  	if image == nil {
    76  		file = filepath.Join(s.dir, "default", uniqHistoryEntry, d.Algorithm().String(), d.Hex())
    77  	} else {
    78  		warn = s.warn.WithField("image", image.String())
    79  		file = filepath.Join(s.dir, (*image).Algorithm().String(), (*image).Hex(), d.Algorithm().String(), d.Hex())
    80  	}
    81  	return NewCacheFile(file, warn)
    82  }
    83  
    84  func (s *imageBuildCache) HttpHeaderCache(image *digest.Digest) source.HttpHeaderCache {
    85  	var dir string
    86  	if image == nil {
    87  		dir = filepath.Join(s.dir, "default")
    88  	} else {
    89  		dir = filepath.Join(s.dir, (*image).Algorithm().String(), (*image).Hex(), "http")
    90  	}
    91  	return source.NewHttpHeaderCache(dir)
    92  }