github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/pkg/apis/identifiers.go (about)

     1  package apis
     2  
     3  import (
     4  	"encoding/hex"
     5  	"hash/fnv"
     6  	"regexp"
     7  	"strings"
     8  
     9  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  
    11  	"k8s.io/apimachinery/pkg/types"
    12  
    13  	"k8s.io/apimachinery/pkg/api/validation/path"
    14  	"k8s.io/apimachinery/pkg/util/validation"
    15  )
    16  
    17  const MaxNameLength = validation.DNS1123SubdomainMaxLength
    18  
    19  var invalidLabelCharacters = regexp.MustCompile("[^-A-Za-z0-9_.]")
    20  
    21  var invalidPathCharacters = regexp.MustCompile(`[` + strings.Join(path.NameMayNotContain, "") + `]`)
    22  
    23  type KeyableObject interface {
    24  	GetName() string
    25  	GetNamespace() string
    26  }
    27  
    28  func Key(o KeyableObject) types.NamespacedName {
    29  	return types.NamespacedName{Name: o.GetName(), Namespace: o.GetNamespace()}
    30  }
    31  
    32  func KeyFromMeta(objMeta metav1.ObjectMeta) types.NamespacedName {
    33  	return types.NamespacedName{Name: objMeta.Name, Namespace: objMeta.Namespace}
    34  }
    35  
    36  // SanitizeLabel ensures a value is suitable as both a label key and value.
    37  func SanitizeLabel(name string) string {
    38  	sanitized := invalidLabelCharacters.ReplaceAllString(name, "_")
    39  	max := validation.LabelValueMaxLength
    40  	if len(sanitized) > max {
    41  		var sb strings.Builder
    42  		sb.Grow(max)
    43  		sb.WriteString(sanitized[:max-9])
    44  		sb.WriteRune('-')
    45  		sb.WriteString(hashValue(name))
    46  		sanitized = sb.String()
    47  	}
    48  	return sanitized
    49  }
    50  
    51  // SanitizeName ensures a value is suitable for usage as an apiserver identifier.
    52  func SanitizeName(name string) string {
    53  	sanitized := name
    54  	if len(path.IsValidPathSegmentName(name)) != 0 {
    55  		for _, invalidName := range path.NameMayNotBe {
    56  			if name == invalidName {
    57  				// the only strictly invalid names are `.` and `..` so this is sufficient
    58  				return strings.ReplaceAll(name, ".", "_")
    59  			}
    60  		}
    61  		sanitized = invalidPathCharacters.ReplaceAllString(sanitized, "_")
    62  	}
    63  	if len(sanitized) > MaxNameLength {
    64  		var sb strings.Builder
    65  		sb.Grow(MaxNameLength)
    66  		sb.WriteString(sanitized[:MaxNameLength-9])
    67  		sb.WriteRune('-')
    68  		sb.WriteString(hashValue(name))
    69  		sanitized = sb.String()
    70  	}
    71  	return sanitized
    72  }
    73  
    74  func hashValue(v string) string {
    75  	h := fnv.New32a()
    76  	_, _ = h.Write([]byte(v))
    77  	return hex.EncodeToString(h.Sum(nil))
    78  }