github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/pkg/imageengine/buildah/commit.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 "os" 19 "time" 20 21 "github.com/containers/buildah" 22 "github.com/containers/buildah/define" 23 "github.com/containers/buildah/util" 24 "github.com/containers/image/v5/pkg/shortnames" 25 storageTransport "github.com/containers/image/v5/storage" 26 "github.com/containers/image/v5/transports/alltransports" 27 "github.com/containers/image/v5/types" 28 "github.com/containers/storage" 29 "github.com/pkg/errors" 30 "github.com/sirupsen/logrus" 31 32 "github.com/sealerio/sealer/pkg/define/options" 33 ) 34 35 func (engine *Engine) Commit(opts *options.CommitOptions) (string, error) { 36 var dest types.ImageReference 37 if len(opts.ContainerID) == 0 { 38 return "", errors.Errorf("container ID must be specified") 39 } 40 if len(opts.Image) == 0 && len(opts.Manifest) == 0 { 41 return "", errors.Errorf("image name should be specified") 42 } 43 44 name := opts.ContainerID 45 image := opts.Image 46 manifest := opts.Manifest 47 compress := define.Gzip 48 if opts.DisableCompression { 49 compress = define.Uncompressed 50 } 51 52 format, err := getImageType(opts.Format) 53 if err != nil { 54 return "", err 55 } 56 57 ctx := getContext() 58 store := engine.ImageStore() 59 builder, err := OpenBuilder(ctx, store, name) 60 if err != nil { 61 return "", errors.Wrapf(err, "error reading build container %q", name) 62 } 63 64 systemCxt := engine.SystemContext() 65 66 // If the user specified an image, we may need to massage it a bit if 67 // no transport is specified. 68 // TODO we support commit to local image only, we'd better limit the input of name 69 if image != "" { 70 dest, err = getImageReference(image, store, systemCxt) 71 if err != nil { 72 return "", err 73 } 74 } 75 76 options := buildah.CommitOptions{ 77 PreferredManifestType: format, 78 Manifest: manifest, 79 Compression: compress, 80 SystemContext: systemCxt, 81 Squash: opts.Squash, 82 } 83 if opts.Timestamp != 0 { 84 timestamp := time.Unix(opts.Timestamp, 0).UTC() 85 options.HistoryTimestamp = ×tamp 86 } 87 88 if !opts.Quiet { 89 options.ReportWriter = os.Stderr 90 } 91 id, ref, _, err := builder.Commit(ctx, dest, options) 92 if err != nil { 93 return "", util.GetFailureCause(err, errors.Wrapf(err, "error committing container %q to %q", builder.Container, image)) 94 } 95 if ref != nil && id != "" { 96 logrus.Debugf("wrote image %s with ID %s", ref, id) 97 } else if ref != nil { 98 logrus.Debugf("wrote image %s", ref) 99 } else if id != "" { 100 logrus.Debugf("wrote image with ID %s", id) 101 } else { 102 logrus.Debugf("wrote image") 103 } 104 105 if opts.Rm { 106 return id, builder.Delete() 107 } 108 return id, nil 109 } 110 111 func getImageReference(image string, store storage.Store, systemCxt *types.SystemContext) (types.ImageReference, error) { 112 dest, err := alltransports.ParseImageName(image) 113 if err == nil { 114 return dest, nil 115 } 116 117 candidates, err := shortnames.ResolveLocally(systemCxt, image) 118 if err != nil { 119 return nil, err 120 } 121 if len(candidates) == 0 { 122 return nil, errors.Errorf("no candidate tags for target image name %q", image) 123 } 124 dest, err = storageTransport.Transport.ParseStoreReference(store, candidates[0].String()) 125 if err != nil { 126 return nil, errors.Wrapf(err, "error parsing target image name %q", image) 127 } 128 129 return dest, nil 130 }