mirror of
https://github.com/moby/moby.git
synced 2026-01-11 10:41:43 +00:00
pkg/stringid: move to daemon, and provide copy in client
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>
This commit is contained in:
18
pkg/stringid/alias.go
Normal file
18
pkg/stringid/alias.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// Package stringid provides helper functions for dealing with string identifiers.
|
||||
package stringid
|
||||
|
||||
import "github.com/moby/moby/client/pkg/stringid"
|
||||
|
||||
// TruncateID returns a shorthand version of a string identifier for presentation.
|
||||
//
|
||||
// Deprecated: use [stringid.TruncateID]. This package will be removed in the next release.
|
||||
func TruncateID(id string) string {
|
||||
return stringid.TruncateID(id)
|
||||
}
|
||||
|
||||
// GenerateRandomID returns a unique, 64-character ID consisting of a-z, 0-9.
|
||||
//
|
||||
// Deprecated: use [stringid.GenerateRandomID]. This package will be removed in the next release.
|
||||
func GenerateRandomID() string {
|
||||
return stringid.GenerateRandomID()
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
// Package stringid provides helper functions for dealing with string identifiers
|
||||
package stringid
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
shortLen = 12
|
||||
fullLen = 64
|
||||
)
|
||||
|
||||
// TruncateID returns a shorthand version of a string identifier for presentation.
|
||||
// For convenience, it accepts both digests ("sha256:xxxx") and IDs without an
|
||||
// algorithm prefix. It truncates the algorithm (if any) before truncating the
|
||||
// ID. The length of the truncated ID is currently fixed, but users should make
|
||||
// no assumptions of this to not change; it is merely a prefix of the ID that
|
||||
// provides enough uniqueness for common scenarios.
|
||||
//
|
||||
// Truncated IDs ("ID-prefixes") usually can be used to uniquely identify an
|
||||
// object (such as a container or network), but collisions may happen, in
|
||||
// which case an "ambiguous result" error is produced. In case of a collision,
|
||||
// the caller should try with a longer prefix or the full-length ID.
|
||||
func TruncateID(id string) string {
|
||||
if i := strings.IndexRune(id, ':'); i >= 0 {
|
||||
id = id[i+1:]
|
||||
}
|
||||
if len(id) > shortLen {
|
||||
id = id[:shortLen]
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// GenerateRandomID returns a unique, 64-character ID consisting of a-z, 0-9.
|
||||
// It guarantees that the ID, when truncated ([TruncateID]) does not consist
|
||||
// of numbers only, so that the truncated ID can be used as hostname for
|
||||
// containers.
|
||||
func GenerateRandomID() string {
|
||||
b := make([]byte, 32)
|
||||
for {
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
panic(err) // This shouldn't happen
|
||||
}
|
||||
id := hex.EncodeToString(b)
|
||||
|
||||
// make sure that the truncated ID does not consist of only numeric
|
||||
// characters, as it's used as default hostname for containers.
|
||||
//
|
||||
// See:
|
||||
// - https://github.com/moby/moby/issues/3869
|
||||
// - https://bugzilla.redhat.com/show_bug.cgi?id=1059122
|
||||
if allNum(id[:shortLen]) {
|
||||
// all numbers; try again
|
||||
continue
|
||||
}
|
||||
return id
|
||||
}
|
||||
}
|
||||
|
||||
// allNum checks whether id consists of only numbers (0-9).
|
||||
func allNum(id string) bool {
|
||||
for _, c := range []byte(id) {
|
||||
if c > '9' || c < '0' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package stringid
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGenerateRandomID(t *testing.T) {
|
||||
id := GenerateRandomID()
|
||||
|
||||
if len(id) != fullLen {
|
||||
t.Fatalf("Id returned is incorrect: %s", id)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTruncateID(t *testing.T) {
|
||||
tests := []struct {
|
||||
doc, id, expected string
|
||||
}{
|
||||
{
|
||||
doc: "empty ID",
|
||||
id: "",
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
// IDs are expected to be 12 (short) or 64 characters, and not be numeric only,
|
||||
// but TruncateID should handle these gracefully.
|
||||
doc: "invalid ID",
|
||||
id: "1234",
|
||||
expected: "1234",
|
||||
},
|
||||
{
|
||||
doc: "full ID",
|
||||
id: "90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2",
|
||||
expected: "90435eec5c4e",
|
||||
},
|
||||
{
|
||||
doc: "digest",
|
||||
id: "sha256:90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2",
|
||||
expected: "90435eec5c4e",
|
||||
},
|
||||
{
|
||||
doc: "very long ID",
|
||||
id: "90435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a290435eec5c4e124e741ef731e118be2fc799a68aba0466ec17717f24ce2ae6a2",
|
||||
expected: "90435eec5c4e",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
actual := TruncateID(tc.id)
|
||||
if actual != tc.expected {
|
||||
t.Errorf("expected: %q, got: %q", tc.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllNum(t *testing.T) {
|
||||
tests := []struct {
|
||||
doc, id string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
doc: "mixed letters and numbers",
|
||||
id: "4e38e38c8ce0",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
doc: "letters only",
|
||||
id: "deadbeefcafe",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
doc: "numbers only",
|
||||
id: "012345678912",
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
if actual := allNum(tc.id); actual != tc.expected {
|
||||
t.Errorf("expected %q to be %t, got %t, ", tc.id, !tc.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user