Path: blob/main/components/registry-facade/pkg/registry/resolver.go
2499 views
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package registry56import (7"context"8"encoding/json"910"github.com/containerd/containerd/remotes"11ociv1 "github.com/opencontainers/image-spec/specs-go/v1"12redis "github.com/redis/go-redis/v9"13)1415type RedisCachedResolver struct {16Client *redis.Client17Provider ResolverProvider1819d remotes.Resolver20}2122var (23_ remotes.Resolver = &RedisCachedResolver{}24_ ResolverProvider = (&RedisCachedResolver{}).Factory25)2627type resolverResult struct {28Name string29Desc ociv1.Descriptor30}3132// Resolve attempts to resolve the reference into a name and descriptor.33//34// The argument `ref` should be a scheme-less URI representing the remote.35// Structurally, it has a host and path. The "host" can be used to directly36// reference a specific host or be matched against a specific handler.37//38// The returned name should be used to identify the referenced entity.39// Dependending on the remote namespace, this may be immutable or mutable.40// While the name may differ from ref, it should itself be a valid ref.41//42// If the resolution fails, an error will be returned.43func (rcr *RedisCachedResolver) Resolve(ctx context.Context, ref string) (name string, desc ociv1.Descriptor, err error) {44raw, _ := rcr.Client.Get(ctx, "resolve."+ref).Result()45if raw != "" {46var res resolverResult47if err := json.Unmarshal([]byte(raw), &res); err == nil {48return res.Name, res.Desc, nil49}50}5152name, desc, err = rcr.resolver().Resolve(ctx, ref)53if err != nil {54return55}5657if raw, err := json.Marshal(resolverResult{Name: name, Desc: desc}); err == nil {58rcr.Client.Set(ctx, "resolve."+ref, string(raw), 0)59}6061return62}6364// Fetcher returns a new fetcher for the provided reference.65// All content fetched from the returned fetcher will be66// from the namespace referred to by ref.67func (rcr *RedisCachedResolver) Fetcher(ctx context.Context, ref string) (remotes.Fetcher, error) {68return rcr.resolver().Fetcher(ctx, ref)69}7071// Pusher returns a new pusher for the provided reference72// The returned Pusher should satisfy content.Ingester and concurrent attempts73// to push the same blob using the Ingester API should result in ErrUnavailable.74func (rcr *RedisCachedResolver) Pusher(ctx context.Context, ref string) (remotes.Pusher, error) {75return rcr.resolver().Pusher(ctx, ref)76}7778func (rcr *RedisCachedResolver) resolver() remotes.Resolver {79if rcr.d == nil {80rcr.d = rcr.Provider()81}82return rcr.d83}8485func (rcr *RedisCachedResolver) Factory() remotes.Resolver {86return &RedisCachedResolver{87Client: rcr.Client,88Provider: rcr.Provider,89d: rcr.Provider(),90}91}929394