github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/build/buildimage/differ.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 buildimage 16 17 import ( 18 "context" 19 "fmt" 20 "io/fs" 21 "path/filepath" 22 "strings" 23 24 v1 "github.com/alibaba/sealer/types/api/v1" 25 26 "github.com/alibaba/sealer/build/layerutils/charts" 27 manifest "github.com/alibaba/sealer/build/layerutils/manifests" 28 "github.com/alibaba/sealer/common" 29 "github.com/alibaba/sealer/pkg/image/save" 30 "github.com/alibaba/sealer/pkg/runtime" 31 "github.com/alibaba/sealer/utils" 32 "golang.org/x/sync/errgroup" 33 ) 34 35 var ( 36 copyToManifests = "manifests" 37 copyToChart = "charts" 38 copyToImageList = "imageList" 39 dispatch map[string]func(srcPath string) ([]string, error) 40 ) 41 42 func init() { 43 dispatch = map[string]func(srcPath string) ([]string, error){ 44 copyToManifests: parseYamlImages, 45 copyToChart: parseChartImages, 46 copyToImageList: parseRawImageList, 47 } 48 } 49 50 type registry struct { 51 platform v1.Platform 52 puller save.ImageSave 53 } 54 55 func (r registry) Process(srcPath, rootfs string) error { 56 eg, _ := errgroup.WithContext(context.Background()) 57 58 var images []string 59 for t, p := range dispatch { 60 dispatchType := t 61 parse := p 62 eg.Go(func() error { 63 ima, err := parse(srcPath) 64 if err != nil { 65 return fmt.Errorf("failed to parse images from %s error is : %v", dispatchType, err) 66 } 67 images = append(images, ima...) 68 return nil 69 }) 70 } 71 72 if err := eg.Wait(); err != nil { 73 return err 74 } 75 76 return r.puller.SaveImages(images, filepath.Join(rootfs, common.RegistryDirName), r.platform) 77 } 78 79 func NewRegistryDiffer(platform v1.Platform) Differ { 80 ctx := context.Background() 81 return registry{ 82 platform: platform, 83 puller: save.NewImageSaver(ctx), 84 } 85 } 86 87 func parseChartImages(srcPath string) ([]string, error) { 88 chartsPath := filepath.Join(srcPath, copyToChart) 89 if !utils.IsExist(chartsPath) { 90 return nil, nil 91 } 92 93 var images []string 94 imageSearcher, err := charts.NewCharts() 95 if err != nil { 96 return nil, err 97 } 98 99 err = filepath.Walk(chartsPath, func(path string, f fs.FileInfo, err error) error { 100 if err != nil { 101 return err 102 } 103 104 if !f.IsDir() { 105 return nil 106 } 107 108 if utils.IsExist(filepath.Join(path, "Chart.yaml")) && utils.IsExist(filepath.Join(path, "values.yaml")) && 109 utils.IsExist(filepath.Join(path, "templates")) { 110 ima, err := imageSearcher.ListImages(path) 111 if err != nil { 112 return err 113 } 114 images = append(images, ima...) 115 } 116 return nil 117 }) 118 if err != nil { 119 return nil, err 120 } 121 return FormatImages(images), nil 122 } 123 124 func parseYamlImages(srcPath string) ([]string, error) { 125 manifestsPath := filepath.Join(srcPath, copyToManifests) 126 if !utils.IsExist(manifestsPath) { 127 return nil, nil 128 } 129 var images []string 130 131 imageSearcher, err := manifest.NewManifests() 132 if err != nil { 133 return nil, err 134 } 135 136 err = filepath.Walk(manifestsPath, func(path string, f fs.FileInfo, err error) error { 137 if err != nil { 138 return err 139 } 140 if f.IsDir() { 141 return nil 142 } 143 144 ext := strings.ToLower(filepath.Ext(f.Name())) 145 if ext != ".yaml" && ext != ".yml" && ext != ".tmpl" { 146 return nil 147 } 148 149 ima, err := imageSearcher.ListImages(path) 150 151 if err != nil { 152 return err 153 } 154 images = append(images, ima...) 155 return nil 156 }) 157 158 if err != nil { 159 return nil, err 160 } 161 return FormatImages(images), nil 162 } 163 164 func parseRawImageList(srcPath string) ([]string, error) { 165 imageListFilePath := filepath.Join(srcPath, copyToManifests, copyToImageList) 166 if !utils.IsExist(imageListFilePath) { 167 return nil, nil 168 } 169 170 images, err := utils.ReadLines(imageListFilePath) 171 if err != nil { 172 return nil, fmt.Errorf("failed to read file content %s:%v", imageListFilePath, err) 173 } 174 return FormatImages(images), nil 175 } 176 177 type metadata struct { 178 } 179 180 func (m metadata) Process(srcPath, rootfs string) error { 181 // check "KubeVersion" of Chart.yaml under charts dir,to overwrite the metadata. 182 kv := getKubeVersion(srcPath) 183 if kv == "" { 184 return nil 185 } 186 187 md, err := m.loadMetadata(srcPath, rootfs) 188 if err != nil { 189 return err 190 } 191 192 if md.KubeVersion == kv { 193 return nil 194 } 195 md.KubeVersion = kv 196 mf := filepath.Join(rootfs, common.DefaultMetadataName) 197 if err = utils.MarshalJSONToFile(mf, md); err != nil { 198 return fmt.Errorf("failed to set image Metadata file, err: %v", err) 199 } 200 201 return nil 202 } 203 204 func (m metadata) loadMetadata(srcPath, rootfs string) (*runtime.Metadata, error) { 205 // if Metadata file existed in srcPath, load and marshal to check the legality of it's content. 206 // if not, use rootfs Metadata. 207 smd, err := runtime.LoadMetadata(srcPath) 208 if err != nil { 209 return nil, err 210 } 211 if smd != nil { 212 return smd, nil 213 } 214 215 md, err := runtime.LoadMetadata(rootfs) 216 if err != nil { 217 return nil, err 218 } 219 220 if md != nil { 221 return md, nil 222 } 223 return nil, fmt.Errorf("failed to load rootfs Metadata") 224 } 225 226 func NewMetadataDiffer() Differ { 227 return metadata{} 228 }