Skip to content

Commit f240e58

Browse files
authored
Merge pull request #3542 from apostasie/rewrite-refutils
`referenceutil` cleanup
2 parents 1122644 + efb9a87 commit f240e58

File tree

18 files changed

+502
-200
lines changed

18 files changed

+502
-200
lines changed

cmd/nerdctl/image/image_list.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,49 +70,47 @@ Properties:
7070
return imagesCommand
7171
}
7272

73-
func processImageListOptions(cmd *cobra.Command, args []string) (types.ImageListOptions, error) {
73+
func processImageListOptions(cmd *cobra.Command, args []string) (*types.ImageListOptions, error) {
7474
globalOptions, err := helpers.ProcessRootCmdFlags(cmd)
7575
if err != nil {
76-
return types.ImageListOptions{}, err
76+
return nil, err
7777
}
7878
var filters []string
79-
8079
if len(args) > 0 {
81-
canonicalRef, err := referenceutil.ParseAny(args[0])
80+
parsedReference, err := referenceutil.Parse(args[0])
8281
if err != nil {
83-
return types.ImageListOptions{}, err
82+
return nil, err
8483
}
85-
filters = append(filters, fmt.Sprintf("name==%s", canonicalRef.String()))
86-
filters = append(filters, fmt.Sprintf("name==%s", args[0]))
84+
filters = []string{fmt.Sprintf("name==%s", parsedReference)}
8785
}
8886
quiet, err := cmd.Flags().GetBool("quiet")
8987
if err != nil {
90-
return types.ImageListOptions{}, err
88+
return nil, err
9189
}
9290
noTrunc, err := cmd.Flags().GetBool("no-trunc")
9391
if err != nil {
94-
return types.ImageListOptions{}, err
92+
return nil, err
9593
}
9694
format, err := cmd.Flags().GetString("format")
9795
if err != nil {
98-
return types.ImageListOptions{}, err
96+
return nil, err
9997
}
10098
var inputFilters []string
10199
if cmd.Flags().Changed("filter") {
102100
inputFilters, err = cmd.Flags().GetStringSlice("filter")
103101
if err != nil {
104-
return types.ImageListOptions{}, err
102+
return nil, err
105103
}
106104
}
107105
digests, err := cmd.Flags().GetBool("digests")
108106
if err != nil {
109-
return types.ImageListOptions{}, err
107+
return nil, err
110108
}
111109
names, err := cmd.Flags().GetBool("names")
112110
if err != nil {
113-
return types.ImageListOptions{}, err
111+
return nil, err
114112
}
115-
return types.ImageListOptions{
113+
return &types.ImageListOptions{
116114
GOptions: globalOptions,
117115
Quiet: quiet,
118116
NoTrunc: noTrunc,

pkg/cmd/builder/build.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import (
2828
"strconv"
2929
"strings"
3030

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

3433
containerd "github.com/containerd/containerd/v2/client"
@@ -42,6 +41,7 @@ import (
4241
"github.com/containerd/nerdctl/v2/pkg/buildkitutil"
4342
"github.com/containerd/nerdctl/v2/pkg/clientutil"
4443
"github.com/containerd/nerdctl/v2/pkg/platformutil"
44+
"github.com/containerd/nerdctl/v2/pkg/referenceutil"
4545
"github.com/containerd/nerdctl/v2/pkg/strutil"
4646
)
4747

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

244244
// pick the first tag and add it to output
245245
for idx, tag := range tags {
246-
named, err := distributionref.ParseNormalizedNamed(tag)
246+
parsedReference, err = referenceutil.Parse(tag)
247247
if err != nil {
248248
return "", nil, false, "", nil, nil, err
249249
}
250-
tags[idx] = distributionref.TagNameOnly(named).String()
250+
tags[idx] = parsedReference.String()
251251
}
252252
} else if len(tags) == 0 {
253253
output = output + ",dangling-name-prefix=<none>"

pkg/cmd/compose/compose.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op
9898
options.VolumeExists = volStore.Exists
9999

100100
options.ImageExists = func(ctx context.Context, rawRef string) (bool, error) {
101-
refNamed, err := referenceutil.ParseAny(rawRef)
101+
parsedReference, err := referenceutil.Parse(rawRef)
102102
if err != nil {
103103
return false, err
104104
}
105-
ref := refNamed.String()
105+
ref := parsedReference.String()
106106
if _, err := client.ImageService().Get(ctx, ref); err != nil {
107107
if errors.Is(err, errdefs.ErrNotFound) {
108108
return false, nil
@@ -133,8 +133,12 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op
133133
Stderr: stderr,
134134
}
135135

136-
// IPFS reference
137-
if scheme, ref, err := referenceutil.ParseIPFSRefWithScheme(imageName); err == nil {
136+
parsedReference, err := referenceutil.Parse(imageName)
137+
if err != nil {
138+
return err
139+
}
140+
141+
if parsedReference.Protocol != "" {
138142
var ipfsPath string
139143
if ipfsAddress := options.IPFSAddress; ipfsAddress != "" {
140144
dir, err := os.MkdirTemp("", "apidirtmp")
@@ -147,7 +151,7 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op
147151
}
148152
ipfsPath = dir
149153
}
150-
_, err = ipfs.EnsureImage(ctx, client, scheme, ref, ipfsPath, imgPullOpts)
154+
_, err = ipfs.EnsureImage(ctx, client, string(parsedReference.Protocol), parsedReference.String(), ipfsPath, imgPullOpts)
151155
return err
152156
}
153157

pkg/cmd/container/commit.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import (
3333

3434
// Commit will commit a container’s file changes or settings into a new image.
3535
func Commit(ctx context.Context, client *containerd.Client, rawRef string, req string, options types.ContainerCommitOptions) error {
36-
named, err := referenceutil.ParseDockerRef(rawRef)
36+
parsedReference, err := referenceutil.Parse(rawRef)
3737
if err != nil {
3838
return err
3939
}
@@ -46,7 +46,7 @@ func Commit(ctx context.Context, client *containerd.Client, rawRef string, req s
4646
opts := &commit.Opts{
4747
Author: options.Author,
4848
Message: options.Message,
49-
Ref: named.String(),
49+
Ref: parsedReference.String(),
5050
Pause: options.Pause,
5151
Changes: changes,
5252
}

pkg/cmd/container/create.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,12 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa
271271
if ensuredImage != nil {
272272
imageRef = ensuredImage.Ref
273273
}
274-
options.Name = referenceutil.SuggestContainerName(imageRef, id)
274+
parsedReference, err := referenceutil.Parse(imageRef)
275+
// Ignore cases where the imageRef is ""
276+
if err != nil && imageRef != "" {
277+
return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err
278+
}
279+
options.Name = parsedReference.SuggestContainerName(id)
275280
}
276281
if options.Name != "" {
277282
containerNameStore, err = namestore.New(dataStore, options.GOptions.Namespace)

pkg/cmd/image/convert.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,17 @@ func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRa
5757
return errors.New("src and target image need to be specified")
5858
}
5959

60-
srcNamed, err := referenceutil.ParseAny(srcRawRef)
60+
parsedReference, err := referenceutil.Parse(srcRawRef)
6161
if err != nil {
6262
return err
6363
}
64-
srcRef := srcNamed.String()
64+
srcRef := parsedReference.String()
6565

66-
targetNamed, err := referenceutil.ParseDockerRef(targetRawRef)
66+
parsedReference, err = referenceutil.Parse(targetRawRef)
6767
if err != nil {
6868
return err
6969
}
70-
targetRef := targetNamed.String()
70+
targetRef := parsedReference.String()
7171

7272
platMC, err := platformutil.NewMatchComparer(options.AllPlatforms, options.Platforms)
7373
if err != nil {

pkg/cmd/image/crypt.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,17 @@ func Crypt(ctx context.Context, client *containerd.Client, srcRawRef, targetRawR
4040
return errors.New("src and target image need to be specified")
4141
}
4242

43-
srcNamed, err := referenceutil.ParseAny(srcRawRef)
43+
parsedRerefence, err := referenceutil.Parse(srcRawRef)
4444
if err != nil {
4545
return err
4646
}
47-
srcRef := srcNamed.String()
47+
srcRef := parsedRerefence.String()
4848

49-
targetNamed, err := referenceutil.ParseDockerRef(targetRawRef)
49+
parsedRerefence, err = referenceutil.Parse(targetRawRef)
5050
if err != nil {
5151
return err
5252
}
53-
targetRef := targetNamed.String()
53+
targetRef := parsedRerefence.String()
5454

5555
platMC, err := platformutil.NewMatchComparer(options.AllPlatforms, options.Platforms)
5656
if err != nil {

pkg/cmd/image/ensure.go

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"net/http"
2323
"os"
2424

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

2827
containerd "github.com/containerd/containerd/v2/client"
@@ -35,6 +34,7 @@ import (
3534
"github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver"
3635
"github.com/containerd/nerdctl/v2/pkg/imgutil/fetch"
3736
"github.com/containerd/nerdctl/v2/pkg/platformutil"
37+
"github.com/containerd/nerdctl/v2/pkg/referenceutil"
3838
)
3939

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

6363
func ensureOne(ctx context.Context, client *containerd.Client, rawRef string, target ocispec.Descriptor, platform ocispec.Platform, options types.GlobalCommandOptions) error {
64-
65-
named, err := distributionref.ParseDockerRef(rawRef)
64+
parsedReference, err := referenceutil.Parse(rawRef)
6665
if err != nil {
6766
return err
6867
}
69-
refDomain := distributionref.Domain(named)
7068
// if platform == nil {
7169
// platform = platforms.DefaultSpec()
7270
//}
@@ -82,11 +80,11 @@ func ensureOne(ctx context.Context, client *containerd.Client, rawRef string, ta
8280
// Get a resolver
8381
var dOpts []dockerconfigresolver.Opt
8482
if options.InsecureRegistry {
85-
log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", refDomain)
83+
log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", parsedReference.Domain)
8684
dOpts = append(dOpts, dockerconfigresolver.WithSkipVerifyCerts(true))
8785
}
8886
dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(options.HostsDir))
89-
resolver, err := dockerconfigresolver.New(ctx, refDomain, dOpts...)
87+
resolver, err := dockerconfigresolver.New(ctx, parsedReference.Domain, dOpts...)
9088
if err != nil {
9189
return err
9290
}
@@ -105,16 +103,16 @@ func ensureOne(ctx context.Context, client *containerd.Client, rawRef string, ta
105103
return err
106104
}
107105
if options.InsecureRegistry {
108-
log.G(ctx).WithError(err).Warnf("server %q does not seem to support HTTPS, falling back to plain HTTP", refDomain)
106+
log.G(ctx).WithError(err).Warnf("server %q does not seem to support HTTPS, falling back to plain HTTP", parsedReference.Domain)
109107
dOpts = append(dOpts, dockerconfigresolver.WithPlainHTTP(true))
110-
resolver, err = dockerconfigresolver.New(ctx, refDomain, dOpts...)
108+
resolver, err = dockerconfigresolver.New(ctx, parsedReference.Domain, dOpts...)
111109
if err != nil {
112110
return err
113111
}
114112
config.Resolver = resolver
115113
return fetch.Fetch(ctx, client, rawRef, config)
116114
}
117-
log.G(ctx).WithError(err).Errorf("server %q does not seem to support HTTPS", refDomain)
115+
log.G(ctx).WithError(err).Errorf("server %q does not seem to support HTTPS", parsedReference.Domain)
118116
log.G(ctx).Info("Hint: you may want to try --insecure-registry to allow plain HTTP (if you are in a trusted network)")
119117
}
120118

pkg/cmd/image/inspect.go

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ import (
2323
"strings"
2424
"time"
2525

26-
"github.com/distribution/reference"
27-
2826
containerd "github.com/containerd/containerd/v2/client"
2927
"github.com/containerd/containerd/v2/core/images"
3028
"github.com/containerd/log"
@@ -39,22 +37,16 @@ import (
3937

4038
func inspectIdentifier(ctx context.Context, client *containerd.Client, identifier string) ([]images.Image, string, string, error) {
4139
// Figure out what we have here - digest, tag, name
42-
parsedIdentifier, err := referenceutil.ParseAnyReference(identifier)
40+
parsedReference, err := referenceutil.Parse(identifier)
4341
if err != nil {
44-
return nil, "", "", fmt.Errorf("invalid identifier %s: %w", identifier, err)
42+
return nil, "", "", err
4543
}
4644
digest := ""
47-
if identifierDigest, hasDigest := parsedIdentifier.(reference.Digested); hasDigest {
48-
digest = identifierDigest.Digest().String()
49-
}
50-
name := ""
51-
if identifierName, hasName := parsedIdentifier.(reference.Named); hasName {
52-
name = identifierName.Name()
53-
}
54-
tag := "latest"
55-
if identifierTag, hasTag := parsedIdentifier.(reference.Tagged); hasTag && identifierTag.Tag() != "" {
56-
tag = identifierTag.Tag()
45+
if parsedReference.Digest != "" {
46+
digest = parsedReference.Digest.String()
5747
}
48+
name := parsedReference.Name()
49+
tag := parsedReference.Tag
5850

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

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

146137
// 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
147138
if requestedName != "" {
148139
// If the candidate did not have a name, then we should ignore this one and continue
149-
if !candidateHasAName {
140+
if parsedReference.Name() == "" {
150141
continue
151142
}
152143

153144
// Otherwise, the candidate has a name. If it is the one we want, store it and continue, otherwise, fall through
154-
candidateTag := parsedCandidateNameTag.Tag()
155-
if candidateTag == "" {
156-
candidateTag = "latest"
145+
candidateTag := parsedReference.Tag
146+
// If the name had a digest, an empty tag is not normalized to latest, so, account for that here
147+
if requestedTag == "" {
148+
requestedTag = "latest"
157149
}
158-
if parsedCandidateNameTag.Name() == requestedName && candidateTag == requestedTag {
150+
if parsedReference.Name() == requestedName && candidateTag == requestedTag {
159151
validatedImage, err = dockercompat.ImageFromNative(candidateNativeImage)
160152
if err != nil {
161153
log.G(ctx).WithError(err).WithField("name", candidateNativeImage.Image.Name).Error("could not get a docker compat version of the native image")
@@ -175,9 +167,13 @@ func Inspect(ctx context.Context, client *containerd.Client, identifiers []strin
175167
// - we got a request by digest, but we already had the image stored
176168
// - we got a request by name, and the name of the candidate did not match the requested name
177169
// Now, check if the candidate has a name - if it does, populate repoTags and repoDigests
178-
if candidateHasAName {
179-
repoTags = append(repoTags, fmt.Sprintf("%s:%s", reference.FamiliarName(parsedCandidateNameTag), parsedCandidateNameTag.Tag()))
180-
repoDigests = append(repoDigests, fmt.Sprintf("%s@%s", reference.FamiliarName(parsedCandidateNameTag), candidateImage.Target.Digest.String()))
170+
if parsedReference.Name() != "" {
171+
tag := parsedReference.Tag
172+
if tag == "" {
173+
tag = "latest"
174+
}
175+
repoTags = append(repoTags, fmt.Sprintf("%s:%s", parsedReference.FamiliarName(), tag))
176+
repoDigests = append(repoDigests, fmt.Sprintf("%s@%s", parsedReference.FamiliarName(), candidateImage.Target.Digest.String()))
181177
}
182178
}
183179

pkg/cmd/image/list.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ import (
4747
)
4848

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

129-
func printImages(ctx context.Context, client *containerd.Client, imageList []images.Image, options types.ImageListOptions) error {
129+
func printImages(ctx context.Context, client *containerd.Client, imageList []images.Image, options *types.ImageListOptions) error {
130130
w := options.Stdout
131131
digestsFlag := options.Digests
132132
if options.Format == "wide" {

0 commit comments

Comments
 (0)