The stringid package is used in many places; while it's trivial
to implement a similar utility, let's just provide it as a utility
package in the client, removing the daemon-specific logic.
For integration tests, I opted to use the implementation in the
client, as those should not ideally not make assumptions about
the daemon implementation.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,47 @@ |
| 0 |
+// Package stringid provides helper functions for dealing with string identifiers. |
|
| 1 |
+// |
|
| 2 |
+// It is similar to the package used by the daemon, but for presentational |
|
| 3 |
+// purposes in the client. |
|
| 4 |
+package stringid |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "crypto/rand" |
|
| 8 |
+ "encoding/hex" |
|
| 9 |
+ "strings" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+const ( |
|
| 13 |
+ shortLen = 12 |
|
| 14 |
+ fullLen = 64 |
|
| 15 |
+) |
|
| 16 |
+ |
|
| 17 |
+// TruncateID returns a shorthand version of a string identifier for presentation. |
|
| 18 |
+// For convenience, it accepts both digests ("sha256:xxxx") and IDs without an
|
|
| 19 |
+// algorithm prefix. It truncates the algorithm (if any) before truncating the |
|
| 20 |
+// ID. The length of the truncated ID is currently fixed, but users should make |
|
| 21 |
+// no assumptions of this to not change; it is merely a prefix of the ID that |
|
| 22 |
+// provides enough uniqueness for common scenarios. |
|
| 23 |
+// |
|
| 24 |
+// Truncated IDs ("ID-prefixes") usually can be used to uniquely identify an
|
|
| 25 |
+// object (such as a container or network), but collisions may happen, in |
|
| 26 |
+// which case an "ambiguous result" error is produced. In case of a collision, |
|
| 27 |
+// the caller should try with a longer prefix or the full-length ID. |
|
| 28 |
+func TruncateID(id string) string {
|
|
| 29 |
+ if i := strings.IndexRune(id, ':'); i >= 0 {
|
|
| 30 |
+ id = id[i+1:] |
|
| 31 |
+ } |
|
| 32 |
+ if len(id) > shortLen {
|
|
| 33 |
+ id = id[:shortLen] |
|
| 34 |
+ } |
|
| 35 |
+ return id |
|
| 36 |
+} |
|
| 37 |
+ |
|
| 38 |
+// GenerateRandomID returns a unique, 64-character ID consisting of a-z, 0-9. |
|
| 39 |
+func GenerateRandomID() string {
|
|
| 40 |
+ b := make([]byte, 32) |
|
| 41 |
+ if _, err := rand.Read(b); err != nil {
|
|
| 42 |
+ panic(err) // This shouldn't happen |
|
| 43 |
+ } |
|
| 44 |
+ id := hex.EncodeToString(b) |
|
| 45 |
+ return id |
|
| 46 |
+} |
| 0 | 47 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,54 @@ |
| 0 |
+package stringid |
|
| 1 |
+ |
|
| 2 |
+import "testing" |
|
| 3 |
+ |
|
| 4 |
+func TestGenerateRandomID(t *testing.T) {
|
|
| 5 |
+ id := GenerateRandomID() |
|
| 6 |
+ |
|
| 7 |
+ if len(id) != fullLen {
|
|
| 8 |
+ t.Fatalf("Id returned is incorrect: %s", id)
|
|
| 9 |
+ } |
|
| 10 |
+} |
|
| 11 |
+ |
|
| 12 |
+func TestTruncateID(t *testing.T) {
|
|
| 13 |
+ tests := []struct {
|
|
| 14 |
+ doc, id, expected string |
|
| 15 |
+ }{
|
|
| 16 |
+ {
|
|
| 17 |
+ doc: "empty ID", |
|
| 18 |
+ id: "", |
|
| 19 |
+ expected: "", |
|
| 20 |
+ }, |
|
| 21 |
+ {
|
|
| 22 |
+ // IDs are expected to be 12 (short) or 64 characters, and not be numeric only, |
|
| 23 |
+ // but TruncateID should handle these gracefully. |
|
| 24 |
+ doc: "invalid ID", |
|
| 25 |
+ id: "1234", |
|
| 26 |
+ expected: "1234", |
|
| 27 |
+ }, |
|
| 28 |
+ {
|
|
| 29 |
+ doc: "full ID", |
|
| 30 |
+ id: "90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2", |
|
| 31 |
+ expected: "90435eec5c4e", |
|
| 32 |
+ }, |
|
| 33 |
+ {
|
|
| 34 |
+ doc: "digest", |
|
| 35 |
+ id: "sha256:90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2", |
|
| 36 |
+ expected: "90435eec5c4e", |
|
| 37 |
+ }, |
|
| 38 |
+ {
|
|
| 39 |
+ doc: "very long ID", |
|
| 40 |
+ id: "90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a290435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2", |
|
| 41 |
+ expected: "90435eec5c4e", |
|
| 42 |
+ }, |
|
| 43 |
+ } |
|
| 44 |
+ |
|
| 45 |
+ for _, tc := range tests {
|
|
| 46 |
+ t.Run(tc.doc, func(t *testing.T) {
|
|
| 47 |
+ actual := TruncateID(tc.id) |
|
| 48 |
+ if actual != tc.expected {
|
|
| 49 |
+ t.Errorf("expected: %q, got: %q", tc.expected, actual)
|
|
| 50 |
+ } |
|
| 51 |
+ }) |
|
| 52 |
+ } |
|
| 53 |
+} |
| ... | ... |
@@ -10,7 +10,7 @@ import ( |
| 10 | 10 |
daemonevents "github.com/docker/docker/daemon/events" |
| 11 | 11 |
buildkit "github.com/docker/docker/daemon/internal/builder-next" |
| 12 | 12 |
"github.com/docker/docker/daemon/internal/image" |
| 13 |
- "github.com/docker/docker/pkg/stringid" |
|
| 13 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 14 | 14 |
"github.com/moby/moby/api/types/backend" |
| 15 | 15 |
"github.com/moby/moby/api/types/build" |
| 16 | 16 |
"github.com/moby/moby/api/types/events" |
| ... | ... |
@@ -12,8 +12,8 @@ import ( |
| 12 | 12 |
"github.com/containerd/platforms" |
| 13 | 13 |
"github.com/docker/docker/daemon/builder" |
| 14 | 14 |
"github.com/docker/docker/daemon/builder/remotecontext" |
| 15 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 15 | 16 |
"github.com/docker/docker/errdefs" |
| 16 |
- "github.com/docker/docker/pkg/stringid" |
|
| 17 | 17 |
"github.com/moby/buildkit/frontend/dockerfile/instructions" |
| 18 | 18 |
"github.com/moby/buildkit/frontend/dockerfile/parser" |
| 19 | 19 |
"github.com/moby/buildkit/frontend/dockerfile/shell" |
| ... | ... |
@@ -8,7 +8,7 @@ import ( |
| 8 | 8 |
cerrdefs "github.com/containerd/errdefs" |
| 9 | 9 |
"github.com/containerd/log" |
| 10 | 10 |
"github.com/docker/docker/daemon/builder" |
| 11 |
- "github.com/docker/docker/pkg/stringid" |
|
| 11 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 12 | 12 |
"github.com/moby/moby/api/types/backend" |
| 13 | 13 |
"github.com/moby/moby/api/types/container" |
| 14 | 14 |
"github.com/pkg/errors" |
| ... | ... |
@@ -14,8 +14,8 @@ import ( |
| 14 | 14 |
"github.com/containerd/platforms" |
| 15 | 15 |
"github.com/docker/docker/daemon/builder" |
| 16 | 16 |
"github.com/docker/docker/daemon/internal/image" |
| 17 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 17 | 18 |
networkSettings "github.com/docker/docker/daemon/network" |
| 18 |
- "github.com/docker/docker/pkg/stringid" |
|
| 19 | 19 |
"github.com/docker/go-connections/nat" |
| 20 | 20 |
"github.com/moby/go-archive" |
| 21 | 21 |
"github.com/moby/go-archive/chrootarchive" |
| ... | ... |
@@ -9,7 +9,7 @@ import ( |
| 9 | 9 |
"github.com/containerd/log" |
| 10 | 10 |
"github.com/docker/docker/daemon/internal/libcontainerd/types" |
| 11 | 11 |
"github.com/docker/docker/daemon/internal/stream" |
| 12 |
- "github.com/docker/docker/pkg/stringid" |
|
| 12 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 13 | 13 |
) |
| 14 | 14 |
|
| 15 | 15 |
// ExecConfig holds the configurations for execs. The Daemon keeps |
| ... | ... |
@@ -8,7 +8,7 @@ import ( |
| 8 | 8 |
"testing" |
| 9 | 9 |
|
| 10 | 10 |
cerrdefs "github.com/containerd/errdefs" |
| 11 |
- "github.com/docker/docker/pkg/stringid" |
|
| 11 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 12 | 12 |
"github.com/google/uuid" |
| 13 | 13 |
"github.com/moby/moby/api/types/container" |
| 14 | 14 |
"gotest.tools/v3/assert" |
| ... | ... |
@@ -20,6 +20,7 @@ import ( |
| 20 | 20 |
"github.com/docker/docker/daemon/internal/metrics" |
| 21 | 21 |
"github.com/docker/docker/daemon/internal/multierror" |
| 22 | 22 |
"github.com/docker/docker/daemon/internal/sliceutil" |
| 23 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 23 | 24 |
"github.com/docker/docker/daemon/libnetwork" |
| 24 | 25 |
"github.com/docker/docker/daemon/libnetwork/netlabel" |
| 25 | 26 |
"github.com/docker/docker/daemon/libnetwork/scope" |
| ... | ... |
@@ -27,7 +28,6 @@ import ( |
| 27 | 27 |
"github.com/docker/docker/daemon/network" |
| 28 | 28 |
"github.com/docker/docker/daemon/pkg/opts" |
| 29 | 29 |
"github.com/docker/docker/errdefs" |
| 30 |
- "github.com/docker/docker/pkg/stringid" |
|
| 31 | 30 |
"github.com/docker/docker/runconfig" |
| 32 | 31 |
"github.com/docker/go-connections/nat" |
| 33 | 32 |
containertypes "github.com/moby/moby/api/types/container" |
| ... | ... |
@@ -14,13 +14,13 @@ import ( |
| 14 | 14 |
"github.com/containerd/log" |
| 15 | 15 |
"github.com/docker/docker/daemon/config" |
| 16 | 16 |
"github.com/docker/docker/daemon/container" |
| 17 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 17 | 18 |
"github.com/docker/docker/daemon/libnetwork" |
| 18 | 19 |
"github.com/docker/docker/daemon/libnetwork/drivers/bridge" |
| 19 | 20 |
"github.com/docker/docker/daemon/links" |
| 20 | 21 |
"github.com/docker/docker/daemon/network" |
| 21 | 22 |
"github.com/docker/docker/errdefs" |
| 22 | 23 |
"github.com/docker/docker/pkg/process" |
| 23 |
- "github.com/docker/docker/pkg/stringid" |
|
| 24 | 24 |
"github.com/moby/sys/mount" |
| 25 | 25 |
"github.com/moby/sys/user" |
| 26 | 26 |
"github.com/opencontainers/selinux/go-selinux/label" |
| ... | ... |
@@ -24,10 +24,10 @@ import ( |
| 24 | 24 |
"github.com/docker/docker/daemon/builder" |
| 25 | 25 |
"github.com/docker/docker/daemon/internal/image" |
| 26 | 26 |
"github.com/docker/docker/daemon/internal/layer" |
| 27 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 27 | 28 |
"github.com/docker/docker/errdefs" |
| 28 | 29 |
"github.com/docker/docker/pkg/progress" |
| 29 | 30 |
"github.com/docker/docker/pkg/streamformatter" |
| 30 |
- "github.com/docker/docker/pkg/stringid" |
|
| 31 | 31 |
imagespec "github.com/moby/docker-image-spec/specs-go/v1" |
| 32 | 32 |
"github.com/moby/go-archive" |
| 33 | 33 |
"github.com/moby/moby/api/types/backend" |
| ... | ... |
@@ -7,7 +7,7 @@ import ( |
| 7 | 7 |
"github.com/containerd/containerd/v2/core/mount" |
| 8 | 8 |
"github.com/containerd/log" |
| 9 | 9 |
"github.com/docker/docker/daemon/container" |
| 10 |
- "github.com/docker/docker/pkg/stringid" |
|
| 10 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 11 | 11 |
"github.com/moby/go-archive" |
| 12 | 12 |
) |
| 13 | 13 |
|
| ... | ... |
@@ -18,7 +18,7 @@ import ( |
| 18 | 18 |
dimages "github.com/docker/docker/daemon/images" |
| 19 | 19 |
"github.com/docker/docker/daemon/internal/image" |
| 20 | 20 |
"github.com/docker/docker/daemon/internal/metrics" |
| 21 |
- "github.com/docker/docker/pkg/stringid" |
|
| 21 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 22 | 22 |
"github.com/moby/moby/api/types/events" |
| 23 | 23 |
imagetypes "github.com/moby/moby/api/types/image" |
| 24 | 24 |
ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
| ... | ... |
@@ -18,10 +18,10 @@ import ( |
| 18 | 18 |
"github.com/distribution/reference" |
| 19 | 19 |
"github.com/docker/docker/daemon/internal/distribution" |
| 20 | 20 |
"github.com/docker/docker/daemon/internal/metrics" |
| 21 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 21 | 22 |
"github.com/docker/docker/errdefs" |
| 22 | 23 |
"github.com/docker/docker/pkg/progress" |
| 23 | 24 |
"github.com/docker/docker/pkg/streamformatter" |
| 24 |
- "github.com/docker/docker/pkg/stringid" |
|
| 25 | 25 |
"github.com/moby/moby/api/types/events" |
| 26 | 26 |
registrytypes "github.com/moby/moby/api/types/registry" |
| 27 | 27 |
ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
| ... | ... |
@@ -17,9 +17,9 @@ import ( |
| 17 | 17 |
cerrdefs "github.com/containerd/errdefs" |
| 18 | 18 |
"github.com/containerd/log" |
| 19 | 19 |
"github.com/distribution/reference" |
| 20 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 20 | 21 |
"github.com/docker/docker/errdefs" |
| 21 | 22 |
"github.com/docker/docker/pkg/progress" |
| 22 |
- "github.com/docker/docker/pkg/stringid" |
|
| 23 | 23 |
"github.com/opencontainers/go-digest" |
| 24 | 24 |
ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
| 25 | 25 |
) |
| ... | ... |
@@ -12,7 +12,7 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
"github.com/docker/docker/daemon/graphdriver" |
| 14 | 14 |
"github.com/docker/docker/daemon/internal/quota" |
| 15 |
- "github.com/docker/docker/pkg/stringid" |
|
| 15 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 16 | 16 |
"github.com/docker/go-units" |
| 17 | 17 |
"golang.org/x/sys/unix" |
| 18 | 18 |
"gotest.tools/v3/assert" |
| ... | ... |
@@ -12,9 +12,9 @@ import ( |
| 12 | 12 |
"github.com/docker/docker/daemon/builder" |
| 13 | 13 |
"github.com/docker/docker/daemon/internal/image" |
| 14 | 14 |
"github.com/docker/docker/daemon/internal/layer" |
| 15 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 15 | 16 |
"github.com/docker/docker/pkg/progress" |
| 16 | 17 |
"github.com/docker/docker/pkg/streamformatter" |
| 17 |
- "github.com/docker/docker/pkg/stringid" |
|
| 18 | 18 |
"github.com/moby/moby/api/types/backend" |
| 19 | 19 |
"github.com/moby/moby/api/types/registry" |
| 20 | 20 |
"github.com/opencontainers/go-digest" |
| ... | ... |
@@ -10,8 +10,8 @@ import ( |
| 10 | 10 |
"github.com/docker/docker/daemon/container" |
| 11 | 11 |
"github.com/docker/docker/daemon/internal/image" |
| 12 | 12 |
"github.com/docker/docker/daemon/internal/metrics" |
| 13 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 13 | 14 |
"github.com/docker/docker/errdefs" |
| 14 |
- "github.com/docker/docker/pkg/stringid" |
|
| 15 | 15 |
"github.com/moby/moby/api/types/backend" |
| 16 | 16 |
"github.com/moby/moby/api/types/events" |
| 17 | 17 |
imagetypes "github.com/moby/moby/api/types/image" |
| ... | ... |
@@ -7,8 +7,8 @@ import ( |
| 7 | 7 |
"strconv" |
| 8 | 8 |
|
| 9 | 9 |
"github.com/containerd/log" |
| 10 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 10 | 11 |
"github.com/docker/docker/daemon/libnetwork" |
| 11 |
- "github.com/docker/docker/pkg/stringid" |
|
| 12 | 12 |
"github.com/moby/buildkit/executor" |
| 13 | 13 |
"github.com/moby/buildkit/executor/oci" |
| 14 | 14 |
"github.com/moby/buildkit/executor/resources" |
| ... | ... |
@@ -22,10 +22,10 @@ import ( |
| 22 | 22 |
"github.com/docker/docker/daemon/internal/image" |
| 23 | 23 |
"github.com/docker/docker/daemon/internal/layer" |
| 24 | 24 |
refstore "github.com/docker/docker/daemon/internal/refstore" |
| 25 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 25 | 26 |
"github.com/docker/docker/daemon/pkg/registry" |
| 26 | 27 |
"github.com/docker/docker/pkg/ioutils" |
| 27 | 28 |
"github.com/docker/docker/pkg/progress" |
| 28 |
- "github.com/docker/docker/pkg/stringid" |
|
| 29 | 29 |
"github.com/opencontainers/go-digest" |
| 30 | 30 |
ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
| 31 | 31 |
"github.com/pkg/errors" |
| ... | ... |
@@ -17,10 +17,10 @@ import ( |
| 17 | 17 |
"github.com/docker/docker/daemon/internal/distribution/metadata" |
| 18 | 18 |
"github.com/docker/docker/daemon/internal/distribution/xfer" |
| 19 | 19 |
"github.com/docker/docker/daemon/internal/layer" |
| 20 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 20 | 21 |
"github.com/docker/docker/daemon/pkg/registry" |
| 21 | 22 |
"github.com/docker/docker/pkg/ioutils" |
| 22 | 23 |
"github.com/docker/docker/pkg/progress" |
| 23 |
- "github.com/docker/docker/pkg/stringid" |
|
| 24 | 24 |
apitypes "github.com/moby/moby/api/types" |
| 25 | 25 |
"github.com/opencontainers/go-digest" |
| 26 | 26 |
"github.com/pkg/errors" |
| ... | ... |
@@ -18,9 +18,9 @@ import ( |
| 18 | 18 |
"github.com/docker/docker/daemon/internal/image" |
| 19 | 19 |
"github.com/docker/docker/daemon/internal/ioutils" |
| 20 | 20 |
"github.com/docker/docker/daemon/internal/layer" |
| 21 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 21 | 22 |
"github.com/docker/docker/pkg/progress" |
| 22 | 23 |
"github.com/docker/docker/pkg/streamformatter" |
| 23 |
- "github.com/docker/docker/pkg/stringid" |
|
| 24 | 24 |
"github.com/moby/go-archive/chrootarchive" |
| 25 | 25 |
"github.com/moby/go-archive/compression" |
| 26 | 26 |
"github.com/moby/moby/api/types/events" |
| ... | ... |
@@ -12,7 +12,7 @@ import ( |
| 12 | 12 |
"github.com/containerd/log" |
| 13 | 13 |
"github.com/docker/distribution" |
| 14 | 14 |
"github.com/docker/docker/daemon/graphdriver" |
| 15 |
- "github.com/docker/docker/pkg/stringid" |
|
| 15 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 16 | 16 |
"github.com/moby/locker" |
| 17 | 17 |
"github.com/moby/sys/user" |
| 18 | 18 |
"github.com/opencontainers/go-digest" |
| ... | ... |
@@ -13,7 +13,7 @@ import ( |
| 13 | 13 |
"github.com/containerd/continuity/driver" |
| 14 | 14 |
"github.com/docker/docker/daemon/graphdriver" |
| 15 | 15 |
"github.com/docker/docker/daemon/graphdriver/vfs" |
| 16 |
- "github.com/docker/docker/pkg/stringid" |
|
| 16 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 17 | 17 |
"github.com/moby/go-archive" |
| 18 | 18 |
"github.com/moby/sys/user" |
| 19 | 19 |
"github.com/opencontainers/go-digest" |
| ... | ... |
@@ -8,7 +8,7 @@ import ( |
| 8 | 8 |
"testing" |
| 9 | 9 |
|
| 10 | 10 |
"github.com/docker/docker/daemon/graphdriver" |
| 11 |
- "github.com/docker/docker/pkg/stringid" |
|
| 11 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 12 | 12 |
) |
| 13 | 13 |
|
| 14 | 14 |
func tarFromFilesInGraph(graph graphdriver.Driver, graphID, parentID string, files ...FileApplier) ([]byte, error) {
|
| 15 | 15 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,70 @@ |
| 0 |
+// Package stringid provides helper functions for dealing with string identifiers |
|
| 1 |
+package stringid |
|
| 2 |
+ |
|
| 3 |
+import ( |
|
| 4 |
+ "crypto/rand" |
|
| 5 |
+ "encoding/hex" |
|
| 6 |
+ "strings" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+const ( |
|
| 10 |
+ shortLen = 12 |
|
| 11 |
+ fullLen = 64 |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+// TruncateID returns a shorthand version of a string identifier for presentation. |
|
| 15 |
+// For convenience, it accepts both digests ("sha256:xxxx") and IDs without an
|
|
| 16 |
+// algorithm prefix. It truncates the algorithm (if any) before truncating the |
|
| 17 |
+// ID. The length of the truncated ID is currently fixed, but users should make |
|
| 18 |
+// no assumptions of this to not change; it is merely a prefix of the ID that |
|
| 19 |
+// provides enough uniqueness for common scenarios. |
|
| 20 |
+// |
|
| 21 |
+// Truncated IDs ("ID-prefixes") usually can be used to uniquely identify an
|
|
| 22 |
+// object (such as a container or network), but collisions may happen, in |
|
| 23 |
+// which case an "ambiguous result" error is produced. In case of a collision, |
|
| 24 |
+// the caller should try with a longer prefix or the full-length ID. |
|
| 25 |
+func TruncateID(id string) string {
|
|
| 26 |
+ if i := strings.IndexRune(id, ':'); i >= 0 {
|
|
| 27 |
+ id = id[i+1:] |
|
| 28 |
+ } |
|
| 29 |
+ if len(id) > shortLen {
|
|
| 30 |
+ id = id[:shortLen] |
|
| 31 |
+ } |
|
| 32 |
+ return id |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+// GenerateRandomID returns a unique, 64-character ID consisting of a-z, 0-9. |
|
| 36 |
+// It guarantees that the ID, when truncated ([TruncateID]) does not consist |
|
| 37 |
+// of numbers only, so that the truncated ID can be used as hostname for |
|
| 38 |
+// containers. |
|
| 39 |
+func GenerateRandomID() string {
|
|
| 40 |
+ b := make([]byte, 32) |
|
| 41 |
+ for {
|
|
| 42 |
+ if _, err := rand.Read(b); err != nil {
|
|
| 43 |
+ panic(err) // This shouldn't happen |
|
| 44 |
+ } |
|
| 45 |
+ id := hex.EncodeToString(b) |
|
| 46 |
+ |
|
| 47 |
+ // make sure that the truncated ID does not consist of only numeric |
|
| 48 |
+ // characters, as it's used as default hostname for containers. |
|
| 49 |
+ // |
|
| 50 |
+ // See: |
|
| 51 |
+ // - https://github.com/moby/moby/issues/3869 |
|
| 52 |
+ // - https://bugzilla.redhat.com/show_bug.cgi?id=1059122 |
|
| 53 |
+ if allNum(id[:shortLen]) {
|
|
| 54 |
+ // all numbers; try again |
|
| 55 |
+ continue |
|
| 56 |
+ } |
|
| 57 |
+ return id |
|
| 58 |
+ } |
|
| 59 |
+} |
|
| 60 |
+ |
|
| 61 |
+// allNum checks whether id consists of only numbers (0-9). |
|
| 62 |
+func allNum(id string) bool {
|
|
| 63 |
+ for _, c := range []byte(id) {
|
|
| 64 |
+ if c > '9' || c < '0' {
|
|
| 65 |
+ return false |
|
| 66 |
+ } |
|
| 67 |
+ } |
|
| 68 |
+ return true |
|
| 69 |
+} |
| 0 | 70 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,86 @@ |
| 0 |
+package stringid |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "testing" |
|
| 4 |
+) |
|
| 5 |
+ |
|
| 6 |
+func TestGenerateRandomID(t *testing.T) {
|
|
| 7 |
+ id := GenerateRandomID() |
|
| 8 |
+ |
|
| 9 |
+ if len(id) != fullLen {
|
|
| 10 |
+ t.Fatalf("Id returned is incorrect: %s", id)
|
|
| 11 |
+ } |
|
| 12 |
+} |
|
| 13 |
+ |
|
| 14 |
+func TestTruncateID(t *testing.T) {
|
|
| 15 |
+ tests := []struct {
|
|
| 16 |
+ doc, id, expected string |
|
| 17 |
+ }{
|
|
| 18 |
+ {
|
|
| 19 |
+ doc: "empty ID", |
|
| 20 |
+ id: "", |
|
| 21 |
+ expected: "", |
|
| 22 |
+ }, |
|
| 23 |
+ {
|
|
| 24 |
+ // IDs are expected to be 12 (short) or 64 characters, and not be numeric only, |
|
| 25 |
+ // but TruncateID should handle these gracefully. |
|
| 26 |
+ doc: "invalid ID", |
|
| 27 |
+ id: "1234", |
|
| 28 |
+ expected: "1234", |
|
| 29 |
+ }, |
|
| 30 |
+ {
|
|
| 31 |
+ doc: "full ID", |
|
| 32 |
+ id: "90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2", |
|
| 33 |
+ expected: "90435eec5c4e", |
|
| 34 |
+ }, |
|
| 35 |
+ {
|
|
| 36 |
+ doc: "digest", |
|
| 37 |
+ id: "sha256:90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2", |
|
| 38 |
+ expected: "90435eec5c4e", |
|
| 39 |
+ }, |
|
| 40 |
+ {
|
|
| 41 |
+ doc: "very long ID", |
|
| 42 |
+ id: "90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a290435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2", |
|
| 43 |
+ expected: "90435eec5c4e", |
|
| 44 |
+ }, |
|
| 45 |
+ } |
|
| 46 |
+ |
|
| 47 |
+ for _, tc := range tests {
|
|
| 48 |
+ t.Run(tc.doc, func(t *testing.T) {
|
|
| 49 |
+ actual := TruncateID(tc.id) |
|
| 50 |
+ if actual != tc.expected {
|
|
| 51 |
+ t.Errorf("expected: %q, got: %q", tc.expected, actual)
|
|
| 52 |
+ } |
|
| 53 |
+ }) |
|
| 54 |
+ } |
|
| 55 |
+} |
|
| 56 |
+ |
|
| 57 |
+func TestAllNum(t *testing.T) {
|
|
| 58 |
+ tests := []struct {
|
|
| 59 |
+ doc, id string |
|
| 60 |
+ expected bool |
|
| 61 |
+ }{
|
|
| 62 |
+ {
|
|
| 63 |
+ doc: "mixed letters and numbers", |
|
| 64 |
+ id: "4e38e38c8ce0", |
|
| 65 |
+ expected: false, |
|
| 66 |
+ }, |
|
| 67 |
+ {
|
|
| 68 |
+ doc: "letters only", |
|
| 69 |
+ id: "deadbeefcafe", |
|
| 70 |
+ expected: false, |
|
| 71 |
+ }, |
|
| 72 |
+ {
|
|
| 73 |
+ doc: "numbers only", |
|
| 74 |
+ id: "012345678912", |
|
| 75 |
+ expected: true, |
|
| 76 |
+ }, |
|
| 77 |
+ } |
|
| 78 |
+ for _, tc := range tests {
|
|
| 79 |
+ t.Run(tc.doc, func(t *testing.T) {
|
|
| 80 |
+ if actual := allNum(tc.id); actual != tc.expected {
|
|
| 81 |
+ t.Errorf("expected %q to be %t, got %t, ", tc.id, !tc.expected, actual)
|
|
| 82 |
+ } |
|
| 83 |
+ }) |
|
| 84 |
+ } |
|
| 85 |
+} |
| ... | ... |
@@ -55,6 +55,7 @@ import ( |
| 55 | 55 |
|
| 56 | 56 |
"github.com/containerd/log" |
| 57 | 57 |
"github.com/docker/docker/daemon/internal/otelutil" |
| 58 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 58 | 59 |
"github.com/docker/docker/daemon/libnetwork/cluster" |
| 59 | 60 |
"github.com/docker/docker/daemon/libnetwork/config" |
| 60 | 61 |
"github.com/docker/docker/daemon/libnetwork/datastore" |
| ... | ... |
@@ -71,7 +72,6 @@ import ( |
| 71 | 71 |
"github.com/docker/docker/daemon/libnetwork/types" |
| 72 | 72 |
"github.com/docker/docker/pkg/plugingetter" |
| 73 | 73 |
"github.com/docker/docker/pkg/plugins" |
| 74 |
- "github.com/docker/docker/pkg/stringid" |
|
| 75 | 74 |
"github.com/moby/locker" |
| 76 | 75 |
"github.com/pkg/errors" |
| 77 | 76 |
"go.opentelemetry.io/otel" |
| ... | ... |
@@ -18,6 +18,7 @@ import ( |
| 18 | 18 |
"github.com/containerd/log" |
| 19 | 19 |
"github.com/docker/docker/daemon/internal/otelutil" |
| 20 | 20 |
"github.com/docker/docker/daemon/internal/sliceutil" |
| 21 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 21 | 22 |
"github.com/docker/docker/daemon/libnetwork/datastore" |
| 22 | 23 |
"github.com/docker/docker/daemon/libnetwork/driverapi" |
| 23 | 24 |
"github.com/docker/docker/daemon/libnetwork/drivers/bridge/internal/firewaller" |
| ... | ... |
@@ -36,7 +37,6 @@ import ( |
| 36 | 36 |
"github.com/docker/docker/daemon/libnetwork/scope" |
| 37 | 37 |
"github.com/docker/docker/daemon/libnetwork/types" |
| 38 | 38 |
"github.com/docker/docker/errdefs" |
| 39 |
- "github.com/docker/docker/pkg/stringid" |
|
| 40 | 39 |
"github.com/pkg/errors" |
| 41 | 40 |
"github.com/vishvananda/netlink" |
| 42 | 41 |
"github.com/vishvananda/netns" |
| ... | ... |
@@ -15,6 +15,7 @@ import ( |
| 15 | 15 |
|
| 16 | 16 |
"github.com/containerd/log" |
| 17 | 17 |
"github.com/docker/docker/daemon/internal/sliceutil" |
| 18 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 18 | 19 |
"github.com/docker/docker/daemon/libnetwork/datastore" |
| 19 | 20 |
"github.com/docker/docker/daemon/libnetwork/driverapi" |
| 20 | 21 |
"github.com/docker/docker/daemon/libnetwork/ipamapi" |
| ... | ... |
@@ -23,7 +24,6 @@ import ( |
| 23 | 23 |
"github.com/docker/docker/daemon/libnetwork/scope" |
| 24 | 24 |
"github.com/docker/docker/daemon/libnetwork/types" |
| 25 | 25 |
"github.com/docker/docker/errdefs" |
| 26 |
- "github.com/docker/docker/pkg/stringid" |
|
| 27 | 26 |
"go.opentelemetry.io/otel" |
| 28 | 27 |
) |
| 29 | 28 |
|
| ... | ... |
@@ -17,6 +17,7 @@ import ( |
| 17 | 17 |
|
| 18 | 18 |
"github.com/containerd/log" |
| 19 | 19 |
"github.com/docker/docker/daemon/internal/sliceutil" |
| 20 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 20 | 21 |
"github.com/docker/docker/daemon/libnetwork/datastore" |
| 21 | 22 |
"github.com/docker/docker/daemon/libnetwork/driverapi" |
| 22 | 23 |
"github.com/docker/docker/daemon/libnetwork/internal/netiputil" |
| ... | ... |
@@ -30,7 +31,6 @@ import ( |
| 30 | 30 |
"github.com/docker/docker/daemon/libnetwork/scope" |
| 31 | 31 |
"github.com/docker/docker/daemon/libnetwork/types" |
| 32 | 32 |
"github.com/docker/docker/errdefs" |
| 33 |
- "github.com/docker/docker/pkg/stringid" |
|
| 34 | 33 |
"go.opentelemetry.io/otel" |
| 35 | 34 |
"go.opentelemetry.io/otel/attribute" |
| 36 | 35 |
"go.opentelemetry.io/otel/trace" |
| ... | ... |
@@ -17,8 +17,8 @@ import ( |
| 17 | 17 |
"time" |
| 18 | 18 |
|
| 19 | 19 |
"github.com/containerd/log" |
| 20 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 20 | 21 |
"github.com/docker/docker/daemon/libnetwork/types" |
| 21 |
- "github.com/docker/docker/pkg/stringid" |
|
| 22 | 22 |
"github.com/docker/go-events" |
| 23 | 23 |
iradix "github.com/hashicorp/go-immutable-radix/v2" |
| 24 | 24 |
"github.com/hashicorp/memberlist" |
| ... | ... |
@@ -14,7 +14,7 @@ import ( |
| 14 | 14 |
|
| 15 | 15 |
cerrdefs "github.com/containerd/errdefs" |
| 16 | 16 |
"github.com/containerd/log" |
| 17 |
- "github.com/docker/docker/pkg/stringid" |
|
| 17 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 18 | 18 |
"github.com/docker/go-events" |
| 19 | 19 |
"github.com/hashicorp/memberlist" |
| 20 | 20 |
"gotest.tools/v3/assert" |
| ... | ... |
@@ -14,8 +14,8 @@ import ( |
| 14 | 14 |
|
| 15 | 15 |
"github.com/containerd/log" |
| 16 | 16 |
"github.com/docker/docker/daemon/internal/otelutil" |
| 17 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 17 | 18 |
"github.com/docker/docker/daemon/libnetwork/types" |
| 18 |
- "github.com/docker/docker/pkg/stringid" |
|
| 19 | 19 |
"github.com/moby/sys/reexec" |
| 20 | 20 |
"github.com/opencontainers/runtime-spec/specs-go" |
| 21 | 21 |
"go.opentelemetry.io/otel" |
| ... | ... |
@@ -7,10 +7,10 @@ import ( |
| 7 | 7 |
"fmt" |
| 8 | 8 |
|
| 9 | 9 |
"github.com/containerd/log" |
| 10 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 10 | 11 |
"github.com/docker/docker/daemon/libnetwork/datastore" |
| 11 | 12 |
"github.com/docker/docker/daemon/libnetwork/osl" |
| 12 | 13 |
"github.com/docker/docker/daemon/libnetwork/scope" |
| 13 |
- "github.com/docker/docker/pkg/stringid" |
|
| 14 | 14 |
) |
| 15 | 15 |
|
| 16 | 16 |
const ( |
| ... | ... |
@@ -12,9 +12,9 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
"github.com/coreos/go-systemd/v22/journal" |
| 14 | 14 |
|
| 15 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 15 | 16 |
"github.com/docker/docker/daemon/logger" |
| 16 | 17 |
"github.com/docker/docker/daemon/logger/loggerutils" |
| 17 |
- "github.com/docker/docker/pkg/stringid" |
|
| 18 | 18 |
) |
| 19 | 19 |
|
| 20 | 20 |
const name = "journald" |
| ... | ... |
@@ -6,10 +6,10 @@ import ( |
| 6 | 6 |
"os" |
| 7 | 7 |
"path/filepath" |
| 8 | 8 |
|
| 9 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 9 | 10 |
"github.com/docker/docker/errdefs" |
| 10 | 11 |
"github.com/docker/docker/pkg/plugingetter" |
| 11 | 12 |
"github.com/docker/docker/pkg/plugins" |
| 12 |
- "github.com/docker/docker/pkg/stringid" |
|
| 13 | 13 |
"github.com/moby/moby/api/types/plugins/logdriver" |
| 14 | 14 |
"github.com/pkg/errors" |
| 15 | 15 |
) |
| ... | ... |
@@ -7,10 +7,10 @@ import ( |
| 7 | 7 |
cerrdefs "github.com/containerd/errdefs" |
| 8 | 8 |
"github.com/containerd/log" |
| 9 | 9 |
"github.com/docker/docker/daemon/container" |
| 10 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 10 | 11 |
"github.com/docker/docker/daemon/names" |
| 11 | 12 |
"github.com/docker/docker/errdefs" |
| 12 | 13 |
"github.com/docker/docker/pkg/namesgenerator" |
| 13 |
- "github.com/docker/docker/pkg/stringid" |
|
| 14 | 14 |
"github.com/pkg/errors" |
| 15 | 15 |
) |
| 16 | 16 |
|
| ... | ... |
@@ -22,13 +22,13 @@ import ( |
| 22 | 22 |
"github.com/containerd/platforms" |
| 23 | 23 |
"github.com/distribution/reference" |
| 24 | 24 |
"github.com/docker/docker/daemon/internal/containerfs" |
| 25 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 25 | 26 |
v2 "github.com/docker/docker/daemon/pkg/plugin/v2" |
| 26 | 27 |
"github.com/docker/docker/dockerversion" |
| 27 | 28 |
"github.com/docker/docker/errdefs" |
| 28 | 29 |
"github.com/docker/docker/pkg/authorization" |
| 29 | 30 |
"github.com/docker/docker/pkg/pools" |
| 30 | 31 |
"github.com/docker/docker/pkg/progress" |
| 31 |
- "github.com/docker/docker/pkg/stringid" |
|
| 32 | 32 |
"github.com/moby/go-archive/chrootarchive" |
| 33 | 33 |
"github.com/moby/moby/api/types" |
| 34 | 34 |
"github.com/moby/moby/api/types/backend" |
| ... | ... |
@@ -14,9 +14,9 @@ import ( |
| 14 | 14 |
"github.com/containerd/log" |
| 15 | 15 |
"github.com/distribution/reference" |
| 16 | 16 |
progressutils "github.com/docker/docker/daemon/internal/distribution/utils" |
| 17 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 17 | 18 |
"github.com/docker/docker/pkg/ioutils" |
| 18 | 19 |
"github.com/docker/docker/pkg/progress" |
| 19 |
- "github.com/docker/docker/pkg/stringid" |
|
| 20 | 20 |
"github.com/moby/go-archive/chrootarchive" |
| 21 | 21 |
"github.com/moby/moby/api/types/registry" |
| 22 | 22 |
"github.com/opencontainers/go-digest" |
| ... | ... |
@@ -11,10 +11,10 @@ import ( |
| 11 | 11 |
"github.com/containerd/containerd/v2/core/content" |
| 12 | 12 |
"github.com/containerd/log" |
| 13 | 13 |
"github.com/docker/docker/daemon/initlayer" |
| 14 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 14 | 15 |
v2 "github.com/docker/docker/daemon/pkg/plugin/v2" |
| 15 | 16 |
"github.com/docker/docker/errdefs" |
| 16 | 17 |
"github.com/docker/docker/pkg/plugins" |
| 17 |
- "github.com/docker/docker/pkg/stringid" |
|
| 18 | 18 |
"github.com/moby/moby/api/types" |
| 19 | 19 |
"github.com/moby/sys/mount" |
| 20 | 20 |
"github.com/opencontainers/go-digest" |
| ... | ... |
@@ -9,8 +9,8 @@ import ( |
| 9 | 9 |
"testing" |
| 10 | 10 |
|
| 11 | 11 |
"github.com/docker/docker/daemon/internal/containerfs" |
| 12 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 12 | 13 |
v2 "github.com/docker/docker/daemon/pkg/plugin/v2" |
| 13 |
- "github.com/docker/docker/pkg/stringid" |
|
| 14 | 14 |
"github.com/moby/moby/api/types" |
| 15 | 15 |
"github.com/moby/moby/api/types/backend" |
| 16 | 16 |
"github.com/moby/moby/api/types/events" |
| ... | ... |
@@ -8,8 +8,8 @@ import ( |
| 8 | 8 |
"net/http" |
| 9 | 9 |
|
| 10 | 10 |
"github.com/docker/docker/daemon/internal/sliceutil" |
| 11 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 11 | 12 |
"github.com/docker/docker/daemon/server/httputils" |
| 12 |
- "github.com/docker/docker/pkg/stringid" |
|
| 13 | 13 |
"github.com/moby/moby/api/types/backend" |
| 14 | 14 |
"github.com/moby/moby/api/types/container" |
| 15 | 15 |
"github.com/moby/moby/api/types/versions" |
| ... | ... |
@@ -8,9 +8,9 @@ import ( |
| 8 | 8 |
|
| 9 | 9 |
"github.com/containerd/log" |
| 10 | 10 |
"github.com/docker/docker/daemon/internal/idtools" |
| 11 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 11 | 12 |
"github.com/docker/docker/daemon/volume" |
| 12 | 13 |
"github.com/docker/docker/daemon/volume/safepath" |
| 13 |
- "github.com/docker/docker/pkg/stringid" |
|
| 14 | 14 |
mounttypes "github.com/moby/moby/api/types/mount" |
| 15 | 15 |
"github.com/moby/sys/user" |
| 16 | 16 |
"github.com/opencontainers/selinux/go-selinux/label" |
| ... | ... |
@@ -8,12 +8,12 @@ import ( |
| 8 | 8 |
"github.com/containerd/log" |
| 9 | 9 |
"github.com/docker/docker/daemon/internal/directory" |
| 10 | 10 |
"github.com/docker/docker/daemon/internal/idtools" |
| 11 |
+ "github.com/docker/docker/daemon/internal/stringid" |
|
| 11 | 12 |
"github.com/docker/docker/daemon/volume" |
| 12 | 13 |
"github.com/docker/docker/daemon/volume/drivers" |
| 13 | 14 |
"github.com/docker/docker/daemon/volume/service/opts" |
| 14 | 15 |
"github.com/docker/docker/errdefs" |
| 15 | 16 |
"github.com/docker/docker/pkg/plugingetter" |
| 16 |
- "github.com/docker/docker/pkg/stringid" |
|
| 17 | 17 |
"github.com/moby/moby/api/types/events" |
| 18 | 18 |
"github.com/moby/moby/api/types/filters" |
| 19 | 19 |
volumetypes "github.com/moby/moby/api/types/volume" |
| ... | ... |
@@ -22,7 +22,6 @@ import ( |
| 22 | 22 |
"github.com/docker/docker/daemon/volume" |
| 23 | 23 |
"github.com/docker/docker/integration-cli/cli" |
| 24 | 24 |
"github.com/docker/docker/integration-cli/cli/build" |
| 25 |
- "github.com/docker/docker/pkg/stringid" |
|
| 26 | 25 |
"github.com/docker/docker/testutil" |
| 27 | 26 |
"github.com/docker/docker/testutil/request" |
| 28 | 27 |
"github.com/docker/go-connections/nat" |
| ... | ... |
@@ -30,6 +29,7 @@ import ( |
| 30 | 30 |
"github.com/moby/moby/api/types/mount" |
| 31 | 31 |
"github.com/moby/moby/api/types/network" |
| 32 | 32 |
"github.com/moby/moby/client" |
| 33 |
+ "github.com/moby/moby/client/pkg/stringid" |
|
| 33 | 34 |
"gotest.tools/v3/assert" |
| 34 | 35 |
is "gotest.tools/v3/assert/cmp" |
| 35 | 36 |
"gotest.tools/v3/poll" |
| ... | ... |
@@ -19,7 +19,6 @@ import ( |
| 19 | 19 |
"github.com/docker/docker/integration-cli/cli" |
| 20 | 20 |
"github.com/docker/docker/integration-cli/daemon" |
| 21 | 21 |
"github.com/docker/docker/pkg/plugins" |
| 22 |
- "github.com/docker/docker/pkg/stringid" |
|
| 23 | 22 |
"github.com/docker/docker/testutil" |
| 24 | 23 |
testdaemon "github.com/docker/docker/testutil/daemon" |
| 25 | 24 |
"github.com/moby/moby/api/types/container" |
| ... | ... |
@@ -560,7 +559,7 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverCapabilities(c *test |
| 560 | 560 |
|
| 561 | 561 |
func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverOutOfBandDelete(c *testing.T) {
|
| 562 | 562 |
ctx := testutil.GetContext(c) |
| 563 |
- driverName := stringid.GenerateRandomID() |
|
| 563 |
+ driverName := strings.ReplaceAll(strings.ToLower(c.Name()), "/", "_") |
|
| 564 | 564 |
p := newVolumePlugin(c, driverName) |
| 565 | 565 |
defer p.Close() |
| 566 | 566 |
|
| ... | ... |
@@ -13,7 +13,7 @@ import ( |
| 13 | 13 |
|
| 14 | 14 |
"github.com/docker/docker/integration-cli/cli" |
| 15 | 15 |
"github.com/docker/docker/integration-cli/cli/build" |
| 16 |
- "github.com/docker/docker/pkg/stringid" |
|
| 16 |
+ "github.com/moby/moby/client/pkg/stringid" |
|
| 17 | 17 |
"gotest.tools/v3/assert" |
| 18 | 18 |
is "gotest.tools/v3/assert/cmp" |
| 19 | 19 |
"gotest.tools/v3/icmd" |
| ... | ... |
@@ -23,11 +23,11 @@ import ( |
| 23 | 23 |
"github.com/docker/docker/integration-cli/cli" |
| 24 | 24 |
"github.com/docker/docker/integration-cli/daemon" |
| 25 | 25 |
"github.com/docker/docker/pkg/plugins" |
| 26 |
- "github.com/docker/docker/pkg/stringid" |
|
| 27 | 26 |
"github.com/docker/docker/testutil" |
| 28 | 27 |
testdaemon "github.com/docker/docker/testutil/daemon" |
| 29 | 28 |
"github.com/moby/moby/api/types/container" |
| 30 | 29 |
"github.com/moby/moby/api/types/network" |
| 30 |
+ "github.com/moby/moby/client/pkg/stringid" |
|
| 31 | 31 |
"github.com/vishvananda/netlink" |
| 32 | 32 |
"golang.org/x/sys/unix" |
| 33 | 33 |
"gotest.tools/v3/assert" |
| ... | ... |
@@ -10,8 +10,8 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
"github.com/docker/docker/integration-cli/cli" |
| 12 | 12 |
"github.com/docker/docker/integration-cli/cli/build" |
| 13 |
- "github.com/docker/docker/pkg/stringid" |
|
| 14 | 13 |
"github.com/docker/go-units" |
| 14 |
+ "github.com/moby/moby/client/pkg/stringid" |
|
| 15 | 15 |
"gotest.tools/v3/assert" |
| 16 | 16 |
is "gotest.tools/v3/assert/cmp" |
| 17 | 17 |
"gotest.tools/v3/icmd" |
| ... | ... |
@@ -9,7 +9,7 @@ import ( |
| 9 | 9 |
|
| 10 | 10 |
"github.com/docker/docker/integration-cli/cli" |
| 11 | 11 |
"github.com/docker/docker/integration-cli/cli/build" |
| 12 |
- "github.com/docker/docker/pkg/stringid" |
|
| 12 |
+ "github.com/moby/moby/client/pkg/stringid" |
|
| 13 | 13 |
"gotest.tools/v3/assert" |
| 14 | 14 |
is "gotest.tools/v3/assert/cmp" |
| 15 | 15 |
"gotest.tools/v3/icmd" |
| ... | ... |
@@ -27,12 +27,12 @@ import ( |
| 27 | 27 |
"github.com/docker/docker/integration-cli/cli/build" |
| 28 | 28 |
"github.com/docker/docker/integration-cli/daemon" |
| 29 | 29 |
"github.com/docker/docker/internal/testutils/specialimage" |
| 30 |
- "github.com/docker/docker/pkg/stringid" |
|
| 31 | 30 |
"github.com/docker/docker/testutil" |
| 32 | 31 |
testdaemon "github.com/docker/docker/testutil/daemon" |
| 33 | 32 |
"github.com/docker/docker/testutil/fakecontext" |
| 34 | 33 |
"github.com/docker/go-connections/nat" |
| 35 | 34 |
"github.com/moby/moby/client" |
| 35 |
+ "github.com/moby/moby/client/pkg/stringid" |
|
| 36 | 36 |
"github.com/moby/sys/mountinfo" |
| 37 | 37 |
"gotest.tools/v3/assert" |
| 38 | 38 |
is "gotest.tools/v3/assert/cmp" |
| ... | ... |
@@ -14,12 +14,12 @@ import ( |
| 14 | 14 |
"github.com/docker/docker/daemon/pkg/oci" |
| 15 | 15 |
testContainer "github.com/docker/docker/integration/internal/container" |
| 16 | 16 |
net "github.com/docker/docker/integration/internal/network" |
| 17 |
- "github.com/docker/docker/pkg/stringid" |
|
| 18 | 17 |
"github.com/docker/docker/testutil" |
| 19 | 18 |
"github.com/moby/moby/api/types/container" |
| 20 | 19 |
"github.com/moby/moby/api/types/network" |
| 21 | 20 |
"github.com/moby/moby/api/types/versions" |
| 22 | 21 |
"github.com/moby/moby/client" |
| 22 |
+ "github.com/moby/moby/client/pkg/stringid" |
|
| 23 | 23 |
ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
| 24 | 24 |
"gotest.tools/v3/assert" |
| 25 | 25 |
is "gotest.tools/v3/assert/cmp" |
| ... | ... |
@@ -4,7 +4,6 @@ import ( |
| 4 | 4 |
"testing" |
| 5 | 5 |
|
| 6 | 6 |
"github.com/docker/docker/integration/internal/container" |
| 7 |
- "github.com/docker/docker/pkg/stringid" |
|
| 8 | 7 |
containertypes "github.com/moby/moby/api/types/container" |
| 9 | 8 |
"github.com/moby/moby/api/types/network" |
| 10 | 9 |
"gotest.tools/v3/assert" |
| ... | ... |
@@ -53,7 +52,7 @@ func TestRenameStoppedContainer(t *testing.T) {
|
| 53 | 53 |
assert.NilError(t, err) |
| 54 | 54 |
assert.Check(t, is.Equal("/"+oldName, inspect.Name))
|
| 55 | 55 |
|
| 56 |
- newName := "new_name" + stringid.GenerateRandomID() |
|
| 56 |
+ newName := "new_name" + cID // using cID as random suffix |
|
| 57 | 57 |
err = apiClient.ContainerRename(ctx, oldName, newName) |
| 58 | 58 |
assert.NilError(t, err) |
| 59 | 59 |
|
| ... | ... |
@@ -69,7 +68,7 @@ func TestRenameRunningContainerAndReuse(t *testing.T) {
|
| 69 | 69 |
oldName := "first_name" + t.Name() |
| 70 | 70 |
cID := container.Run(ctx, t, apiClient, container.WithName(oldName)) |
| 71 | 71 |
|
| 72 |
- newName := "new_name" + stringid.GenerateRandomID() |
|
| 72 |
+ newName := "new_name" + cID // using cID as random suffix |
|
| 73 | 73 |
err := apiClient.ContainerRename(ctx, oldName, newName) |
| 74 | 74 |
assert.NilError(t, err) |
| 75 | 75 |
|
| 76 | 76 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,18 @@ |
| 0 |
+// Package stringid provides helper functions for dealing with string identifiers. |
|
| 1 |
+package stringid |
|
| 2 |
+ |
|
| 3 |
+import "github.com/moby/moby/client/pkg/stringid" |
|
| 4 |
+ |
|
| 5 |
+// TruncateID returns a shorthand version of a string identifier for presentation. |
|
| 6 |
+// |
|
| 7 |
+// Deprecated: use [stringid.TruncateID]. This package will be removed in the next release. |
|
| 8 |
+func TruncateID(id string) string {
|
|
| 9 |
+ return stringid.TruncateID(id) |
|
| 10 |
+} |
|
| 11 |
+ |
|
| 12 |
+// GenerateRandomID returns a unique, 64-character ID consisting of a-z, 0-9. |
|
| 13 |
+// |
|
| 14 |
+// Deprecated: use [stringid.GenerateRandomID]. This package will be removed in the next release. |
|
| 15 |
+func GenerateRandomID() string {
|
|
| 16 |
+ return stringid.GenerateRandomID() |
|
| 17 |
+} |
| 0 | 18 |
deleted file mode 100644 |
| ... | ... |
@@ -1,70 +0,0 @@ |
| 1 |
-// Package stringid provides helper functions for dealing with string identifiers |
|
| 2 |
-package stringid |
|
| 3 |
- |
|
| 4 |
-import ( |
|
| 5 |
- "crypto/rand" |
|
| 6 |
- "encoding/hex" |
|
| 7 |
- "strings" |
|
| 8 |
-) |
|
| 9 |
- |
|
| 10 |
-const ( |
|
| 11 |
- shortLen = 12 |
|
| 12 |
- fullLen = 64 |
|
| 13 |
-) |
|
| 14 |
- |
|
| 15 |
-// TruncateID returns a shorthand version of a string identifier for presentation. |
|
| 16 |
-// For convenience, it accepts both digests ("sha256:xxxx") and IDs without an
|
|
| 17 |
-// algorithm prefix. It truncates the algorithm (if any) before truncating the |
|
| 18 |
-// ID. The length of the truncated ID is currently fixed, but users should make |
|
| 19 |
-// no assumptions of this to not change; it is merely a prefix of the ID that |
|
| 20 |
-// provides enough uniqueness for common scenarios. |
|
| 21 |
-// |
|
| 22 |
-// Truncated IDs ("ID-prefixes") usually can be used to uniquely identify an
|
|
| 23 |
-// object (such as a container or network), but collisions may happen, in |
|
| 24 |
-// which case an "ambiguous result" error is produced. In case of a collision, |
|
| 25 |
-// the caller should try with a longer prefix or the full-length ID. |
|
| 26 |
-func TruncateID(id string) string {
|
|
| 27 |
- if i := strings.IndexRune(id, ':'); i >= 0 {
|
|
| 28 |
- id = id[i+1:] |
|
| 29 |
- } |
|
| 30 |
- if len(id) > shortLen {
|
|
| 31 |
- id = id[:shortLen] |
|
| 32 |
- } |
|
| 33 |
- return id |
|
| 34 |
-} |
|
| 35 |
- |
|
| 36 |
-// GenerateRandomID returns a unique, 64-character ID consisting of a-z, 0-9. |
|
| 37 |
-// It guarantees that the ID, when truncated ([TruncateID]) does not consist |
|
| 38 |
-// of numbers only, so that the truncated ID can be used as hostname for |
|
| 39 |
-// containers. |
|
| 40 |
-func GenerateRandomID() string {
|
|
| 41 |
- b := make([]byte, 32) |
|
| 42 |
- for {
|
|
| 43 |
- if _, err := rand.Read(b); err != nil {
|
|
| 44 |
- panic(err) // This shouldn't happen |
|
| 45 |
- } |
|
| 46 |
- id := hex.EncodeToString(b) |
|
| 47 |
- |
|
| 48 |
- // make sure that the truncated ID does not consist of only numeric |
|
| 49 |
- // characters, as it's used as default hostname for containers. |
|
| 50 |
- // |
|
| 51 |
- // See: |
|
| 52 |
- // - https://github.com/moby/moby/issues/3869 |
|
| 53 |
- // - https://bugzilla.redhat.com/show_bug.cgi?id=1059122 |
|
| 54 |
- if allNum(id[:shortLen]) {
|
|
| 55 |
- // all numbers; try again |
|
| 56 |
- continue |
|
| 57 |
- } |
|
| 58 |
- return id |
|
| 59 |
- } |
|
| 60 |
-} |
|
| 61 |
- |
|
| 62 |
-// allNum checks whether id consists of only numbers (0-9). |
|
| 63 |
-func allNum(id string) bool {
|
|
| 64 |
- for _, c := range []byte(id) {
|
|
| 65 |
- if c > '9' || c < '0' {
|
|
| 66 |
- return false |
|
| 67 |
- } |
|
| 68 |
- } |
|
| 69 |
- return true |
|
| 70 |
-} |
| 71 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,86 +0,0 @@ |
| 1 |
-package stringid |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "testing" |
|
| 5 |
-) |
|
| 6 |
- |
|
| 7 |
-func TestGenerateRandomID(t *testing.T) {
|
|
| 8 |
- id := GenerateRandomID() |
|
| 9 |
- |
|
| 10 |
- if len(id) != fullLen {
|
|
| 11 |
- t.Fatalf("Id returned is incorrect: %s", id)
|
|
| 12 |
- } |
|
| 13 |
-} |
|
| 14 |
- |
|
| 15 |
-func TestTruncateID(t *testing.T) {
|
|
| 16 |
- tests := []struct {
|
|
| 17 |
- doc, id, expected string |
|
| 18 |
- }{
|
|
| 19 |
- {
|
|
| 20 |
- doc: "empty ID", |
|
| 21 |
- id: "", |
|
| 22 |
- expected: "", |
|
| 23 |
- }, |
|
| 24 |
- {
|
|
| 25 |
- // IDs are expected to be 12 (short) or 64 characters, and not be numeric only, |
|
| 26 |
- // but TruncateID should handle these gracefully. |
|
| 27 |
- doc: "invalid ID", |
|
| 28 |
- id: "1234", |
|
| 29 |
- expected: "1234", |
|
| 30 |
- }, |
|
| 31 |
- {
|
|
| 32 |
- doc: "full ID", |
|
| 33 |
- id: "90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2", |
|
| 34 |
- expected: "90435eec5c4e", |
|
| 35 |
- }, |
|
| 36 |
- {
|
|
| 37 |
- doc: "digest", |
|
| 38 |
- id: "sha256:90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2", |
|
| 39 |
- expected: "90435eec5c4e", |
|
| 40 |
- }, |
|
| 41 |
- {
|
|
| 42 |
- doc: "very long ID", |
|
| 43 |
- id: "90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a290435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2", |
|
| 44 |
- expected: "90435eec5c4e", |
|
| 45 |
- }, |
|
| 46 |
- } |
|
| 47 |
- |
|
| 48 |
- for _, tc := range tests {
|
|
| 49 |
- t.Run(tc.doc, func(t *testing.T) {
|
|
| 50 |
- actual := TruncateID(tc.id) |
|
| 51 |
- if actual != tc.expected {
|
|
| 52 |
- t.Errorf("expected: %q, got: %q", tc.expected, actual)
|
|
| 53 |
- } |
|
| 54 |
- }) |
|
| 55 |
- } |
|
| 56 |
-} |
|
| 57 |
- |
|
| 58 |
-func TestAllNum(t *testing.T) {
|
|
| 59 |
- tests := []struct {
|
|
| 60 |
- doc, id string |
|
| 61 |
- expected bool |
|
| 62 |
- }{
|
|
| 63 |
- {
|
|
| 64 |
- doc: "mixed letters and numbers", |
|
| 65 |
- id: "4e38e38c8ce0", |
|
| 66 |
- expected: false, |
|
| 67 |
- }, |
|
| 68 |
- {
|
|
| 69 |
- doc: "letters only", |
|
| 70 |
- id: "deadbeefcafe", |
|
| 71 |
- expected: false, |
|
| 72 |
- }, |
|
| 73 |
- {
|
|
| 74 |
- doc: "numbers only", |
|
| 75 |
- id: "012345678912", |
|
| 76 |
- expected: true, |
|
| 77 |
- }, |
|
| 78 |
- } |
|
| 79 |
- for _, tc := range tests {
|
|
| 80 |
- t.Run(tc.doc, func(t *testing.T) {
|
|
| 81 |
- if actual := allNum(tc.id); actual != tc.expected {
|
|
| 82 |
- t.Errorf("expected %q to be %t, got %t, ", tc.id, !tc.expected, actual)
|
|
| 83 |
- } |
|
| 84 |
- }) |
|
| 85 |
- } |
|
| 86 |
-} |
| ... | ... |
@@ -23,7 +23,6 @@ import ( |
| 23 | 23 |
|
| 24 | 24 |
"github.com/docker/docker/daemon/container" |
| 25 | 25 |
"github.com/docker/docker/pkg/ioutils" |
| 26 |
- "github.com/docker/docker/pkg/stringid" |
|
| 27 | 26 |
"github.com/docker/docker/pkg/tailfile" |
| 28 | 27 |
"github.com/docker/docker/testutil/request" |
| 29 | 28 |
"github.com/docker/go-connections/sockets" |
| ... | ... |
@@ -31,6 +30,7 @@ import ( |
| 31 | 31 |
"github.com/moby/moby/api/types/events" |
| 32 | 32 |
"github.com/moby/moby/api/types/system" |
| 33 | 33 |
"github.com/moby/moby/client" |
| 34 |
+ "github.com/moby/moby/client/pkg/stringid" |
|
| 34 | 35 |
"github.com/pkg/errors" |
| 35 | 36 |
"gotest.tools/v3/assert" |
| 36 | 37 |
"gotest.tools/v3/poll" |
| 37 | 38 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,47 @@ |
| 0 |
+// Package stringid provides helper functions for dealing with string identifiers. |
|
| 1 |
+// |
|
| 2 |
+// It is similar to the package used by the daemon, but for presentational |
|
| 3 |
+// purposes in the client. |
|
| 4 |
+package stringid |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "crypto/rand" |
|
| 8 |
+ "encoding/hex" |
|
| 9 |
+ "strings" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+const ( |
|
| 13 |
+ shortLen = 12 |
|
| 14 |
+ fullLen = 64 |
|
| 15 |
+) |
|
| 16 |
+ |
|
| 17 |
+// TruncateID returns a shorthand version of a string identifier for presentation. |
|
| 18 |
+// For convenience, it accepts both digests ("sha256:xxxx") and IDs without an
|
|
| 19 |
+// algorithm prefix. It truncates the algorithm (if any) before truncating the |
|
| 20 |
+// ID. The length of the truncated ID is currently fixed, but users should make |
|
| 21 |
+// no assumptions of this to not change; it is merely a prefix of the ID that |
|
| 22 |
+// provides enough uniqueness for common scenarios. |
|
| 23 |
+// |
|
| 24 |
+// Truncated IDs ("ID-prefixes") usually can be used to uniquely identify an
|
|
| 25 |
+// object (such as a container or network), but collisions may happen, in |
|
| 26 |
+// which case an "ambiguous result" error is produced. In case of a collision, |
|
| 27 |
+// the caller should try with a longer prefix or the full-length ID. |
|
| 28 |
+func TruncateID(id string) string {
|
|
| 29 |
+ if i := strings.IndexRune(id, ':'); i >= 0 {
|
|
| 30 |
+ id = id[i+1:] |
|
| 31 |
+ } |
|
| 32 |
+ if len(id) > shortLen {
|
|
| 33 |
+ id = id[:shortLen] |
|
| 34 |
+ } |
|
| 35 |
+ return id |
|
| 36 |
+} |
|
| 37 |
+ |
|
| 38 |
+// GenerateRandomID returns a unique, 64-character ID consisting of a-z, 0-9. |
|
| 39 |
+func GenerateRandomID() string {
|
|
| 40 |
+ b := make([]byte, 32) |
|
| 41 |
+ if _, err := rand.Read(b); err != nil {
|
|
| 42 |
+ panic(err) // This shouldn't happen |
|
| 43 |
+ } |
|
| 44 |
+ id := hex.EncodeToString(b) |
|
| 45 |
+ return id |
|
| 46 |
+} |
| ... | ... |
@@ -966,6 +966,7 @@ github.com/moby/moby/api/types/volume |
| 966 | 966 |
# github.com/moby/moby/client v0.0.0 => ./client |
| 967 | 967 |
## explicit; go 1.23.0 |
| 968 | 968 |
github.com/moby/moby/client |
| 969 |
+github.com/moby/moby/client/pkg/stringid |
|
| 969 | 970 |
# github.com/moby/patternmatcher v0.6.0 |
| 970 | 971 |
## explicit; go 1.19 |
| 971 | 972 |
github.com/moby/patternmatcher |