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
repoInfo := registry.ParseRepositoryInfo(ref)
indexInfo := registry.NewIndexInfo(ref)
// 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)
if err != nil {
return err
@ -134,7 +134,7 @@ To push the complete multi-platform image, remove the --platform flag.
defer responseBody.Close()
if !opts.untrusted {
// 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 {

View File

@ -11,7 +11,6 @@ import (
"github.com/docker/cli/cli/streams"
"github.com/docker/cli/cli/trust"
"github.com/docker/cli/internal/jsonstream"
"github.com/docker/cli/internal/registry"
"github.com/docker/docker/api/types/image"
registrytypes "github.com/docker/docker/api/types/registry"
"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.
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())
}

View File

@ -65,7 +65,7 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
return types.PluginInstallOptions{}, err
}
repoInfo := registry.ParseRepositoryInfo(ref)
indexInfo := registry.NewIndexInfo(ref)
remote := ref.String()
_, isCanonical := ref.(reference.Canonical)
@ -83,7 +83,7 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
remote = reference.FamiliarString(trusted)
}
authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), repoInfo.Index)
authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), indexInfo)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil {
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)
repoInfo := registry.ParseRepositoryInfo(named)
authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), repoInfo.Index)
indexInfo := registry.NewIndexInfo(named)
authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), indexInfo)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil {
return err
@ -63,6 +63,10 @@ func runPush(ctx context.Context, dockerCli command.Cli, opts pushOptions) error
defer responseBody.Close()
if !opts.untrusted {
repoInfo := &trust.RepositoryInfo{
Name: reference.TrimNamed(named),
Index: indexInfo,
}
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) {
repoInfo := registry.ParseRepositoryInfo(ref)
authConfig := command.ResolveAuthConfig(cli.ConfigFile(), repoInfo.Index)
indexInfo := registry.NewIndexInfo(ref)
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")
if err != nil {
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) {
repoName := reference.TrimNamed(ref)
repoInfo := registry.ParseRepositoryInfo(ref)
indexInfo := repoInfo.Index
indexInfo := registry.NewIndexInfo(ref)
endpoint, err := getDefaultEndpoint(ref, !indexInfo.Secure)
if err != nil {

View File

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

View File

@ -95,7 +95,7 @@ func (simpleCredentialStore) SetRefreshToken(*url.URL, string, string) {}
// GetNotaryRepository returns a NotaryRepository which stores all the
// information needed to operate on a notary repository.
// 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)
if err != nil {
return nil, err
@ -304,11 +304,18 @@ type ImageRefAndAuth struct {
original string
authConfig *registrytypes.AuthConfig
reference reference.Named
repoInfo *registry.RepositoryInfo
repoInfo *RepositoryInfo
tag string
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
// as an ImageRefAndAuth struct
func GetImageReferencesAndAuth(ctx context.Context,
@ -321,15 +328,18 @@ func GetImageReferencesAndAuth(ctx context.Context,
}
// Resolve the Repository name from fqn to RepositoryInfo
repoInfo := registry.ParseRepositoryInfo(ref)
authConfig := authResolver(ctx, repoInfo.Index)
indexInfo := registry.NewIndexInfo(ref)
authConfig := authResolver(ctx, indexInfo)
return ImageRefAndAuth{
original: imgName,
authConfig: &authConfig,
reference: ref,
repoInfo: repoInfo,
tag: getTag(ref),
digest: getDigest(ref),
repoInfo: &RepositoryInfo{
Name: reference.TrimNamed(ref),
Index: indexInfo,
},
tag: getTag(ref),
digest: getDigest(ref),
}, nil
}
@ -366,7 +376,7 @@ func (imgRefAuth *ImageRefAndAuth) Reference() reference.Named {
}
// RepoInfo returns the repository information for a given ImageRefAndAuth
func (imgRefAuth *ImageRefAndAuth) RepoInfo() *registry.RepositoryInfo {
func (imgRefAuth *ImageRefAndAuth) RepoInfo() *RepositoryInfo {
return imgRefAuth.repoInfo
}

View File

@ -11,7 +11,6 @@ import (
"github.com/distribution/reference"
"github.com/docker/cli/cli/streams"
"github.com/docker/cli/internal/jsonstream"
"github.com/docker/cli/internal/registry"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/opencontainers/go-digest"
@ -32,7 +31,7 @@ type Streams interface {
// PushTrustedReference pushes a canonical reference to the trust server.
//
//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
// tag provided in the function and then do an AddTarget later.
notaryTarget := &client.Target{}

View File

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

View File

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