2015-11-18 17:15:00 -05:00
package layer
2016-02-09 14:38:37 -05:00
import (
"fmt"
"io"
2016-05-25 22:11:51 -04:00
"github.com/docker/distribution"
2017-01-06 20:23:18 -05:00
"github.com/opencontainers/go-digest"
2016-02-09 14:38:37 -05:00
)
2015-11-18 17:15:00 -05:00
type roLayer struct {
chainID ChainID
diffID DiffID
parent * roLayer
cacheID string
size int64
layerStore * layerStore
2016-06-06 20:49:34 -04:00
descriptor distribution . Descriptor
2017-08-08 15:43:48 -04:00
os OS
2015-11-18 17:15:00 -05:00
referenceCount int
references map [ Layer ] struct { }
}
2016-11-28 12:21:47 -05:00
// TarStream for roLayer guarantees that the data that is produced is the exact
2016-04-21 12:08:37 -04:00
// data that the layer was registered with.
2015-11-25 19:39:54 -05:00
func ( rl * roLayer ) TarStream ( ) ( io . ReadCloser , error ) {
2017-03-20 14:38:17 -04:00
rc , err := rl . layerStore . getTarStream ( rl )
2015-11-18 17:15:00 -05:00
if err != nil {
return nil , err
}
2017-03-20 14:38:17 -04:00
vrc , err := newVerifiedReadCloser ( rc , digest . Digest ( rl . diffID ) )
2016-02-09 14:38:37 -05:00
if err != nil {
return nil , err
}
2017-03-20 14:38:17 -04:00
return vrc , nil
2015-11-18 17:15:00 -05:00
}
2016-11-28 12:21:47 -05:00
// TarStreamFrom does not make any guarantees to the correctness of the produced
2016-04-21 12:08:37 -04:00
// data. As such it should not be used when the layer content must be verified
// to be an exact match to the registered layer.
func ( rl * roLayer ) TarStreamFrom ( parent ChainID ) ( io . ReadCloser , error ) {
var parentCacheID string
for pl := rl . parent ; pl != nil ; pl = pl . parent {
if pl . chainID == parent {
parentCacheID = pl . cacheID
break
}
}
if parent != ChainID ( "" ) && parentCacheID == "" {
return nil , fmt . Errorf ( "layer ID '%s' is not a parent of the specified layer: cannot provide diff to non-parent" , parent )
}
return rl . layerStore . driver . Diff ( rl . cacheID , parentCacheID )
}
2015-11-18 17:15:00 -05:00
func ( rl * roLayer ) ChainID ( ) ChainID {
return rl . chainID
}
func ( rl * roLayer ) DiffID ( ) DiffID {
return rl . diffID
}
func ( rl * roLayer ) Parent ( ) Layer {
if rl . parent == nil {
return nil
}
return rl . parent
}
func ( rl * roLayer ) Size ( ) ( size int64 , err error ) {
if rl . parent != nil {
size , err = rl . parent . Size ( )
if err != nil {
return
}
}
return size + rl . size , nil
}
func ( rl * roLayer ) DiffSize ( ) ( size int64 , err error ) {
return rl . size , nil
}
func ( rl * roLayer ) Metadata ( ) ( map [ string ] string , error ) {
return rl . layerStore . driver . GetMetadata ( rl . cacheID )
}
type referencedCacheLayer struct {
* roLayer
}
func ( rl * roLayer ) getReference ( ) Layer {
ref := & referencedCacheLayer {
roLayer : rl ,
}
rl . references [ ref ] = struct { } { }
return ref
}
func ( rl * roLayer ) hasReference ( ref Layer ) bool {
_ , ok := rl . references [ ref ]
return ok
}
func ( rl * roLayer ) hasReferences ( ) bool {
return len ( rl . references ) > 0
}
func ( rl * roLayer ) deleteReference ( ref Layer ) {
delete ( rl . references , ref )
}
func ( rl * roLayer ) depth ( ) int {
if rl . parent == nil {
return 1
}
return rl . parent . depth ( ) + 1
}
func storeLayer ( tx MetadataTransaction , layer * roLayer ) error {
if err := tx . SetDiffID ( layer . diffID ) ; err != nil {
return err
}
if err := tx . SetSize ( layer . size ) ; err != nil {
return err
}
if err := tx . SetCacheID ( layer . cacheID ) ; err != nil {
return err
}
2016-06-06 20:49:34 -04:00
// Do not store empty descriptors
if layer . descriptor . Digest != "" {
if err := tx . SetDescriptor ( layer . descriptor ) ; err != nil {
2015-11-18 17:15:00 -05:00
return err
}
}
2016-06-06 20:49:34 -04:00
if layer . parent != nil {
if err := tx . SetParent ( layer . parent . chainID ) ; err != nil {
2016-05-25 22:11:51 -04:00
return err
}
}
2017-08-08 15:43:48 -04:00
if err := tx . SetOS ( layer . os ) ; err != nil {
2017-04-25 12:37:29 -04:00
return err
}
2015-11-18 17:15:00 -05:00
return nil
}
2016-02-09 14:38:37 -05:00
func newVerifiedReadCloser ( rc io . ReadCloser , dgst digest . Digest ) ( io . ReadCloser , error ) {
return & verifiedReadCloser {
rc : rc ,
dgst : dgst ,
2017-01-06 20:23:18 -05:00
verifier : dgst . Verifier ( ) ,
2016-02-09 14:38:37 -05:00
} , nil
}
type verifiedReadCloser struct {
rc io . ReadCloser
dgst digest . Digest
verifier digest . Verifier
}
func ( vrc * verifiedReadCloser ) Read ( p [ ] byte ) ( n int , err error ) {
n , err = vrc . rc . Read ( p )
if n > 0 {
if n , err := vrc . verifier . Write ( p [ : n ] ) ; err != nil {
return n , err
}
}
if err == io . EOF {
if ! vrc . verifier . Verified ( ) {
err = fmt . Errorf ( "could not verify layer data for: %s. This may be because internal files in the layer store were modified. Re-pulling or rebuilding this image may resolve the issue" , vrc . dgst )
}
}
return
}
func ( vrc * verifiedReadCloser ) Close ( ) error {
return vrc . rc . Close ( )
}