133 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
| //go:build !remote
 | |
| 
 | |
| package libimage
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"net/url"
 | |
| 	"os"
 | |
| 
 | |
| 	"github.com/containers/common/pkg/download"
 | |
| 	storageTransport "github.com/containers/image/v5/storage"
 | |
| 	tarballTransport "github.com/containers/image/v5/tarball"
 | |
| 	v1 "github.com/opencontainers/image-spec/specs-go/v1"
 | |
| 	"github.com/sirupsen/logrus"
 | |
| )
 | |
| 
 | |
| // ImportOptions allow for customizing image imports.
 | |
| type ImportOptions struct {
 | |
| 	CopyOptions
 | |
| 
 | |
| 	// Apply the specified changes to the created image. Please refer to
 | |
| 	// `ImageConfigFromChanges` for supported change instructions.
 | |
| 	Changes []string
 | |
| 	// Set the commit message as a comment to created image's history.
 | |
| 	CommitMessage string
 | |
| 	// Tag the imported image with this value.
 | |
| 	Tag string
 | |
| 	// Overwrite OS of imported image.
 | |
| 	OS string
 | |
| 	// Overwrite Arch of imported image.
 | |
| 	Arch string
 | |
| }
 | |
| 
 | |
| // Import imports a custom tarball at the specified path.  Returns the name of
 | |
| // the imported image.
 | |
| func (r *Runtime) Import(ctx context.Context, path string, options *ImportOptions) (string, error) {
 | |
| 	logrus.Debugf("Importing image from %q", path)
 | |
| 
 | |
| 	if options == nil {
 | |
| 		options = &ImportOptions{}
 | |
| 	}
 | |
| 
 | |
| 	ic := v1.ImageConfig{}
 | |
| 	if len(options.Changes) > 0 {
 | |
| 		config, err := ImageConfigFromChanges(options.Changes)
 | |
| 		if err != nil {
 | |
| 			return "", err
 | |
| 		}
 | |
| 		ic = config.ImageConfig
 | |
| 	}
 | |
| 
 | |
| 	history := []v1.History{
 | |
| 		{Comment: options.CommitMessage},
 | |
| 	}
 | |
| 
 | |
| 	config := v1.Image{
 | |
| 		Config:  ic,
 | |
| 		History: history,
 | |
| 		Platform: v1.Platform{
 | |
| 			OS:           options.OS,
 | |
| 			Architecture: options.Arch,
 | |
| 			Variant:      options.Variant,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	u, err := url.ParseRequestURI(path)
 | |
| 	if err == nil && u.Scheme != "" {
 | |
| 		// If source is a URL, download the file.
 | |
| 		fmt.Printf("Downloading from %q\n", path) //nolint:forbidigo
 | |
| 		file, err := download.FromURL(r.systemContext.BigFilesTemporaryDir, path)
 | |
| 		if err != nil {
 | |
| 			return "", err
 | |
| 		}
 | |
| 		defer os.Remove(file)
 | |
| 		path = file
 | |
| 	} else if path == "-" {
 | |
| 		// "-" special cases stdin
 | |
| 		path = os.Stdin.Name()
 | |
| 	}
 | |
| 
 | |
| 	srcRef, err := tarballTransport.Transport.ParseReference(path)
 | |
| 	if err != nil {
 | |
| 		return "", err
 | |
| 	}
 | |
| 
 | |
| 	updater, ok := srcRef.(tarballTransport.ConfigUpdater)
 | |
| 	if !ok {
 | |
| 		return "", errors.New("unexpected type, a tarball reference should implement tarball.ConfigUpdater")
 | |
| 	}
 | |
| 	annotations := make(map[string]string)
 | |
| 	if err := updater.ConfigUpdate(config, annotations); err != nil {
 | |
| 		return "", err
 | |
| 	}
 | |
| 
 | |
| 	id, err := getImageID(ctx, srcRef, r.systemContextCopy())
 | |
| 	if err != nil {
 | |
| 		return "", err
 | |
| 	}
 | |
| 
 | |
| 	destRef, err := storageTransport.Transport.ParseStoreReference(r.store, id)
 | |
| 	if err != nil {
 | |
| 		return "", err
 | |
| 	}
 | |
| 
 | |
| 	c, err := r.newCopier(&options.CopyOptions)
 | |
| 	if err != nil {
 | |
| 		return "", err
 | |
| 	}
 | |
| 	defer c.Close()
 | |
| 
 | |
| 	if _, err := c.Copy(ctx, srcRef, destRef); err != nil {
 | |
| 		return "", err
 | |
| 	}
 | |
| 
 | |
| 	// Strip the leading @ off the id.
 | |
| 	name := id[1:]
 | |
| 
 | |
| 	// If requested, tag the imported image.
 | |
| 	if options.Tag != "" {
 | |
| 		image, _, err := r.LookupImage(name, nil)
 | |
| 		if err != nil {
 | |
| 			return "", fmt.Errorf("looking up imported image: %w", err)
 | |
| 		}
 | |
| 		if err := image.Tag(options.Tag); err != nil {
 | |
| 			return "", err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return "sha256:" + name, nil
 | |
| }
 |