From b4a43208eadfc603b10f600e16d7db789154202b Mon Sep 17 00:00:00 2001 From: Carl Montanari Date: Sat, 3 Feb 2024 15:53:04 -0800 Subject: [PATCH] fix: util to enforce rfc1123 name reqs for k8s things, apply that to volumes for deployments --- controllers/topology/deployment.go | 8 +++-- util/kubernetes/names.go | 37 +++++++++++++++++++++++ util/kubernetes/names_test.go | 47 ++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 3 deletions(-) diff --git a/controllers/topology/deployment.go b/controllers/topology/deployment.go index 5b7c6e19..c28f67bc 100644 --- a/controllers/topology/deployment.go +++ b/controllers/topology/deployment.go @@ -268,9 +268,11 @@ func (r *DeploymentReconciler) renderDeploymentVolumes( ) for _, podVolume := range volumesFromConfigMaps { - volumeName := clabernetesutilkubernetes.SafeConcatNameKubernetes( - podVolume.ConfigMapName, - podVolume.ConfigMapPath, + volumeName := clabernetesutilkubernetes.EnforceDNSLabelConvention( + clabernetesutilkubernetes.SafeConcatNameKubernetes( + podVolume.ConfigMapName, + podVolume.ConfigMapPath, + ), ) var mode *int32 diff --git a/util/kubernetes/names.go b/util/kubernetes/names.go index 10287fad..28d38d6b 100644 --- a/util/kubernetes/names.go +++ b/util/kubernetes/names.go @@ -3,7 +3,14 @@ package kubernetes import ( "crypto/sha256" "encoding/hex" + "regexp" "strings" + "sync" +) + +var ( + validDNSLabelConventionPatternsObj *validDNSLabelConventionPatterns //nolint:gochecknoglobals + validNSLabelConventionPatternsObjOnce sync.Once //nolint:gochecknoglobals ) const ( @@ -11,6 +18,24 @@ const ( NameMaxLen = 63 ) +type validDNSLabelConventionPatterns struct { + invalidChars *regexp.Regexp + startsWithNonAlpha *regexp.Regexp + endsWithNonAlpha *regexp.Regexp +} + +func getDNSLabelConventionPatterns() *validDNSLabelConventionPatterns { + validNSLabelConventionPatternsObjOnce.Do(func() { + validDNSLabelConventionPatternsObj = &validDNSLabelConventionPatterns{ + invalidChars: regexp.MustCompile(`[^a-z0-9\-]`), + startsWithNonAlpha: regexp.MustCompile(`^[^a-z]`), + endsWithNonAlpha: regexp.MustCompile(`[^a-z]$`), + } + }) + + return validDNSLabelConventionPatternsObj +} + // SafeConcatNameKubernetes concats all provided strings into a string joined by "-" - if the final // string is greater than 63 characters, the string will be shortened, and a hash will be used at // the end of the string to keep it unique, but safely within allowed lengths. @@ -32,3 +57,15 @@ func SafeConcatNameMax(name []string, max int) string { return finalName[0:max-8] + "-" + hex.EncodeToString(digest[0:])[0:7] } + +// EnforceDNSLabelConvention attempts to enforce the RFC 1123 label name requirements on s. +func EnforceDNSLabelConvention(s string) string { + p := getDNSLabelConventionPatterns() + + s = strings.ToLower(s) + s = p.invalidChars.ReplaceAllString(s, "-") + s = p.startsWithNonAlpha.ReplaceAllString(s, "z") + s = p.endsWithNonAlpha.ReplaceAllString(s, "z") + + return s +} diff --git a/util/kubernetes/names_test.go b/util/kubernetes/names_test.go index f679b551..152a873d 100644 --- a/util/kubernetes/names_test.go +++ b/util/kubernetes/names_test.go @@ -94,3 +94,50 @@ func TestSafeConcatNameMax(t *testing.T) { }) } } + +func TestEnforceDNSLabelConvention(t *testing.T) { + cases := []struct { + name string + in string + expected string + }{ + { + name: "simple", + in: "afinename", + expected: "afinename", + }, + { + name: "ending-with-non-alpha", + in: "afinename1", + expected: "afinenamez", + }, + { + name: "starting-with-non-alpha", + in: "1afinename", + expected: "zafinename", + }, + { + name: "special-chars", + in: "afine.name", + expected: "afine-name", + }, + { + name: "ending-starting-with-non-alpha-special-chars", + in: "1afine.name2", + expected: "zafine-namez", + }, + } + + for _, testCase := range cases { + t.Run( + testCase.name, + func(t *testing.T) { + t.Logf("%s: starting", testCase.name) + + actual := clabernetesutilkubernetes.EnforceDNSLabelConvention(testCase.in) + if actual != testCase.expected { + clabernetestesthelper.FailOutput(t, actual, testCase.expected) + } + }) + } +}