internal/registry: remove RepositoryInfo, add NewIndexInfo

Most places only use IndexInfo (and may not even need that), so replace
the use of ParseRepositoryInfo for NewIndexInfo, and move the RepositoryInfo
type to the trust package, which uses it as part of its ImageRefAndAuth
struct.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 21e8bbc8a2)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2025-08-03 14:39:30 +02:00
parent 28ffe2416d
commit efdf008933
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
12 changed files with 62 additions and 63 deletions

View File

@ -105,10 +105,10 @@ To push the complete multi-platform image, remove the --platform flag.
} }
// Resolve the Repository name from fqn to RepositoryInfo // Resolve the Repository name from fqn to RepositoryInfo
repoInfo := registry.ParseRepositoryInfo(ref) indexInfo := registry.NewIndexInfo(ref)
// Resolve the Auth config relevant for this server // Resolve the Auth config relevant for this server
authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), repoInfo.Index) authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), indexInfo)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil { if err != nil {
return err return err
@ -134,7 +134,7 @@ To push the complete multi-platform image, remove the --platform flag.
defer responseBody.Close() defer responseBody.Close()
if !opts.untrusted { if !opts.untrusted {
// TODO pushTrustedReference currently doesn't respect `--quiet` // TODO pushTrustedReference currently doesn't respect `--quiet`
return pushTrustedReference(ctx, dockerCli, repoInfo, ref, authConfig, responseBody) return pushTrustedReference(ctx, dockerCli, indexInfo, ref, authConfig, responseBody)
} }
if opts.quiet { if opts.quiet {

View File

@ -11,7 +11,6 @@ import (
"github.com/docker/cli/cli/streams" "github.com/docker/cli/cli/streams"
"github.com/docker/cli/cli/trust" "github.com/docker/cli/cli/trust"
"github.com/docker/cli/internal/jsonstream" "github.com/docker/cli/internal/jsonstream"
"github.com/docker/cli/internal/registry"
"github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/image"
registrytypes "github.com/docker/docker/api/types/registry" registrytypes "github.com/docker/docker/api/types/registry"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
@ -42,7 +41,11 @@ func newNotaryClient(cli command.Streams, imgRefAndAuth trust.ImageRefAndAuth) (
} }
// pushTrustedReference pushes a canonical reference to the trust server. // pushTrustedReference pushes a canonical reference to the trust server.
func pushTrustedReference(ctx context.Context, ioStreams command.Streams, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig registrytypes.AuthConfig, in io.Reader) error { func pushTrustedReference(ctx context.Context, ioStreams command.Streams, indexInfo *registrytypes.IndexInfo, ref reference.Named, authConfig registrytypes.AuthConfig, in io.Reader) error {
repoInfo := &trust.RepositoryInfo{
Name: reference.TrimNamed(ref),
Index: indexInfo,
}
return trust.PushTrustedReference(ctx, ioStreams, repoInfo, ref, authConfig, in, command.UserAgent()) return trust.PushTrustedReference(ctx, ioStreams, repoInfo, ref, authConfig, in, command.UserAgent())
} }

View File

@ -65,7 +65,7 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
return types.PluginInstallOptions{}, err return types.PluginInstallOptions{}, err
} }
repoInfo := registry.ParseRepositoryInfo(ref) indexInfo := registry.NewIndexInfo(ref)
remote := ref.String() remote := ref.String()
_, isCanonical := ref.(reference.Canonical) _, isCanonical := ref.(reference.Canonical)
@ -83,7 +83,7 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
remote = reference.FamiliarString(trusted) remote = reference.FamiliarString(trusted)
} }
authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), repoInfo.Index) authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), indexInfo)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil { if err != nil {
return types.PluginInstallOptions{}, err return types.PluginInstallOptions{}, err

View File

@ -49,8 +49,8 @@ func runPush(ctx context.Context, dockerCli command.Cli, opts pushOptions) error
named = reference.TagNameOnly(named) named = reference.TagNameOnly(named)
repoInfo := registry.ParseRepositoryInfo(named) indexInfo := registry.NewIndexInfo(named)
authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), repoInfo.Index) authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), indexInfo)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil { if err != nil {
return err return err
@ -63,6 +63,10 @@ func runPush(ctx context.Context, dockerCli command.Cli, opts pushOptions) error
defer responseBody.Close() defer responseBody.Close()
if !opts.untrusted { if !opts.untrusted {
repoInfo := &trust.RepositoryInfo{
Name: reference.TrimNamed(named),
Index: indexInfo,
}
return trust.PushTrustedReference(ctx, dockerCli, repoInfo, named, authConfig, responseBody, command.UserAgent()) return trust.PushTrustedReference(ctx, dockerCli, repoInfo, named, authConfig, responseBody, command.UserAgent())
} }

View File

@ -51,9 +51,12 @@ func resolveServiceImageDigestContentTrust(dockerCli command.Cli, service *swarm
} }
func trustedResolveDigest(cli command.Cli, ref reference.NamedTagged) (reference.Canonical, error) { func trustedResolveDigest(cli command.Cli, ref reference.NamedTagged) (reference.Canonical, error) {
repoInfo := registry.ParseRepositoryInfo(ref) indexInfo := registry.NewIndexInfo(ref)
authConfig := command.ResolveAuthConfig(cli.ConfigFile(), repoInfo.Index) authConfig := command.ResolveAuthConfig(cli.ConfigFile(), indexInfo)
repoInfo := &trust.RepositoryInfo{
Name: reference.TrimNamed(ref),
Index: indexInfo,
}
notaryRepo, err := trust.GetNotaryRepository(cli.In(), cli.Out(), command.UserAgent(), repoInfo, &authConfig, "pull") notaryRepo, err := trust.GetNotaryRepository(cli.In(), cli.Out(), command.UserAgent(), repoInfo, &authConfig, "pull")
if err != nil { if err != nil {
return nil, errors.Wrap(err, "error establishing connection to trust repository") return nil, errors.Wrap(err, "error establishing connection to trust repository")

View File

@ -34,8 +34,7 @@ func (r repositoryEndpoint) BaseURL() string {
func newDefaultRepositoryEndpoint(ref reference.Named, insecure bool) (repositoryEndpoint, error) { func newDefaultRepositoryEndpoint(ref reference.Named, insecure bool) (repositoryEndpoint, error) {
repoName := reference.TrimNamed(ref) repoName := reference.TrimNamed(ref)
repoInfo := registry.ParseRepositoryInfo(ref) indexInfo := registry.NewIndexInfo(ref)
indexInfo := repoInfo.Index
endpoint, err := getDefaultEndpoint(ref, !indexInfo.Secure) endpoint, err := getDefaultEndpoint(ref, !indexInfo.Secure)
if err != nil { if err != nil {

View File

@ -221,8 +221,7 @@ func (c *client) iterateEndpoints(ctx context.Context, namedRef reference.Named,
} }
repoName := reference.TrimNamed(namedRef) repoName := reference.TrimNamed(namedRef)
repoInfo := registry.ParseRepositoryInfo(namedRef) indexInfo := registry.NewIndexInfo(namedRef)
indexInfo := repoInfo.Index
confirmedTLSRegistries := make(map[string]bool) confirmedTLSRegistries := make(map[string]bool)
for _, endpoint := range endpoints { for _, endpoint := range endpoints {
@ -285,8 +284,7 @@ func allEndpoints(namedRef reference.Named, insecure bool) ([]registry.APIEndpoi
if err != nil { if err != nil {
return nil, err return nil, err
} }
repoInfo := registry.ParseRepositoryInfo(namedRef) endpoints, err := registryService.Endpoints(context.TODO(), reference.Domain(namedRef))
endpoints, err := registryService.Endpoints(context.TODO(), reference.Domain(repoInfo.Name))
logrus.Debugf("endpoints for %s: %v", namedRef, endpoints) logrus.Debugf("endpoints for %s: %v", namedRef, endpoints)
return endpoints, err return endpoints, err
} }

View File

@ -95,7 +95,7 @@ func (simpleCredentialStore) SetRefreshToken(*url.URL, string, string) {}
// GetNotaryRepository returns a NotaryRepository which stores all the // GetNotaryRepository returns a NotaryRepository which stores all the
// information needed to operate on a notary repository. // information needed to operate on a notary repository.
// It creates an HTTP transport providing authentication support. // It creates an HTTP transport providing authentication support.
func GetNotaryRepository(in io.Reader, out io.Writer, userAgent string, repoInfo *registry.RepositoryInfo, authConfig *registrytypes.AuthConfig, actions ...string) (client.Repository, error) { func GetNotaryRepository(in io.Reader, out io.Writer, userAgent string, repoInfo *RepositoryInfo, authConfig *registrytypes.AuthConfig, actions ...string) (client.Repository, error) {
server, err := Server(repoInfo.Index) server, err := Server(repoInfo.Index)
if err != nil { if err != nil {
return nil, err return nil, err
@ -304,11 +304,18 @@ type ImageRefAndAuth struct {
original string original string
authConfig *registrytypes.AuthConfig authConfig *registrytypes.AuthConfig
reference reference.Named reference reference.Named
repoInfo *registry.RepositoryInfo repoInfo *RepositoryInfo
tag string tag string
digest digest.Digest digest digest.Digest
} }
// RepositoryInfo describes a repository
type RepositoryInfo struct {
Name reference.Named
// Index points to registry information
Index *registrytypes.IndexInfo
}
// GetImageReferencesAndAuth retrieves the necessary reference and auth information for an image name // GetImageReferencesAndAuth retrieves the necessary reference and auth information for an image name
// as an ImageRefAndAuth struct // as an ImageRefAndAuth struct
func GetImageReferencesAndAuth(ctx context.Context, func GetImageReferencesAndAuth(ctx context.Context,
@ -321,15 +328,18 @@ func GetImageReferencesAndAuth(ctx context.Context,
} }
// Resolve the Repository name from fqn to RepositoryInfo // Resolve the Repository name from fqn to RepositoryInfo
repoInfo := registry.ParseRepositoryInfo(ref) indexInfo := registry.NewIndexInfo(ref)
authConfig := authResolver(ctx, repoInfo.Index) authConfig := authResolver(ctx, indexInfo)
return ImageRefAndAuth{ return ImageRefAndAuth{
original: imgName, original: imgName,
authConfig: &authConfig, authConfig: &authConfig,
reference: ref, reference: ref,
repoInfo: repoInfo, repoInfo: &RepositoryInfo{
tag: getTag(ref), Name: reference.TrimNamed(ref),
digest: getDigest(ref), Index: indexInfo,
},
tag: getTag(ref),
digest: getDigest(ref),
}, nil }, nil
} }
@ -366,7 +376,7 @@ func (imgRefAuth *ImageRefAndAuth) Reference() reference.Named {
} }
// RepoInfo returns the repository information for a given ImageRefAndAuth // RepoInfo returns the repository information for a given ImageRefAndAuth
func (imgRefAuth *ImageRefAndAuth) RepoInfo() *registry.RepositoryInfo { func (imgRefAuth *ImageRefAndAuth) RepoInfo() *RepositoryInfo {
return imgRefAuth.repoInfo return imgRefAuth.repoInfo
} }

View File

@ -11,7 +11,6 @@ import (
"github.com/distribution/reference" "github.com/distribution/reference"
"github.com/docker/cli/cli/streams" "github.com/docker/cli/cli/streams"
"github.com/docker/cli/internal/jsonstream" "github.com/docker/cli/internal/jsonstream"
"github.com/docker/cli/internal/registry"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry" registrytypes "github.com/docker/docker/api/types/registry"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
@ -32,7 +31,7 @@ type Streams interface {
// PushTrustedReference pushes a canonical reference to the trust server. // PushTrustedReference pushes a canonical reference to the trust server.
// //
//nolint:gocyclo //nolint:gocyclo
func PushTrustedReference(ctx context.Context, ioStreams Streams, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig registrytypes.AuthConfig, in io.Reader, userAgent string) error { func PushTrustedReference(ctx context.Context, ioStreams Streams, repoInfo *RepositoryInfo, ref reference.Named, authConfig registrytypes.AuthConfig, in io.Reader, userAgent string) error {
// If it is a trusted push we would like to find the target entry which match the // If it is a trusted push we would like to find the target entry which match the
// tag provided in the function and then do an AddTarget later. // tag provided in the function and then do an AddTarget later.
notaryTarget := &client.Target{} notaryTarget := &client.Target{}

View File

@ -252,27 +252,22 @@ func validateHostPort(s string) error {
return nil return nil
} }
// ParseRepositoryInfo performs the breakdown of a repository name into a // NewIndexInfo creates a new [registry.IndexInfo] or the given
// [RepositoryInfo], but lacks registry configuration. // repository-name, and detects whether the registry is considered
func ParseRepositoryInfo(reposName reference.Named) *RepositoryInfo { // "secure" (non-localhost).
func NewIndexInfo(reposName reference.Named) *registry.IndexInfo {
indexName := normalizeIndexName(reference.Domain(reposName)) indexName := normalizeIndexName(reference.Domain(reposName))
if indexName == IndexName { if indexName == IndexName {
return &RepositoryInfo{ return &registry.IndexInfo{
Name: reference.TrimNamed(reposName), Name: IndexName,
Index: &registry.IndexInfo{ Secure: true,
Name: IndexName, Official: true,
Secure: true,
Official: true,
},
} }
} }
return &RepositoryInfo{ return &registry.IndexInfo{
Name: reference.TrimNamed(reposName), Name: indexName,
Index: &registry.IndexInfo{ Secure: !isInsecure(indexName),
Name: indexName,
Secure: !isInsecure(indexName),
},
} }
} }

View File

@ -9,7 +9,7 @@ import (
is "gotest.tools/v3/assert/cmp" is "gotest.tools/v3/assert/cmp"
) )
func TestParseRepositoryInfo(t *testing.T) { func TestNewIndexInfo(t *testing.T) {
type staticRepositoryInfo struct { type staticRepositoryInfo struct {
Index *registry.IndexInfo Index *registry.IndexInfo
RemoteName string RemoteName string
@ -269,12 +269,13 @@ func TestParseRepositoryInfo(t *testing.T) {
named, err := reference.ParseNormalizedNamed(reposName) named, err := reference.ParseNormalizedNamed(reposName)
assert.NilError(t, err) assert.NilError(t, err)
repoInfo := ParseRepositoryInfo(named) indexInfo := NewIndexInfo(named)
repoInfoName := reference.TrimNamed(named)
assert.Check(t, is.DeepEqual(repoInfo.Index, expected.Index)) assert.Check(t, is.DeepEqual(indexInfo, expected.Index))
assert.Check(t, is.Equal(reference.Path(repoInfo.Name), expected.RemoteName)) assert.Check(t, is.Equal(reference.Path(repoInfoName), expected.RemoteName))
assert.Check(t, is.Equal(reference.FamiliarName(repoInfo.Name), expected.LocalName)) assert.Check(t, is.Equal(reference.FamiliarName(repoInfoName), expected.LocalName))
assert.Check(t, is.Equal(repoInfo.Name.Name(), expected.CanonicalName)) assert.Check(t, is.Equal(repoInfoName.Name(), expected.CanonicalName))
}) })
} }
} }

View File

@ -1,13 +0,0 @@
package registry
import (
"github.com/distribution/reference"
"github.com/docker/docker/api/types/registry"
)
// RepositoryInfo describes a repository
type RepositoryInfo struct {
Name reference.Named
// Index points to registry information
Index *registry.IndexInfo
}