Skip to content

Commit

Permalink
Cache authenticators between registry operations to speed up large co…
Browse files Browse the repository at this point in the history
…pies.
  • Loading branch information
Evan Anderson committed Feb 13, 2023
1 parent 93bcd93 commit 6194c0d
Showing 1 changed file with 25 additions and 11 deletions.
36 changes: 25 additions & 11 deletions pkg/imgpkg/registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ type SimpleRegistry struct {
remoteOpts []regremote.Option
refOpts []regname.Option
keychain regauthn.Keychain
authn map[string]regauthn.Authenticator
roundTrippers RoundTripperStorage
transportAccess *sync.Mutex
}
Expand Down Expand Up @@ -195,6 +196,7 @@ func NewSimpleRegistryWithTransport(opts Opts, rTripper http.RoundTripper, regOp
refOpts: refOpts,
keychain: keychain,
roundTrippers: NewMultiRoundTripperStorage(baseRoundTripper),
authn: map[string]regauthn.Authenticator{},
transportAccess: &sync.Mutex{},
}, nil
}
Expand All @@ -219,6 +221,7 @@ func (r SimpleRegistry) CloneWithSingleAuth(imageRef regname.Tag) (Registry, err
refOpts: r.refOpts,
keychain: keychain,
roundTrippers: NewSingleTripperStorage(rt),
authn: map[string]regauthn.Authenticator{},
transportAccess: &sync.Mutex{},
}, nil
}
Expand All @@ -237,42 +240,53 @@ func (r SimpleRegistry) CloneWithLogger(_ util.ProgressLogger) Registry {

// readOpts Returns the readOpts + the keychain
func (r *SimpleRegistry) readOpts(ref regname.Reference) ([]regremote.Option, error) {
rt, err := r.transport(ref, ref.Scope(transport.PullScope))
rt, authn, err := r.transport(ref, ref.Scope(transport.PullScope))
if err != nil {
return nil, err
}
return append([]regremote.Option{regremote.WithAuthFromKeychain(r.keychain), regremote.WithTransport(rt)}, r.remoteOpts...), nil
return append([]regremote.Option{regremote.WithAuth(authn), regremote.WithTransport(rt)}, r.remoteOpts...), nil
}

// writeOpts Returns the writeOpts + the keychain
func (r *SimpleRegistry) writeOpts(ref regname.Reference) ([]regremote.Option, error) {
rt, err := r.transport(ref, ref.Scope(transport.PushScope))
rt, auth, err := r.transport(ref, ref.Scope(transport.PushScope))
if err != nil {
return nil, err
}

return append([]regremote.Option{regremote.WithAuthFromKeychain(r.keychain), regremote.WithTransport(rt)}, r.remoteOpts...), nil
return append([]regremote.Option{regremote.WithAuth(auth), regremote.WithTransport(rt)}, r.remoteOpts...), nil
}

// transport Retrieve the RoundTripper that can be used to access the repository
func (r *SimpleRegistry) transport(ref regname.Reference, scope string) (http.RoundTripper, error) {
func (r *SimpleRegistry) transport(ref regname.Reference, scope string) (http.RoundTripper, regauthn.Authenticator, error) {
registry := ref.Context()
// The idea is that we can only retrieve 1 RoundTripper at a time to ensure that we do not create
// the same RoundTripper multiple times
r.transportAccess.Lock()
defer r.transportAccess.Unlock()
rt := r.roundTrippers.RoundTripper(ref.Context(), scope)
rt := r.roundTrippers.RoundTripper(registry, scope)
if rt == nil {
resolvedAuth, err := r.keychain.Resolve(ref.Context())
resolvedAuth, err := r.keychain.Resolve(registry)
if err != nil {
return nil, fmt.Errorf("Unable retrieve credentials for registry: %s", err)
return nil, nil, fmt.Errorf("Unable retrieve credentials for registry: %s", err)
}
rt, err = r.roundTrippers.CreateRoundTripper(ref.Context().Registry, resolvedAuth, scope)
rt, err = r.roundTrippers.CreateRoundTripper(registry.Registry, resolvedAuth, scope)
if err != nil {
return nil, fmt.Errorf("Error while preparing a transport to talk with the registry: %s", err)
return nil, nil, fmt.Errorf("Error while preparing a transport to talk with the registry: %s", err)
}
}

return rt, nil
auth, ok := r.authn[registry.Name()]
if !ok {
regauth, err := r.keychain.Resolve(registry)
if err != nil {
return nil, nil, fmt.Errorf("Unable to get authenticator for registry %s: %s", ref.Context().Name(), err)
}
r.authn[registry.Name()] = regauth
auth = regauth
}

return rt, auth, nil
}

// Get Retrieve Image descriptor for an Image reference
Expand Down

0 comments on commit 6194c0d

Please sign in to comment.