0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2024-12-23 22:27:35 -05:00
zot/pkg/extensions/sync/utils.go

173 lines
4.4 KiB
Go
Raw Normal View History

//go:build sync
// +build sync
package sync
import (
"context"
"encoding/json"
"fmt"
"io"
"os"
"strings"
"github.com/containers/image/v5/copy"
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/signature"
"github.com/containers/image/v5/types"
"github.com/docker/distribution/reference"
"github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
zerr "zotregistry.io/zot/errors"
"zotregistry.io/zot/pkg/common"
syncconf "zotregistry.io/zot/pkg/extensions/config/sync"
"zotregistry.io/zot/pkg/log"
"zotregistry.io/zot/pkg/test/inject"
)
const (
SyncBlobUploadDir = ".sync"
)
// Get sync.FileCredentials from file.
func getFileCredentials(filepath string) (syncconf.CredentialsFile, error) {
credsFile, err := os.ReadFile(filepath)
if err != nil {
return nil, err
}
var creds syncconf.CredentialsFile
err = json.Unmarshal(credsFile, &creds)
if err != nil {
return nil, err
}
return creds, nil
}
func getUpstreamContext(certDir, username, password string, tlsVerify bool) *types.SystemContext {
upstreamCtx := &types.SystemContext{}
upstreamCtx.DockerCertPath = certDir
upstreamCtx.DockerDaemonCertPath = certDir
if tlsVerify {
upstreamCtx.DockerDaemonInsecureSkipTLSVerify = false
upstreamCtx.DockerInsecureSkipTLSVerify = types.NewOptionalBool(false)
} else {
upstreamCtx.DockerDaemonInsecureSkipTLSVerify = true
upstreamCtx.DockerInsecureSkipTLSVerify = types.NewOptionalBool(true)
}
if username != "" && password != "" {
upstreamCtx.DockerAuthConfig = &types.DockerAuthConfig{
Username: username,
Password: password,
}
}
return upstreamCtx
}
// sync needs transport to be stripped to not be wrongly interpreted as an image reference
// at a non-fully qualified registry (hostname as image and port as tag).
func StripRegistryTransport(url string) string {
return strings.Replace(strings.Replace(url, "http://", "", 1), "https://", "", 1)
}
// getRepoTags lists all tags in a repository.
// It returns a string slice of tags and any error encountered.
func getRepoTags(ctx context.Context, sysCtx *types.SystemContext, host, repo string) ([]string, error) {
repoRef, err := parseRepositoryReference(fmt.Sprintf("%s/%s", host, repo))
if err != nil {
return []string{}, err
}
dockerRef, err := docker.NewReference(reference.TagNameOnly(repoRef))
// hard to reach test case, injected error, see pkg/test/dev.go
if err = inject.Error(err); err != nil {
return nil, err // Should never happen for a reference with tag and no digest
}
tags, err := docker.GetRepositoryTags(ctx, sysCtx, dockerRef)
if err != nil {
return nil, err
}
return tags, nil
}
// parseRepositoryReference parses input into a reference.Named, and verifies that it names a repository, not an image.
func parseRepositoryReference(input string) (reference.Named, error) {
ref, err := reference.ParseNormalizedNamed(input)
if err != nil {
return nil, err
}
if !reference.IsNameOnly(ref) {
return nil, zerr.ErrInvalidRepositoryName
}
return ref, nil
}
// parse a reference, return its digest and if it's valid.
func parseReference(reference string) (digest.Digest, bool) {
var ok bool
d, err := digest.Parse(reference)
if err == nil {
ok = true
}
return d, ok
}
func getCopyOptions(upstreamCtx, localCtx *types.SystemContext) copy.Options {
options := copy.Options{
DestinationCtx: localCtx,
SourceCtx: upstreamCtx,
ReportWriter: io.Discard,
ForceManifestMIMEType: ispec.MediaTypeImageManifest, // force only oci manifest MIME type
ImageListSelection: copy.CopyAllImages,
}
return options
}
func getPolicyContext(log log.Logger) (*signature.PolicyContext, error) {
policy := &signature.Policy{Default: []signature.PolicyRequirement{signature.NewPRInsecureAcceptAnything()}}
policyContext, err := signature.NewPolicyContext(policy)
if err := inject.Error(err); err != nil {
log.Error().Str("errorType", common.TypeOf(err)).
Err(err).Msg("couldn't create policy context")
return nil, err
}
return policyContext, nil
}
func getSupportedMediaType() []string {
return []string{
ispec.MediaTypeImageIndex,
ispec.MediaTypeImageManifest,
manifest.DockerV2ListMediaType,
manifest.DockerV2Schema2MediaType,
}
}
func isSupportedMediaType(mediaType string) bool {
mediaTypes := getSupportedMediaType()
for _, m := range mediaTypes {
if m == mediaType {
return true
}
}
return false
}