Skip to content

Commit

Permalink
Merge pull request #3542 from apostasie/rewrite-refutils
Browse files Browse the repository at this point in the history
`referenceutil` cleanup
  • Loading branch information
ktock authored Oct 17, 2024
2 parents 1122644 + efb9a87 commit f240e58
Show file tree
Hide file tree
Showing 18 changed files with 502 additions and 200 deletions.
26 changes: 12 additions & 14 deletions cmd/nerdctl/image/image_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,49 +70,47 @@ Properties:
return imagesCommand
}

func processImageListOptions(cmd *cobra.Command, args []string) (types.ImageListOptions, error) {
func processImageListOptions(cmd *cobra.Command, args []string) (*types.ImageListOptions, error) {
globalOptions, err := helpers.ProcessRootCmdFlags(cmd)
if err != nil {
return types.ImageListOptions{}, err
return nil, err
}
var filters []string

if len(args) > 0 {
canonicalRef, err := referenceutil.ParseAny(args[0])
parsedReference, err := referenceutil.Parse(args[0])
if err != nil {
return types.ImageListOptions{}, err
return nil, err
}
filters = append(filters, fmt.Sprintf("name==%s", canonicalRef.String()))
filters = append(filters, fmt.Sprintf("name==%s", args[0]))
filters = []string{fmt.Sprintf("name==%s", parsedReference)}
}
quiet, err := cmd.Flags().GetBool("quiet")
if err != nil {
return types.ImageListOptions{}, err
return nil, err
}
noTrunc, err := cmd.Flags().GetBool("no-trunc")
if err != nil {
return types.ImageListOptions{}, err
return nil, err
}
format, err := cmd.Flags().GetString("format")
if err != nil {
return types.ImageListOptions{}, err
return nil, err
}
var inputFilters []string
if cmd.Flags().Changed("filter") {
inputFilters, err = cmd.Flags().GetStringSlice("filter")
if err != nil {
return types.ImageListOptions{}, err
return nil, err
}
}
digests, err := cmd.Flags().GetBool("digests")
if err != nil {
return types.ImageListOptions{}, err
return nil, err
}
names, err := cmd.Flags().GetBool("names")
if err != nil {
return types.ImageListOptions{}, err
return nil, err
}
return types.ImageListOptions{
return &types.ImageListOptions{
GOptions: globalOptions,
Quiet: quiet,
NoTrunc: noTrunc,
Expand Down
10 changes: 5 additions & 5 deletions pkg/cmd/builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"strconv"
"strings"

distributionref "github.com/distribution/reference"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"

containerd "github.com/containerd/containerd/v2/client"
Expand All @@ -42,6 +41,7 @@ import (
"github.com/containerd/nerdctl/v2/pkg/buildkitutil"
"github.com/containerd/nerdctl/v2/pkg/clientutil"
"github.com/containerd/nerdctl/v2/pkg/platformutil"
"github.com/containerd/nerdctl/v2/pkg/referenceutil"
"github.com/containerd/nerdctl/v2/pkg/strutil"
)

Expand Down Expand Up @@ -235,19 +235,19 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
}
if tags = strutil.DedupeStrSlice(options.Tag); len(tags) > 0 {
ref := tags[0]
named, err := distributionref.ParseNormalizedNamed(ref)
parsedReference, err := referenceutil.Parse(ref)
if err != nil {
return "", nil, false, "", nil, nil, err
}
output += ",name=" + distributionref.TagNameOnly(named).String()
output += ",name=" + parsedReference.String()

// pick the first tag and add it to output
for idx, tag := range tags {
named, err := distributionref.ParseNormalizedNamed(tag)
parsedReference, err = referenceutil.Parse(tag)
if err != nil {
return "", nil, false, "", nil, nil, err
}
tags[idx] = distributionref.TagNameOnly(named).String()
tags[idx] = parsedReference.String()
}
} else if len(tags) == 0 {
output = output + ",dangling-name-prefix=<none>"
Expand Down
14 changes: 9 additions & 5 deletions pkg/cmd/compose/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op
options.VolumeExists = volStore.Exists

options.ImageExists = func(ctx context.Context, rawRef string) (bool, error) {
refNamed, err := referenceutil.ParseAny(rawRef)
parsedReference, err := referenceutil.Parse(rawRef)
if err != nil {
return false, err
}
ref := refNamed.String()
ref := parsedReference.String()
if _, err := client.ImageService().Get(ctx, ref); err != nil {
if errors.Is(err, errdefs.ErrNotFound) {
return false, nil
Expand Down Expand Up @@ -133,8 +133,12 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op
Stderr: stderr,
}

// IPFS reference
if scheme, ref, err := referenceutil.ParseIPFSRefWithScheme(imageName); err == nil {
parsedReference, err := referenceutil.Parse(imageName)
if err != nil {
return err
}

if parsedReference.Protocol != "" {
var ipfsPath string
if ipfsAddress := options.IPFSAddress; ipfsAddress != "" {
dir, err := os.MkdirTemp("", "apidirtmp")
Expand All @@ -147,7 +151,7 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op
}
ipfsPath = dir
}
_, err = ipfs.EnsureImage(ctx, client, scheme, ref, ipfsPath, imgPullOpts)
_, err = ipfs.EnsureImage(ctx, client, string(parsedReference.Protocol), parsedReference.String(), ipfsPath, imgPullOpts)
return err
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/container/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (

// Commit will commit a container’s file changes or settings into a new image.
func Commit(ctx context.Context, client *containerd.Client, rawRef string, req string, options types.ContainerCommitOptions) error {
named, err := referenceutil.ParseDockerRef(rawRef)
parsedReference, err := referenceutil.Parse(rawRef)
if err != nil {
return err
}
Expand All @@ -46,7 +46,7 @@ func Commit(ctx context.Context, client *containerd.Client, rawRef string, req s
opts := &commit.Opts{
Author: options.Author,
Message: options.Message,
Ref: named.String(),
Ref: parsedReference.String(),
Pause: options.Pause,
Changes: changes,
}
Expand Down
7 changes: 6 additions & 1 deletion pkg/cmd/container/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,12 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa
if ensuredImage != nil {
imageRef = ensuredImage.Ref
}
options.Name = referenceutil.SuggestContainerName(imageRef, id)
parsedReference, err := referenceutil.Parse(imageRef)
// Ignore cases where the imageRef is ""
if err != nil && imageRef != "" {
return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err
}
options.Name = parsedReference.SuggestContainerName(id)
}
if options.Name != "" {
containerNameStore, err = namestore.New(dataStore, options.GOptions.Namespace)
Expand Down
8 changes: 4 additions & 4 deletions pkg/cmd/image/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,17 @@ func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRa
return errors.New("src and target image need to be specified")
}

srcNamed, err := referenceutil.ParseAny(srcRawRef)
parsedReference, err := referenceutil.Parse(srcRawRef)
if err != nil {
return err
}
srcRef := srcNamed.String()
srcRef := parsedReference.String()

targetNamed, err := referenceutil.ParseDockerRef(targetRawRef)
parsedReference, err = referenceutil.Parse(targetRawRef)
if err != nil {
return err
}
targetRef := targetNamed.String()
targetRef := parsedReference.String()

platMC, err := platformutil.NewMatchComparer(options.AllPlatforms, options.Platforms)
if err != nil {
Expand Down
8 changes: 4 additions & 4 deletions pkg/cmd/image/crypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,17 @@ func Crypt(ctx context.Context, client *containerd.Client, srcRawRef, targetRawR
return errors.New("src and target image need to be specified")
}

srcNamed, err := referenceutil.ParseAny(srcRawRef)
parsedRerefence, err := referenceutil.Parse(srcRawRef)
if err != nil {
return err
}
srcRef := srcNamed.String()
srcRef := parsedRerefence.String()

targetNamed, err := referenceutil.ParseDockerRef(targetRawRef)
parsedRerefence, err = referenceutil.Parse(targetRawRef)
if err != nil {
return err
}
targetRef := targetNamed.String()
targetRef := parsedRerefence.String()

platMC, err := platformutil.NewMatchComparer(options.AllPlatforms, options.Platforms)
if err != nil {
Expand Down
16 changes: 7 additions & 9 deletions pkg/cmd/image/ensure.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"net/http"
"os"

distributionref "github.com/distribution/reference"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"

containerd "github.com/containerd/containerd/v2/client"
Expand All @@ -35,6 +34,7 @@ import (
"github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver"
"github.com/containerd/nerdctl/v2/pkg/imgutil/fetch"
"github.com/containerd/nerdctl/v2/pkg/platformutil"
"github.com/containerd/nerdctl/v2/pkg/referenceutil"
)

func EnsureAllContent(ctx context.Context, client *containerd.Client, srcName string, options types.GlobalCommandOptions) error {
Expand All @@ -61,12 +61,10 @@ func EnsureAllContent(ctx context.Context, client *containerd.Client, srcName st
}

func ensureOne(ctx context.Context, client *containerd.Client, rawRef string, target ocispec.Descriptor, platform ocispec.Platform, options types.GlobalCommandOptions) error {

named, err := distributionref.ParseDockerRef(rawRef)
parsedReference, err := referenceutil.Parse(rawRef)
if err != nil {
return err
}
refDomain := distributionref.Domain(named)
// if platform == nil {
// platform = platforms.DefaultSpec()
//}
Expand All @@ -82,11 +80,11 @@ func ensureOne(ctx context.Context, client *containerd.Client, rawRef string, ta
// Get a resolver
var dOpts []dockerconfigresolver.Opt
if options.InsecureRegistry {
log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", refDomain)
log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", parsedReference.Domain)
dOpts = append(dOpts, dockerconfigresolver.WithSkipVerifyCerts(true))
}
dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(options.HostsDir))
resolver, err := dockerconfigresolver.New(ctx, refDomain, dOpts...)
resolver, err := dockerconfigresolver.New(ctx, parsedReference.Domain, dOpts...)
if err != nil {
return err
}
Expand All @@ -105,16 +103,16 @@ func ensureOne(ctx context.Context, client *containerd.Client, rawRef string, ta
return err
}
if options.InsecureRegistry {
log.G(ctx).WithError(err).Warnf("server %q does not seem to support HTTPS, falling back to plain HTTP", refDomain)
log.G(ctx).WithError(err).Warnf("server %q does not seem to support HTTPS, falling back to plain HTTP", parsedReference.Domain)
dOpts = append(dOpts, dockerconfigresolver.WithPlainHTTP(true))
resolver, err = dockerconfigresolver.New(ctx, refDomain, dOpts...)
resolver, err = dockerconfigresolver.New(ctx, parsedReference.Domain, dOpts...)
if err != nil {
return err
}
config.Resolver = resolver
return fetch.Fetch(ctx, client, rawRef, config)
}
log.G(ctx).WithError(err).Errorf("server %q does not seem to support HTTPS", refDomain)
log.G(ctx).WithError(err).Errorf("server %q does not seem to support HTTPS", parsedReference.Domain)
log.G(ctx).Info("Hint: you may want to try --insecure-registry to allow plain HTTP (if you are in a trusted network)")
}

Expand Down
44 changes: 20 additions & 24 deletions pkg/cmd/image/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import (
"strings"
"time"

"github.com/distribution/reference"

containerd "github.com/containerd/containerd/v2/client"
"github.com/containerd/containerd/v2/core/images"
"github.com/containerd/log"
Expand All @@ -39,22 +37,16 @@ import (

func inspectIdentifier(ctx context.Context, client *containerd.Client, identifier string) ([]images.Image, string, string, error) {
// Figure out what we have here - digest, tag, name
parsedIdentifier, err := referenceutil.ParseAnyReference(identifier)
parsedReference, err := referenceutil.Parse(identifier)
if err != nil {
return nil, "", "", fmt.Errorf("invalid identifier %s: %w", identifier, err)
return nil, "", "", err
}
digest := ""
if identifierDigest, hasDigest := parsedIdentifier.(reference.Digested); hasDigest {
digest = identifierDigest.Digest().String()
}
name := ""
if identifierName, hasName := parsedIdentifier.(reference.Named); hasName {
name = identifierName.Name()
}
tag := "latest"
if identifierTag, hasTag := parsedIdentifier.(reference.Tagged); hasTag && identifierTag.Tag() != "" {
tag = identifierTag.Tag()
if parsedReference.Digest != "" {
digest = parsedReference.Digest.String()
}
name := parsedReference.Name()
tag := parsedReference.Tag

// Initialize filters
var filters []string
Expand Down Expand Up @@ -136,26 +128,26 @@ func Inspect(ctx context.Context, client *containerd.Client, identifiers []strin
}

// If dockercompat: does the candidate have a name? Get it if so
candidateRef, err := referenceutil.ParseAnyReference(candidateNativeImage.Image.Name)
parsedReference, err := referenceutil.Parse(candidateNativeImage.Image.Name)
if err != nil {
log.G(ctx).WithError(err).WithField("name", candidateNativeImage.Image.Name).Error("the found image has an unparsable name")
continue
}
parsedCandidateNameTag, candidateHasAName := candidateRef.(reference.NamedTagged)

// If we were ALSO asked for a specific name on top of the digest, we need to make sure we keep only the image with that name
if requestedName != "" {
// If the candidate did not have a name, then we should ignore this one and continue
if !candidateHasAName {
if parsedReference.Name() == "" {
continue
}

// Otherwise, the candidate has a name. If it is the one we want, store it and continue, otherwise, fall through
candidateTag := parsedCandidateNameTag.Tag()
if candidateTag == "" {
candidateTag = "latest"
candidateTag := parsedReference.Tag
// If the name had a digest, an empty tag is not normalized to latest, so, account for that here
if requestedTag == "" {
requestedTag = "latest"
}
if parsedCandidateNameTag.Name() == requestedName && candidateTag == requestedTag {
if parsedReference.Name() == requestedName && candidateTag == requestedTag {
validatedImage, err = dockercompat.ImageFromNative(candidateNativeImage)
if err != nil {
log.G(ctx).WithError(err).WithField("name", candidateNativeImage.Image.Name).Error("could not get a docker compat version of the native image")
Expand All @@ -175,9 +167,13 @@ func Inspect(ctx context.Context, client *containerd.Client, identifiers []strin
// - we got a request by digest, but we already had the image stored
// - we got a request by name, and the name of the candidate did not match the requested name
// Now, check if the candidate has a name - if it does, populate repoTags and repoDigests
if candidateHasAName {
repoTags = append(repoTags, fmt.Sprintf("%s:%s", reference.FamiliarName(parsedCandidateNameTag), parsedCandidateNameTag.Tag()))
repoDigests = append(repoDigests, fmt.Sprintf("%s@%s", reference.FamiliarName(parsedCandidateNameTag), candidateImage.Target.Digest.String()))
if parsedReference.Name() != "" {
tag := parsedReference.Tag
if tag == "" {
tag = "latest"
}
repoTags = append(repoTags, fmt.Sprintf("%s:%s", parsedReference.FamiliarName(), tag))
repoDigests = append(repoDigests, fmt.Sprintf("%s@%s", parsedReference.FamiliarName(), candidateImage.Target.Digest.String()))
}
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/image/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import (
)

// ListCommandHandler `List` and print images matching filters in `options`.
func ListCommandHandler(ctx context.Context, client *containerd.Client, options types.ImageListOptions) error {
func ListCommandHandler(ctx context.Context, client *containerd.Client, options *types.ImageListOptions) error {
imageList, err := List(ctx, client, options.Filters, options.NameAndRefFilter)
if err != nil {
return err
Expand Down Expand Up @@ -126,7 +126,7 @@ type imagePrintable struct {
Platform string // nerdctl extension
}

func printImages(ctx context.Context, client *containerd.Client, imageList []images.Image, options types.ImageListOptions) error {
func printImages(ctx context.Context, client *containerd.Client, imageList []images.Image, options *types.ImageListOptions) error {
w := options.Stdout
digestsFlag := options.Digests
if options.Format == "wide" {
Expand Down
Loading

0 comments on commit f240e58

Please sign in to comment.