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/on_demand.go
Petu Eusebiu 19003e8a71 Added new extension "sync"
Periodically poll registries and pull images according to sync's config
Added sync on demand, syncing when clients asks for an image which
zot doesn't have.

Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
2021-10-21 10:32:46 -07:00

90 lines
2.7 KiB
Go

package sync
import (
"context"
"fmt"
"strings"
"github.com/anuvu/zot/pkg/log"
"github.com/containers/common/pkg/retry"
"github.com/containers/image/v5/copy"
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/docker/reference"
)
func OneImage(cfg Config, log log.Logger,
address, port, serverCert, serverKey, caCert, repoName, tag string) (bool, error) {
localCtx, policyCtx, err := getLocalContexts(serverCert, serverKey, caCert, log)
if err != nil {
return false, err
}
localRegistryName := strings.Replace(fmt.Sprintf("%s:%s", address, port), "0.0.0.0", "127.0.0.1", 1)
var credentialsFile CredentialsFile
if cfg.CredentialsFile != "" {
credentialsFile, err = getFileCredentials(cfg.CredentialsFile)
if err != nil {
log.Error().Err(err).Msgf("couldn't get registry credentials from %s", cfg.CredentialsFile)
return false, err
}
}
var synced bool
for _, regCfg := range cfg.Registries {
if !regCfg.OnDemand {
log.Info().Msgf("skipping syncing on demand from %s, onDemand flag is false", regCfg.URL)
continue
}
registryConfig := regCfg
log.Info().Msgf("syncing on demand with %s", registryConfig.URL)
upstreamRegistryName := strings.Replace(strings.Replace(regCfg.URL, "http://", "", 1), "https://", "", 1)
upstreamCtx := getUpstreamContext(&registryConfig, credentialsFile[upstreamRegistryName])
upstreamRepoRef, err := parseRepositoryReference(fmt.Sprintf("%s/%s", upstreamRegistryName, repoName))
upstreamTaggedRef, err := reference.WithTag(upstreamRepoRef, tag)
if err != nil {
log.Err(err).Msgf("error creating a reference for repository %s and tag %q", upstreamRepoRef.Name(), tag)
return synced, err
}
upstreamRef, err := docker.NewReference(upstreamTaggedRef)
ref := strings.Replace(upstreamRef.DockerReference().String(), upstreamRegistryName, "", 1)
localRef, err := docker.Transport.ParseReference(
fmt.Sprintf("//%s%s", localRegistryName, ref),
)
if err != nil {
return synced, err
}
log.Info().Msgf("copying image %s to %s", upstreamRef.DockerReference().Name(), localRef.DockerReference().Name())
options := getCopyOptions(upstreamCtx, localCtx)
retryOptions := &retry.RetryOptions{
MaxRetry: maxRetries,
}
if err = retry.RetryIfNecessary(context.Background(), func() error {
_, err = copy.Image(context.Background(), policyCtx, localRef, upstreamRef, &options)
return err
}, retryOptions); err != nil {
log.Error().Err(err).Msgf("error while copying image %s to %s",
upstreamRef.DockerReference().Name(), localRef.DockerReference().Name())
} else {
log.Info().Msgf("successfully synced %s", upstreamRef.DockerReference().Name())
synced = true
return synced, nil
}
}
return synced, nil
}