Skip to content

Commit 1fbd776

Browse files
fix: relax identifier limits
Signed-off-by: Shubharanshu Mahapatra <[email protected]>
1 parent ccf6830 commit 1fbd776

File tree

8 files changed

+76
-30
lines changed

8 files changed

+76
-30
lines changed

cmd/nerdctl/network_create.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ import (
2121

2222
"github.com/spf13/cobra"
2323

24-
"github.com/containerd/containerd/v2/pkg/identifiers"
25-
2624
"github.com/containerd/nerdctl/v2/pkg/api/types"
2725
"github.com/containerd/nerdctl/v2/pkg/cmd/network"
26+
"github.com/containerd/nerdctl/v2/pkg/identifiers"
2827
"github.com/containerd/nerdctl/v2/pkg/strutil"
2928
)
3029

@@ -58,8 +57,8 @@ func networkCreateAction(cmd *cobra.Command, args []string) error {
5857
return err
5958
}
6059
name := args[0]
61-
if err := identifiers.Validate(name); err != nil {
62-
return fmt.Errorf("malformed name %s: %w", name, err)
60+
if err := identifiers.ValidateDockerCompat(name); err != nil {
61+
return fmt.Errorf("invalid network name: %w", err)
6362
}
6463
driver, err := cmd.Flags().GetString("driver")
6564
if err != nil {

pkg/composer/composer.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ import (
2727
compose "github.com/compose-spec/compose-go/v2/types"
2828

2929
containerd "github.com/containerd/containerd/v2/client"
30-
"github.com/containerd/containerd/v2/pkg/identifiers"
3130
"github.com/containerd/log"
3231

3332
"github.com/containerd/nerdctl/v2/pkg/composer/serviceparser"
33+
"github.com/containerd/nerdctl/v2/pkg/identifiers"
3434
"github.com/containerd/nerdctl/v2/pkg/reflectutil"
3535
)
3636

@@ -63,8 +63,8 @@ func New(o Options, client *containerd.Client) (*Composer, error) {
6363
}
6464

6565
if o.Project != "" {
66-
if err := identifiers.Validate(o.Project); err != nil {
67-
return nil, fmt.Errorf("got invalid project name %q: %w", o.Project, err)
66+
if err := identifiers.ValidateDockerCompat(o.Project); err != nil {
67+
return nil, fmt.Errorf("invalid project name: %w", err)
6868
}
6969
}
7070

pkg/composer/serviceparser/build.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ import (
2525
"github.com/compose-spec/compose-go/v2/types"
2626
securejoin "github.com/cyphar/filepath-securejoin"
2727

28-
"github.com/containerd/containerd/v2/pkg/identifiers"
2928
"github.com/containerd/errdefs"
3029
"github.com/containerd/log"
3130

31+
"github.com/containerd/nerdctl/v2/pkg/identifiers"
3232
"github.com/containerd/nerdctl/v2/pkg/reflectutil"
3333
)
3434

@@ -84,9 +84,11 @@ func parseBuildConfig(c *types.BuildConfig, project *types.Project, imageName st
8484

8585
for _, s := range c.Secrets {
8686
fileRef := types.FileReferenceConfig(s)
87-
if err := identifiers.Validate(fileRef.Source); err != nil {
88-
return nil, fmt.Errorf("secret source %q is invalid: %w", fileRef.Source, err)
87+
88+
if err := identifiers.ValidateDockerCompat(fileRef.Source); err != nil {
89+
return nil, fmt.Errorf("invalid secret source name: %w", err)
8990
}
91+
9092
projectSecret, ok := project.Secrets[fileRef.Source]
9193
if !ok {
9294
return nil, fmt.Errorf("build: secret %s is undefined", fileRef.Source)

pkg/composer/serviceparser/serviceparser.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ import (
3131
"github.com/compose-spec/compose-go/v2/types"
3232

3333
"github.com/containerd/containerd/v2/contrib/nvidia"
34-
"github.com/containerd/containerd/v2/pkg/identifiers"
3534
"github.com/containerd/log"
3635

36+
"github.com/containerd/nerdctl/v2/pkg/identifiers"
3737
"github.com/containerd/nerdctl/v2/pkg/reflectutil"
3838
)
3939

@@ -851,8 +851,8 @@ func fileReferenceConfigToFlagV(c types.FileReferenceConfig, project *types.Proj
851851
log.L.Warnf("Ignoring: %s: %+v", objType, unknown)
852852
}
853853

854-
if err := identifiers.Validate(c.Source); err != nil {
855-
return "", fmt.Errorf("%s source %q is invalid: %w", objType, c.Source, err)
854+
if err := identifiers.ValidateDockerCompat(c.Source); err != nil {
855+
return "", fmt.Errorf("invalid source name for %s: %w", objType, err)
856856
}
857857

858858
var obj types.FileObjectConfig

pkg/identifiers/validate.go

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package identifiers implements functions for docker compatible identifier validation.
18+
package identifiers
19+
20+
import (
21+
"fmt"
22+
"regexp"
23+
24+
"github.com/containerd/errdefs"
25+
)
26+
27+
const AllowedIdentfierChars = `[a-zA-Z0-9][a-zA-Z0-9_.-]`
28+
29+
var AllowedIdentifierPattern = regexp.MustCompile(`^` + AllowedIdentfierChars + `+$`)
30+
31+
// ValidateDockerCompat implements docker compatible identifier validation.
32+
// The containerd implementation allows single character identifiers, while the
33+
// Docker compatible implementation requires at least 2 characters for identifiers.
34+
// The containerd implementation enforces a maximum length constraint of 76 characters,
35+
// while the Docker compatible implementation omits the length check entirely.
36+
func ValidateDockerCompat(s string) error {
37+
if len(s) == 0 {
38+
return fmt.Errorf("identifier must not be empty %w", errdefs.ErrInvalidArgument)
39+
}
40+
41+
if !AllowedIdentifierPattern.MatchString(s) {
42+
return fmt.Errorf("identifier %q must match pattern %q: %w", s, AllowedIdentfierChars, errdefs.ErrInvalidArgument)
43+
}
44+
return nil
45+
}

pkg/mountutil/mountutil.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ import (
2626
"github.com/moby/sys/userns"
2727
"github.com/opencontainers/runtime-spec/specs-go"
2828

29-
"github.com/containerd/containerd/v2/pkg/identifiers"
3029
"github.com/containerd/containerd/v2/pkg/oci"
3130
"github.com/containerd/log"
3231

32+
"github.com/containerd/nerdctl/v2/pkg/identifiers"
3333
"github.com/containerd/nerdctl/v2/pkg/idgen"
3434
"github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore"
3535
"github.com/containerd/nerdctl/v2/pkg/strutil"
@@ -260,7 +260,7 @@ func createDirOnHost(src string, createDir bool) error {
260260
}
261261

262262
func isNamedVolume(s string) bool {
263-
err := identifiers.Validate(s)
263+
err := identifiers.ValidateDockerCompat(s)
264264

265265
// If the volume name is invalid, we assume it is a path
266266
return err == nil

pkg/mountutil/volumestore/volumestore.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ import (
2323
"os"
2424
"path/filepath"
2525

26-
"github.com/containerd/containerd/v2/pkg/identifiers"
2726
"github.com/containerd/errdefs"
2827
"github.com/containerd/log"
2928

29+
"github.com/containerd/nerdctl/v2/pkg/identifiers"
3030
"github.com/containerd/nerdctl/v2/pkg/inspecttypes/native"
3131
"github.com/containerd/nerdctl/v2/pkg/lockutil"
3232
"github.com/containerd/nerdctl/v2/pkg/strutil"
@@ -109,9 +109,10 @@ func (vs *volumeStore) Unlock() error {
109109
// Create will create a new volume, or return an existing one if there is one already by that name
110110
// Besides a possible locking error, it might return ErrInvalidArgument, hard filesystem errors, json errors
111111
func (vs *volumeStore) Create(name string, labels []string) (*native.Volume, error) {
112-
if err := identifiers.Validate(name); err != nil {
113-
return nil, fmt.Errorf("malformed volume name: %w (%w)", err, errdefs.ErrInvalidArgument)
112+
if err := identifiers.ValidateDockerCompat(name); err != nil {
113+
return nil, fmt.Errorf("invalid volume name: %w", err)
114114
}
115+
115116
volPath := filepath.Join(vs.dir, name)
116117
volDataPath := filepath.Join(volPath, dataDirName)
117118
volFilePath := filepath.Join(volPath, volumeJSONFileName)
@@ -178,8 +179,8 @@ func (vs *volumeStore) Create(name string, labels []string) (*native.Volume, err
178179
// Get retrieves a native volume from the store
179180
// Besides a possible locking error, it might return ErrInvalidArgument, ErrNotFound, or a filesystem error
180181
func (vs *volumeStore) Get(name string, size bool) (*native.Volume, error) {
181-
if err := identifiers.Validate(name); err != nil {
182-
return nil, fmt.Errorf("malformed volume name %q: %w", name, err)
182+
if err := identifiers.ValidateDockerCompat(name); err != nil {
183+
return nil, fmt.Errorf("invalid volume name: %w", err)
183184
}
184185
volPath := filepath.Join(vs.dir, name)
185186
volDataPath := filepath.Join(volPath, dataDirName)
@@ -274,8 +275,8 @@ func (vs *volumeStore) Remove(names []string) (removed []string, warns []error,
274275
fn := func() error {
275276
for _, name := range names {
276277
// Invalid name, soft error
277-
if err := identifiers.Validate(name); err != nil {
278-
warns = append(warns, fmt.Errorf("malformed volume name: %w (%w)", err, errdefs.ErrInvalidArgument))
278+
if err := identifiers.ValidateDockerCompat(name); err != nil {
279+
warns = append(warns, fmt.Errorf("invalid volume name: %w", err))
279280
continue
280281
}
281282
dir := filepath.Join(vs.dir, name)

pkg/namestore/namestore.go

+7-8
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ import (
2222
"path/filepath"
2323
"strings"
2424

25-
"github.com/containerd/containerd/v2/pkg/identifiers"
26-
25+
"github.com/containerd/nerdctl/v2/pkg/identifiers"
2726
"github.com/containerd/nerdctl/v2/pkg/lockutil"
2827
)
2928

@@ -49,8 +48,8 @@ type nameStore struct {
4948
}
5049

5150
func (x *nameStore) Acquire(name, id string) error {
52-
if err := identifiers.Validate(name); err != nil {
53-
return fmt.Errorf("invalid name %q: %w", name, err)
51+
if err := identifiers.ValidateDockerCompat(name); err != nil {
52+
return fmt.Errorf("invalid name: %w", err)
5453
}
5554
if strings.TrimSpace(id) != id {
5655
return fmt.Errorf("untrimmed ID %q", id)
@@ -69,8 +68,8 @@ func (x *nameStore) Release(name, id string) error {
6968
if name == "" {
7069
return nil
7170
}
72-
if err := identifiers.Validate(name); err != nil {
73-
return fmt.Errorf("invalid name %q: %w", name, err)
71+
if err := identifiers.ValidateDockerCompat(name); err != nil {
72+
return fmt.Errorf("invalid name: %w", err)
7473
}
7574
if strings.TrimSpace(id) != id {
7675
return fmt.Errorf("untrimmed ID %q", id)
@@ -96,8 +95,8 @@ func (x *nameStore) Rename(oldName, id, newName string) error {
9695
if oldName == "" || newName == "" {
9796
return nil
9897
}
99-
if err := identifiers.Validate(newName); err != nil {
100-
return fmt.Errorf("invalid name %q: %w", oldName, err)
98+
if err := identifiers.ValidateDockerCompat(newName); err != nil {
99+
return fmt.Errorf("invalid name %q: %w", newName, err)
101100
}
102101
fn := func() error {
103102
oldFileName := filepath.Join(x.dir, oldName)

0 commit comments

Comments
 (0)