1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
// Copyright (c) 2020, Control Command Inc. All rights reserved.
// Copyright (c) 2018-2023, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE.md file distributed with the sources of this project regarding your
// rights to use or distribute this software.
package oci
import (
"context"
"fmt"
"os"
ocitypes "github.com/containers/image/v5/types"
gccrv1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/sylabs/singularity/v4/internal/pkg/cache"
"github.com/sylabs/singularity/v4/internal/pkg/client/ocisif"
"github.com/sylabs/singularity/v4/internal/pkg/util/fs"
"github.com/sylabs/singularity/v4/pkg/syfs"
"github.com/sylabs/singularity/v4/pkg/sylog"
useragent "github.com/sylabs/singularity/v4/pkg/util/user-agent"
)
type PullOptions struct {
TmpDir string
OciAuth *ocitypes.DockerAuthConfig
DockerHost string
NoHTTPS bool
NoCleanUp bool
OciSif bool
Platform gccrv1.Platform
}
// sysCtx provides authentication and tempDir config for containers/image OCI operations
//
//nolint:unparam
func sysCtx(opts PullOptions) (*ocitypes.SystemContext, error) {
// DockerInsecureSkipTLSVerify is set only if --no-https is specified to honor
// configuration from /etc/containers/registries.conf because DockerInsecureSkipTLSVerify
// can have three possible values true/false and undefined, so we left it as undefined instead
// of forcing it to false in order to delegate decision to /etc/containers/registries.conf:
// https://github.com/sylabs/singularity/issues/5172
sysCtx := &ocitypes.SystemContext{
OCIInsecureSkipTLSVerify: opts.NoHTTPS,
DockerAuthConfig: opts.OciAuth,
AuthFilePath: syfs.DockerConf(),
DockerRegistryUserAgent: useragent.Value(),
BigFilesTemporaryDir: opts.TmpDir,
DockerDaemonHost: opts.DockerHost,
OSChoice: opts.Platform.OS,
ArchitectureChoice: opts.Platform.Architecture,
VariantChoice: opts.Platform.Variant,
}
if opts.NoHTTPS {
sysCtx.DockerInsecureSkipTLSVerify = ocitypes.NewOptionalBool(true)
}
return sysCtx, nil
}
// Pull will create a SIF / OCI-SIF image to the cache or direct to a temporary file if cache is disabled
func Pull(ctx context.Context, imgCache *cache.Handle, pullFrom string, opts PullOptions) (imagePath string, err error) {
directTo := ""
if imgCache.IsDisabled() {
file, err := os.CreateTemp(opts.TmpDir, "sbuild-tmp-cache-")
if err != nil {
return "", fmt.Errorf("unable to create tmp file: %v", err)
}
directTo = file.Name()
sylog.Infof("Downloading library image to tmp cache: %s", directTo)
}
if opts.OciSif {
ocisifOpts := ocisif.PullOptions{
TmpDir: opts.TmpDir,
OciAuth: opts.OciAuth,
DockerHost: opts.DockerHost,
NoHTTPS: opts.NoHTTPS,
NoCleanUp: opts.NoCleanUp,
Platform: opts.Platform,
}
return ocisif.PullOCISIF(ctx, imgCache, directTo, pullFrom, ocisifOpts)
}
return pullNativeSIF(ctx, imgCache, directTo, pullFrom, opts)
}
// PullToFile will create a SIF / OCI-SIF image from the specified oci URI and place it at the specified dest
func PullToFile(ctx context.Context, imgCache *cache.Handle, pullTo, pullFrom string, opts PullOptions) (imagePath string, err error) {
directTo := ""
if imgCache.IsDisabled() {
directTo = pullTo
sylog.Debugf("Cache disabled, pulling directly to: %s", directTo)
}
src := ""
if opts.OciSif {
ocisifOpts := ocisif.PullOptions{
TmpDir: opts.TmpDir,
OciAuth: opts.OciAuth,
DockerHost: opts.DockerHost,
NoHTTPS: opts.NoHTTPS,
NoCleanUp: opts.NoCleanUp,
Platform: opts.Platform,
}
src, err = ocisif.PullOCISIF(ctx, imgCache, directTo, pullFrom, ocisifOpts)
} else {
src, err = pullNativeSIF(ctx, imgCache, directTo, pullFrom, opts)
}
if err != nil {
return "", fmt.Errorf("error fetching image to cache: %v", err)
}
if directTo == "" {
// mode is before umask if pullTo doesn't exist
err = fs.CopyFileAtomic(src, pullTo, 0o777)
if err != nil {
return "", fmt.Errorf("error copying image out of cache (from %q to %q): %w", src, pullTo, err)
}
}
return pullTo, nil
}
|