Skip to content

Commit

Permalink
Truncate long service names to 63 characters
Browse files Browse the repository at this point in the history
In some environments, the combination of cluster name and hostname
can get long enough that a service name exceeds 63 characters. This
is not allowed by the dns library, so we need to ensure that we never
pass it such long names.

This change shortens the name by hashing it to 32 characters, then
sandwiching that between the first 15 and last 16 characters of the
original name. This way the likely unique parts of the name are
preserved, but the total length of the name is shortened to an
allowable length. Something similar to kubernetes->k8s.
  • Loading branch information
cybertron authored and openshift-cherrypick-robot committed Jul 19, 2021
1 parent 207a7e5 commit d01e6a5
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
20 changes: 19 additions & 1 deletion pkg/publisher/publisher.go
@@ -1,6 +1,7 @@
package publisher

import (
"crypto/sha256"
"fmt"
"net"
"sync"
Expand All @@ -14,7 +15,8 @@ var log = logrus.New()

func Publish(ip net.IP, iface net.Interface, service Service, shutdown chan struct{}, waitGroup *sync.WaitGroup) (err error) {
defer waitGroup.Done()
svcEntry := zeroconf.NewServiceEntry(service.Name, service.SvcType, service.Domain)
svcName := truncateLongServiceName(service.Name)
svcEntry := zeroconf.NewServiceEntry(svcName, service.SvcType, service.Domain)
svcEntry.Port = service.Port
if ip.To4() != nil {
svcEntry.AddrIPv4 = append(svcEntry.AddrIPv4, ip)
Expand Down Expand Up @@ -105,6 +107,22 @@ func SetLogLevel(level logrus.Level) {
log.SetLevel(level)
}

// Service names cannot be longer than 63 characters. If we get a service name
// that is longer, hash it to 32 characters, and sandwich that between the
// first 15 and last 16 characters of the original name. This way we preserve
// the likely unique parts of the name while ensuring it does not exceed
// the 63 character limit.
func truncateLongServiceName(serviceName string) (svcName string) {
svcName = serviceName
if len(svcName) > 63 {
value := sha256.Sum256([]byte(svcName))
hexValue := fmt.Sprintf("%x", value)[:32]
svcName = svcName[:15] + string(hexValue[:]) + svcName[len(svcName)-16:]
log.Printf("Truncating long service name '%s' to '%s'", serviceName, svcName)
}
return svcName
}

// networkInterfacer defines an interface for several net library functions. Production
// code will forward to net library functions, and unit tests will override the methods
// for testing purposes.
Expand Down
20 changes: 20 additions & 0 deletions pkg/publisher/publisher_test.go
Expand Up @@ -163,3 +163,23 @@ func (networkInterfaceWithInvalidAddr) Addrs(intf *net.Interface) ([]net.Addr, e
func (networkInterfaceWithInvalidAddr) Interfaces() ([]net.Interface, error) {
return []net.Interface{upIntf}, nil
}

func TestLongNameTruncation(t *testing.T) {
testCases := []struct {
tcase string
name string
expected string
}{
{"short name", "master-0", "master-0"},
{"long name", "prefix-someverylongservicenamethatwouldcauseaproblemfordns-suffix", "prefix-somevery47540ff49304816bc5054bb4f3cc9a9clemfordns-suffix"},
}
for _, tc := range testCases {
result := truncateLongServiceName(tc.name)
if result != tc.expected {
t.Errorf("case[%v]: expected %v, got %v", tc.tcase, tc.expected, result)
}
if len(result) > 63 {
t.Errorf("case[%v]: Truncated name too long: '%v' is %d characters long", tc.tcase, result, len(result))
}
}
}

0 comments on commit d01e6a5

Please sign in to comment.