knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/kmeta/names.go (about) 1 /* 2 copyright 2019 the knative authors 3 4 licensed under the apache license, version 2.0 (the "license"); 5 you may not use this file except in compliance with the license. 6 you may obtain a copy of the license at 7 8 http://www.apache.org/licenses/license-2.0 9 10 unless required by applicable law or agreed to in writing, software 11 distributed under the license is distributed on an "as is" basis, 12 without warranties or conditions of any kind, either express or implied. 13 see the license for the specific language governing permissions and 14 limitations under the license. 15 */ 16 17 package kmeta 18 19 import ( 20 "crypto/md5" //nolint:gosec // No strong cryptography needed. 21 "encoding/hex" 22 "fmt" 23 "regexp" 24 ) 25 26 // The longest name supported by the K8s is 63. 27 // These constants 28 const ( 29 longest = 63 30 md5Len = 32 31 head = longest - md5Len // How much to truncate to fit the hash. 32 ) 33 34 var isAlphanumeric = regexp.MustCompile(`^[a-zA-Z0-9]*$`) 35 36 // ChildName generates a name for the resource based upon the parent resource and suffix. 37 // If the concatenated name is longer than K8s permits the name is hashed and truncated to permit 38 // construction of the resource, but still keeps it unique. 39 // If the suffix itself is longer than 31 characters, then the whole string will be hashed 40 // and `parent|hash|suffix` will be returned, where parent and suffix will be trimmed to 41 // fit (prefix of parent at most of length 31, and prefix of suffix at most length 30). 42 func ChildName(parent, suffix string) string { 43 n := parent 44 if len(parent) > (longest - len(suffix)) { 45 // If the suffix is longer than the longest allowed suffix, then 46 // we hash the whole combined string and use that as the suffix. 47 if head-len(suffix) <= 0 { 48 //nolint:gosec // No strong cryptography needed. 49 h := md5.Sum([]byte(parent + suffix)) 50 // 1. trim parent, if needed 51 if head < len(parent) { 52 parent = parent[:head] 53 } 54 // Format the return string, if it's shorter than longest: pad with 55 // beginning of the suffix. This happens, for example, when parent is 56 // short, but the suffix is very long. 57 ret := parent + hex.EncodeToString(h[:]) 58 if d := longest - len(ret); d > 0 { 59 ret += suffix[:d] 60 } 61 return makeValidName(ret) 62 } 63 //nolint:gosec // No strong cryptography needed. 64 n = fmt.Sprintf("%s%x", parent[:head-len(suffix)], md5.Sum([]byte(parent))) 65 } 66 return n + suffix 67 } 68 69 // If due to trimming above we're terminating the string with a non-alphanumeric 70 // character, remove it. 71 func makeValidName(n string) string { 72 for i := len(n) - 1; !isAlphanumeric.MatchString(string(n[i])); i-- { 73 n = n[:len(n)-1] 74 } 75 return n 76 }