github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/pkg/image/store/layer.go (about) 1 // Copyright © 2021 Alibaba Group Holding Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package store 16 17 import ( 18 "fmt" 19 "io" 20 "os" 21 "path/filepath" 22 23 "github.com/docker/distribution/manifest/schema2" 24 "github.com/opencontainers/go-digest" 25 26 "github.com/alibaba/sealer/logger" 27 "github.com/alibaba/sealer/utils/archive" 28 ) 29 30 type LayerID digest.Digest 31 32 func (li LayerID) String() string { 33 return string(li) 34 } 35 36 func (li LayerID) ToDigest() digest.Digest { 37 return digest.Digest(li) 38 } 39 40 func (li LayerID) Validate() error { 41 return li.ToDigest().Validate() 42 } 43 44 type ROLayer struct { 45 id LayerID 46 size int64 47 distributionMetadata map[string]digest.Digest 48 } 49 50 func (rl *ROLayer) ID() LayerID { 51 return rl.id 52 } 53 54 func (rl *ROLayer) SimpleID() string { 55 return rl.ID().ToDigest().Hex()[0:12] 56 } 57 58 func (rl *ROLayer) TarStream() (io.ReadCloser, error) { 59 layerBackend, err := NewFSStoreBackend() 60 if err != nil { 61 return nil, err 62 } 63 64 var ( 65 tarDataPath = filepath.Join(layerBackend.LayerDBDir(rl.ID().ToDigest()), tarDataGZ) 66 layerDataPath = layerBackend.LayerDataDir(rl.ID().ToDigest()) 67 ) 68 _, err = os.Stat(tarDataPath) 69 // tar-data.json.gz does not exist 70 // at the pull stage, the file won't exist 71 // so we tar the layer dir. 72 if err != nil { 73 logger.Debug("failed to find %s for layer %s, use tar, err: %s", tarDataGZ, rl.ID(), err) 74 tarReader, tarErr := archive.TarWithoutRootDir(layerDataPath) 75 if tarErr != nil { 76 return nil, fmt.Errorf("failed to tar layer %s, err: %s", rl.ID(), tarErr) 77 } 78 return tarReader, nil 79 } 80 81 pr, pw := io.Pipe() 82 go func() { 83 err := layerBackend.assembleTar(rl.ID(), pw) 84 if err != nil { 85 _ = pw.CloseWithError(err) 86 } else { 87 _ = pw.Close() 88 } 89 }() 90 91 return pr, nil 92 } 93 94 func (rl *ROLayer) Size() int64 { 95 return rl.size 96 } 97 98 func (rl *ROLayer) SetSize(size int64) { 99 rl.size = size 100 } 101 102 func (rl *ROLayer) MediaType() string { 103 return schema2.MediaTypeLayer 104 } 105 106 func (rl *ROLayer) DistributionMetadata() map[string]digest.Digest { 107 return rl.distributionMetadata 108 } 109 110 func NewROLayer(layerDigest digest.Digest, size int64, distributionMetadata map[string]digest.Digest) (*ROLayer, error) { 111 if err := layerDigest.Validate(); err != nil { 112 return nil, err 113 } 114 if distributionMetadata == nil { 115 distributionMetadata = map[string]digest.Digest{} 116 } 117 return &ROLayer{ 118 id: LayerID(layerDigest), 119 size: size, 120 distributionMetadata: distributionMetadata, 121 }, nil 122 }