Use distribution reference

Remove forked reference package. Use normalized named values
everywhere and familiar functions to convert back to familiar
strings for UX and storage compatibility.

Enforce that the source repository in the distribution metadata
is always a normalized string, ignore invalid values which are not.
Update distribution tests to use normalized values.

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
This commit is contained in:
Derek McGowan 2017-01-25 16:54:18 -08:00
parent a4cd8a978f
commit 635d686a88
13 changed files with 53 additions and 71 deletions

View File

@ -168,11 +168,7 @@ func createContainer(ctx context.Context, dockerCli *command.DockerCli, config *
return nil, err
}
if named, ok := ref.(reference.Named); ok {
if reference.IsNameOnly(named) {
namedRef = reference.EnsureTagged(named)
} else {
namedRef = named
}
namedRef = reference.TagNameOnly(named)
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && command.IsTrusted() {
var err error

View File

@ -94,12 +94,12 @@ func (ctx *DiskUsageContext) Write() {
tag := "<none>"
if len(i.RepoTags) > 0 && !isDangling(*i) {
// Only show the first tag
ref, err := reference.ParseNamed(i.RepoTags[0])
ref, err := reference.ParseNormalizedNamed(i.RepoTags[0])
if err != nil {
continue
}
if nt, ok := ref.(reference.NamedTagged); ok {
repo = ref.Name()
repo = reference.FamiliarName(ref)
tag = nt.Tag()
}
}

View File

@ -94,7 +94,7 @@ func imageFormat(ctx ImageContext, images []types.ImageSummary, format func(subC
repoTags := map[string][]string{}
repoDigests := map[string][]string{}
for _, refString := range append(image.RepoTags) {
for _, refString := range image.RepoTags {
ref, err := reference.ParseNormalizedNamed(refString)
if err != nil {
continue
@ -104,7 +104,7 @@ func imageFormat(ctx ImageContext, images []types.ImageSummary, format func(subC
repoTags[familiarRef] = append(repoTags[familiarRef], nt.Tag())
}
}
for _, refString := range append(image.RepoDigests) {
for _, refString := range image.RepoDigests {
ref, err := reference.ParseNormalizedNamed(refString)
if err != nil {
continue

View File

@ -5,7 +5,7 @@ import (
"strings"
"time"
distreference "github.com/docker/distribution/reference"
"github.com/docker/distribution/reference"
mounttypes "github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/cli/command/inspect"
@ -409,11 +409,12 @@ func (c *serviceContext) Replicas() string {
func (c *serviceContext) Image() string {
c.AddHeader(imageHeader)
image := c.service.Spec.TaskTemplate.ContainerSpec.Image
if ref, err := distreference.ParseNamed(image); err == nil {
// update image string for display
namedTagged, ok := ref.(distreference.NamedTagged)
if ok {
image = namedTagged.Name() + ":" + namedTagged.Tag()
if ref, err := reference.ParseNormalizedNamed(image); err == nil {
// update image string for display, (strips any digest)
if nt, ok := ref.(reference.NamedTagged); ok {
if namedTagged, err := reference.WithTag(reference.TrimNamed(nt), nt.Tag()); err == nil {
image = reference.FamiliarString(namedTagged)
}
}
}

View File

@ -397,9 +397,7 @@ func rewriteDockerfileFrom(ctx context.Context, dockerfile io.Reader, translator
if err != nil {
return nil, nil, err
}
if reference.IsNameOnly(ref) {
ref = reference.EnsureTagged(ref)
}
ref = reference.TagNameOnly(ref)
if ref, ok := ref.(reference.NamedTagged); ok && command.IsTrusted() {
trustedRef, err := translator(ctx, ref)
if err != nil {

View File

@ -42,7 +42,6 @@ func NewPullCommand(dockerCli *command.DockerCli) *cobra.Command {
}
func runPull(dockerCli *command.DockerCli, opts pullOptions) error {
var distributionRef reference.Named
distributionRef, err := reference.ParseNormalizedNamed(opts.remote)
if err != nil {
return err
@ -52,9 +51,10 @@ func runPull(dockerCli *command.DockerCli, opts pullOptions) error {
}
if !opts.all && reference.IsNameOnly(distributionRef) {
taggedRef := reference.EnsureTagged(distributionRef)
fmt.Fprintf(dockerCli.Out(), "Using default tag: %s\n", taggedRef.Tag())
distributionRef = taggedRef
distributionRef = reference.TagNameOnly(distributionRef)
if tagged, ok := distributionRef.(reference.Tagged); ok {
fmt.Fprintf(dockerCli.Out(), "Using default tag: %s\n", tagged.Tag())
}
}
// Resolve the Repository name from fqn to RepositoryInfo

View File

@ -129,15 +129,15 @@ func PushTrustedReference(cli *command.DockerCli, repoInfo *registry.RepositoryI
// Initialize the notary repository with a remotely managed snapshot key
if err := repo.Initialize([]string{rootKeyID}, data.CanonicalSnapshotRole); err != nil {
return trust.NotaryError(repoInfo.FullName(), err)
return trust.NotaryError(repoInfo.Name.Name(), err)
}
fmt.Fprintf(cli.Out(), "Finished initializing %q\n", repoInfo.FullName())
fmt.Fprintf(cli.Out(), "Finished initializing %q\n", repoInfo.Name.Name())
err = repo.AddTarget(target, data.CanonicalTargetsRole)
case nil:
// already initialized and we have successfully downloaded the latest metadata
err = addTargetToAllSignableRoles(repo, target)
default:
return trust.NotaryError(repoInfo.FullName(), err)
return trust.NotaryError(repoInfo.Name.Name(), err)
}
if err == nil {
@ -145,11 +145,11 @@ func PushTrustedReference(cli *command.DockerCli, repoInfo *registry.RepositoryI
}
if err != nil {
fmt.Fprintf(cli.Out(), "Failed to sign %q:%s - %s\n", repoInfo.FullName(), tag, err.Error())
return trust.NotaryError(repoInfo.FullName(), err)
fmt.Fprintf(cli.Out(), "Failed to sign %q:%s - %s\n", repoInfo.Name.Name(), tag, err.Error())
return trust.NotaryError(repoInfo.Name.Name(), err)
}
fmt.Fprintf(cli.Out(), "Successfully signed %q:%s\n", repoInfo.FullName(), tag)
fmt.Fprintf(cli.Out(), "Successfully signed %q:%s\n", repoInfo.Name.Name(), tag)
return nil
}
@ -342,12 +342,12 @@ func TrustedReference(ctx context.Context, cli *command.DockerCli, ref reference
t, err := notaryRepo.GetTargetByName(ref.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole)
if err != nil {
return nil, trust.NotaryError(repoInfo.FullName(), err)
return nil, trust.NotaryError(repoInfo.Name.Name(), err)
}
// Only list tags in the top level targets role or the releases delegation role - ignore
// all other delegation roles
if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole {
return nil, trust.NotaryError(repoInfo.FullName(), fmt.Errorf("No trust data for %s", ref.Tag()))
return nil, trust.NotaryError(repoInfo.Name.Name(), fmt.Errorf("No trust data for %s", ref.Tag()))
}
r, err := convertTarget(t.Target)
if err != nil {

View File

@ -7,7 +7,6 @@ import (
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/cli/command/image"
@ -54,20 +53,6 @@ func newInstallCommand(dockerCli *command.DockerCli) *cobra.Command {
return cmd
}
func getRepoIndexFromUnnormalizedRef(ref reference.Named) (*registrytypes.IndexInfo, error) {
named, err := reference.ParseNormalizedNamed(ref.Name())
if err != nil {
return nil, err
}
repoInfo, err := registry.ParseRepositoryInfo(named)
if err != nil {
return nil, err
}
return repoInfo.Index, nil
}
type pluginRegistryService struct {
registry.Service
}
@ -104,9 +89,10 @@ func buildPullConfig(ctx context.Context, dockerCli *command.DockerCli, opts plu
_, isCanonical := ref.(reference.Canonical)
if command.IsTrusted() && !isCanonical {
ref = reference.TagNameOnly(ref)
nt, ok := ref.(reference.NamedTagged)
if !ok {
nt = reference.EnsureTagged(ref)
return types.PluginInstallOptions{}, fmt.Errorf("invalid name: %s", ref.String())
}
ctx := context.Background()
@ -148,7 +134,7 @@ func runInstall(dockerCli *command.DockerCli, opts pluginOptions) error {
if _, ok := aref.(reference.Canonical); ok {
return fmt.Errorf("invalid name: %s", opts.localName)
}
localName = reference.FamiliarString(reference.EnsureTagged(aref))
localName = reference.FamiliarString(reference.TagNameOnly(aref))
}
ctx := context.Background()

View File

@ -40,10 +40,7 @@ func runPush(dockerCli *command.DockerCli, name string) error {
return fmt.Errorf("invalid name: %s", name)
}
taggedRef, ok := named.(reference.NamedTagged)
if !ok {
taggedRef = reference.EnsureTagged(named)
}
named = reference.TagNameOnly(named)
ctx := context.Background()
@ -58,7 +55,7 @@ func runPush(dockerCli *command.DockerCli, name string) error {
return err
}
responseBody, err := dockerCli.Client().PluginPush(ctx, reference.FamiliarString(taggedRef), encodedAuth)
responseBody, err := dockerCli.Client().PluginPush(ctx, reference.FamiliarString(named), encodedAuth)
if err != nil {
return err
}

View File

@ -5,10 +5,10 @@ import (
"fmt"
"strings"
"github.com/docker/distribution/reference"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/reference"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@ -49,19 +49,19 @@ func runUpgrade(dockerCli *command.DockerCli, opts pluginOptions) error {
if opts.remote == "" {
opts.remote = p.PluginReference
}
remote, err := reference.ParseNamed(opts.remote)
remote, err := reference.ParseNormalizedNamed(opts.remote)
if err != nil {
return errors.Wrap(err, "error parsing remote upgrade image reference")
}
remote = reference.WithDefaultTag(remote)
remote = reference.TagNameOnly(remote)
old, err := reference.ParseNamed(p.PluginReference)
old, err := reference.ParseNormalizedNamed(p.PluginReference)
if err != nil {
return errors.Wrap(err, "error parsing current image reference")
}
old = reference.WithDefaultTag(old)
old = reference.TagNameOnly(old)
fmt.Fprintf(dockerCli.Out(), "Upgrading plugin %s from %s to %s\n", p.Name, old, remote)
fmt.Fprintf(dockerCli.Out(), "Upgrading plugin %s from %s to %s\n", p.Name, reference.FamiliarString(old), reference.FamiliarString(remote))
if !opts.skipRemoteCheck && remote.String() != old.String() {
if !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), "Plugin images do not match, are you sure?") {
return errors.New("canceling upgrade request")

View File

@ -33,10 +33,12 @@ func resolveServiceImageDigest(dockerCli *command.DockerCli, service *swarm.Serv
namedRef, ok := ref.(reference.Named)
if !ok {
return errors.New("failed to resolve image digest using content trust: reference is not named")
}
taggedRef := reference.EnsureTagged(namedRef)
namedRef = reference.TagNameOnly(namedRef)
taggedRef, ok := namedRef.(reference.NamedTagged)
if !ok {
return errors.New("failed to resolve image digest using content trust: reference is not tagged")
}
resolvedImage, err := trustedResolveDigest(context.Background(), dockerCli, taggedRef)
if err != nil {
@ -65,12 +67,12 @@ func trustedResolveDigest(ctx context.Context, cli *command.DockerCli, ref refer
t, err := notaryRepo.GetTargetByName(ref.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole)
if err != nil {
return nil, trust.NotaryError(repoInfo.FullName(), err)
return nil, trust.NotaryError(repoInfo.Name.Name(), err)
}
// Only get the tag if it's in the top level targets role or the releases delegation role
// ignore it if it's in any other delegation roles
if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole {
return nil, trust.NotaryError(repoInfo.FullName(), fmt.Errorf("No trust data for %s", reference.FamiliarString(ref)))
return nil, trust.NotaryError(repoInfo.Name.Name(), fmt.Errorf("No trust data for %s", reference.FamiliarString(ref)))
}
logrus.Debugf("retrieving target for %s role\n", t.Role)

View File

@ -10,7 +10,7 @@ import (
"golang.org/x/net/context"
distreference "github.com/docker/distribution/reference"
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/cli/command/idresolver"
@ -129,13 +129,15 @@ func print(out io.Writer, ctx context.Context, tasks []swarm.Task, resolver *idr
image := task.Spec.ContainerSpec.Image
if !noTrunc {
ref, err := distreference.ParseNamed(image)
ref, err := reference.ParseNormalizedNamed(image)
if err == nil {
// update image string for display
namedTagged, ok := ref.(distreference.NamedTagged)
if ok {
image = namedTagged.Name() + ":" + namedTagged.Tag()
// update image string for display, (strips any digest)
if nt, ok := ref.(reference.NamedTagged); ok {
if namedTagged, err := reference.WithTag(reference.TrimNamed(nt), nt.Tag()); err == nil {
image = reference.FamiliarString(namedTagged)
}
}
}
}

View File

@ -148,7 +148,7 @@ func GetNotaryRepository(streams command.Streams, repoInfo *registry.RepositoryI
}
scope := auth.RepositoryScope{
Repository: repoInfo.FullName(),
Repository: repoInfo.Name.Name(),
Actions: actions,
Class: repoInfo.Class,
}
@ -166,7 +166,7 @@ func GetNotaryRepository(streams command.Streams, repoInfo *registry.RepositoryI
return client.NewNotaryRepository(
trustDirectory(),
repoInfo.FullName(),
repoInfo.Name.Name(),
server,
tr,
getPassphraseRetriever(streams),