Skip to content

Commit

Permalink
more robust container names
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmdm committed May 28, 2021
1 parent f433d71 commit bb599ae
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 18 deletions.
8 changes: 1 addition & 7 deletions src/cmd/tidy/tidy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package tidy

import (
"context"
"fmt"
"path/filepath"
"strings"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -39,11 +37,7 @@ func run(ctx context.Context) error {
validNames[yey.ContainerName(contexts.Path, ctx)] = struct{}{}
}

prefix := fmt.Sprintf(
"yey-%s-%s",
filepath.Base(filepath.Dir(contexts.Path)),
yey.Hash(contexts.Path),
)
prefix := yey.ContainerPathPrefix(contexts.Path)

names, err := docker.ListContainers(ctx)
if err != nil {
Expand Down
12 changes: 6 additions & 6 deletions src/internal/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,32 +84,32 @@ func TestMerge(t *testing.T) {

func TestSameHashesForSameContexts(t *testing.T) {
ctx1 := getCtx1()
hash1 := Hash(ctx1.String())
hash1 := hash(ctx1.String())

ctx2 := getCtx1()
hash2 := Hash(ctx2.String())
hash2 := hash(ctx2.String())

assert.Equal(t, hash1, hash2)
}

func TestDifferentHashesForDifferentEnvs(t *testing.T) {
ctx1 := getCtx1()
hash1 := Hash(ctx1.String())
hash1 := hash(ctx1.String())

ctx2 := getCtx1()
ctx2.Env["ENV1"] = "value1b"
hash2 := Hash(ctx2.String())
hash2 := hash(ctx2.String())

assert.NotEqual(t, hash1, hash2)
}

func TestDifferentHashesForDifferentMounts(t *testing.T) {
ctx1 := getCtx1()
hash1 := Hash(ctx1.String())
hash1 := hash(ctx1.String())

ctx2 := getCtx1()
ctx2.Mounts["/local/mount1"] = "/container/mount1b"
hash2 := Hash(ctx2.String())
hash2 := hash(ctx2.String())

assert.NotEqual(t, hash1, hash2)
}
Expand Down
43 changes: 38 additions & 5 deletions src/internal/yey.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,53 @@ import (
"hash/crc64"
"io"
"path/filepath"
"regexp"
)

func Hash(value string) string {
var (
spaces = regexp.MustCompile(`\s+`)
special = regexp.MustCompile(`[^a-zA-Z0-9.\-_]`)
dashes = regexp.MustCompile(`-+`)
alphaNumericStart = regexp.MustCompile(`^[a-zA-Z0-9]`)
trailingDashes = regexp.MustCompile(`-+$`)
)

func hash(value string) string {
hasher := crc64.New(crc64.MakeTable(crc64.ECMA))
io.WriteString(hasher, value)
return hex.EncodeToString(hasher.Sum(nil))
}

func ContainerName(path string, context Context) string {
return fmt.Sprintf(
"yey-%s-%s-%s-%s",
filepath.Base(filepath.Dir(path)),
Hash(path),
"%s-%s-%s",
ContainerPathPrefix(path),
context.Name,
Hash(context.String()),
hash(context.String()),
)
}

func sanitizePathName(value string) string {
value = spaces.ReplaceAllString(value, "_")
value = special.ReplaceAllString(value, "")
value = dashes.ReplaceAllString(value, "-")
value = trailingDashes.ReplaceAllString(value, "")

if value == "" {
return ""
}

if !alphaNumericStart.MatchString(value) {
value = "0" + value
}

return value
}

func ContainerPathPrefix(path string) string {
pathBase := sanitizePathName(filepath.Base(filepath.Dir(path)))
if pathBase == "" {
return fmt.Sprintf("yey-%s", hash(path))
}
return fmt.Sprintf("yey-%s-%s", pathBase, hash(path))
}
89 changes: 89 additions & 0 deletions src/internal/yey_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package yey

import "testing"

func TestSanitizePathName(t *testing.T) {
testCases := []struct {
Name string
Value string
Expected string
}{
{
Name: "removes space from name",
Value: "my folder with spaces",
Expected: "my_folder_with_spaces",
},
{
Name: "strips invalid characters",
Value: "my&folder#cool*stuff!",
Expected: "myfoldercoolstuff",
},
{
Name: "padds with 0 if does not start with alphanumeric character",
Value: "_valid_if_not_for_underscore_start",
Expected: "0_valid_if_not_for_underscore_start",
},
{
Name: "reduces multidashes to single dash",
Value: "my---folder----path",
Expected: "my-folder-path",
},
{
Name: "strips trailing dashes from name",
Value: "my_folder----",
Expected: "my_folder",
},
{
Name: "empty string",
Value: "",
Expected: "",
},
{
Name: "full strip returns empty string",
Value: "$%^&",
Expected: "",
},
}

for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
actual := sanitizePathName(tc.Value)
if actual != tc.Expected {
t.Fatalf("expected %s but got: %s", tc.Expected, actual)
}
})
}
}

func TestContainerPathPrefix(t *testing.T) {
testCases := []struct {
Name string
Value string
Expected string
}{
{
Name: "simple base name with hash prefix",
Value: "/root/projectName/.yeyrc.yaml",
Expected: "yey-projectName-45c6afaff136ad78",
},
{
Name: "root path",
Value: "/.yeyrc.yaml",
Expected: "yey-8767bf26c174b05d",
},
{
Name: "path base that sanitizes to empty string",
Value: "/specialBase/#%!/.yeyrc.yaml",
Expected: "yey-19bd96cb89cf189c",
},
}

for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
actual := ContainerPathPrefix(tc.Value)
if actual != tc.Expected {
t.Fatalf("expected %s but got: %s", tc.Expected, actual)
}
})
}
}

0 comments on commit bb599ae

Please sign in to comment.