github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/pkg/imageengine/buildah/load.go (about) 1 // Copyright © 2022 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 buildah 16 17 import ( 18 "context" 19 "fmt" 20 "io/fs" 21 "io/ioutil" 22 "os" 23 "path/filepath" 24 "strings" 25 26 "github.com/containers/common/libimage" 27 "github.com/go-errors/errors" 28 "github.com/sealerio/sealer/common" 29 "github.com/sealerio/sealer/pkg/define/options" 30 "github.com/sealerio/sealer/utils/archive" 31 "github.com/sirupsen/logrus" 32 ) 33 34 var LoadError = errors.Errorf("failed to load new image") 35 36 func (engine *Engine) Load(opts *options.LoadOptions) error { 37 imageSrc := opts.Input 38 if _, err := os.Stat(imageSrc); err != nil { 39 return err 40 } 41 42 loadOpts := &libimage.LoadOptions{} 43 if !opts.Quiet { 44 loadOpts.Writer = os.Stderr 45 } 46 47 srcFile, err := os.Open(filepath.Clean(imageSrc)) 48 if err != nil { 49 return fmt.Errorf("failed to open %s, err : %v", imageSrc, err) 50 } 51 52 defer func() { 53 if err := srcFile.Close(); err != nil { 54 logrus.Errorf("failed to close file: %v", err) 55 } 56 }() 57 58 tempDir, err := os.MkdirTemp(opts.TmpDir, "sealer-load-tmp") 59 if err != nil { 60 return fmt.Errorf("failed to create %s, err: %v", tempDir, err) 61 } 62 63 defer func() { 64 err = os.RemoveAll(tempDir) 65 if err != nil { 66 logrus.Errorf("failed to delete %s: %v", tempDir, err) 67 } 68 }() 69 70 // decompress tar file 71 if _, err = archive.Decompress(srcFile, tempDir, archive.Options{Compress: false}); err != nil { 72 return err 73 } 74 75 metaFile := filepath.Join(tempDir, common.DefaultMetadataName) 76 if _, err := os.Stat(metaFile); err != nil { 77 //assume it is single image to load 78 return engine.loadOneImage(imageSrc, loadOpts) 79 } 80 81 // get manifestName 82 metaBytes, err := ioutil.ReadFile(filepath.Clean(metaFile)) 83 if err != nil { 84 return err 85 } 86 87 manifestName := string(metaBytes) 88 // delete it if manifestName is already used 89 _, err = engine.ImageRuntime().LookupManifestList(manifestName) 90 if err == nil { 91 logrus.Warnf("%s is already in use, will delete it", manifestName) 92 delErr := engine.DeleteManifests([]string{manifestName}, &options.ManifestDeleteOpts{}) 93 if delErr != nil { 94 return fmt.Errorf("%s is already in use: %v", manifestName, delErr) 95 } 96 } 97 98 // walk through temp dir to load each instance 99 var instancesIDs []string 100 err = filepath.Walk(tempDir, func(path string, f fs.FileInfo, err error) error { 101 if err != nil { 102 return err 103 } 104 105 if !strings.HasSuffix(f.Name(), ".tar") { 106 return nil 107 } 108 109 instanceSrc := filepath.Join(tempDir, f.Name()) 110 err = engine.loadOneImage(instanceSrc, loadOpts) 111 if err != nil { 112 return fmt.Errorf("failed to load %s from %s: %v", f.Name(), imageSrc, err) 113 } 114 115 instancesIDs = append(instancesIDs, strings.TrimSuffix(f.Name(), ".tar")) 116 return nil 117 }) 118 119 if err != nil { 120 return fmt.Errorf("failed to load image instance %v", err) 121 } 122 123 // create a new manifest and add instance to it. 124 _, err = engine.CreateManifest(manifestName, &options.ManifestCreateOpts{}) 125 if err != nil { 126 return fmt.Errorf("failed to create new manifest %s :%v ", manifestName, err) 127 } 128 129 err = engine.AddToManifest(manifestName, instancesIDs, &options.ManifestAddOpts{}) 130 if err != nil { 131 return fmt.Errorf("failed to add new image to %s :%v ", manifestName, err) 132 } 133 134 return nil 135 } 136 137 func (engine *Engine) loadOneImage(imageSrc string, loadOpts *libimage.LoadOptions) error { 138 loadedImages, err := engine.ImageRuntime().Load(context.Background(), imageSrc, loadOpts) 139 if err != nil { 140 return err 141 } 142 143 logrus.Infof("Loaded image: " + strings.Join(loadedImages, "\nLoaded image: ")) 144 return nil 145 }