diff --git a/CHANGELOG.md b/CHANGELOG.md index ac63ba196..2d8bd53c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Changelog for Cass Operator, new PRs should update the `main / unreleased` secti ``` ## unreleased +* [BUGFIX] [#355](https://github.com/k8ssandra/cass-operator/issues/335) Cleanse label names derived from cluster name, which can contain illegal chars for label names. ## v1.11.0 diff --git a/pkg/oplabels/labels.go b/pkg/oplabels/labels.go index 33feb550c..3c5e7cb2c 100644 --- a/pkg/oplabels/labels.go +++ b/pkg/oplabels/labels.go @@ -5,8 +5,9 @@ package oplabels import ( "fmt" - api "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" + "regexp" + "strings" ) const ( @@ -20,13 +21,13 @@ const ( CreatedByLabel = "app.kubernetes.io/created-by" ) +var whitelistRegex = regexp.MustCompile(`(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?`) + func AddOperatorLabels(m map[string]string, dc *api.CassandraDatacenter) { m[ManagedByLabel] = ManagedByLabelValue m[NameLabel] = NameLabelValue m[VersionLabel] = dc.Spec.ServerVersion - - instanceName := fmt.Sprintf("cassandra-%s", dc.Spec.ClusterName) - m[InstanceLabel] = instanceName + m[InstanceLabel] = fmt.Sprintf("cassandra-%s", CleanLabelName(dc.Spec.ClusterName)) if len(dc.Spec.AdditionalLabels) != 0 { for key, value := range dc.Spec.AdditionalLabels { @@ -43,3 +44,12 @@ func HasManagedByCassandraOperatorLabel(m map[string]string) bool { v, ok := m[ManagedByLabel] return ok && v == ManagedByLabelValue } + +// CleanLabelName a valid label must be an empty string or consist of alphanumeric characters, +// '-', '_' or '.', and must start and end with an alphanumeric. +// Note: we apply a prefix of "cassandra-" to the cluster name value used as label name. +// As such, empty string isn't a valid case. +func CleanLabelName(labelName string) string { + var regexpResult = whitelistRegex.FindAllString(strings.Replace(labelName, " ", "", -1), -1) + return strings.Join(regexpResult, "") +} diff --git a/pkg/oplabels/labels_test.go b/pkg/oplabels/labels_test.go new file mode 100644 index 000000000..d49828548 --- /dev/null +++ b/pkg/oplabels/labels_test.go @@ -0,0 +1,63 @@ +package oplabels + +import ( + "github.com/stretchr/testify/require" + "regexp" + "strings" + "testing" +) + +/** +A valid label must be an empty string or consist of alphanumeric characters, +'-', '_' or '.', and must start and end with an alphanumeric. +*/ +func TestLabelNameClean(t *testing.T) { + + var cleaned = CleanLabelName("TestCluster") + require.EqualValues(t, "TestCluster", cleaned, + "expect label name to not be cleaned as no need") + + cleaned = CleanLabelName("Test Cluster") + require.EqualValues(t, "TestCluster", cleaned, + "expect space to be cleaned") + + cleaned = CleanLabelName("+!*(-_)cor @#$%^&rect_ LABEL.name-1=<>_?,.") + require.EqualValues(t, "correct_LABEL.name-1", cleaned, + "expect label name w/ outlier chars to be cleaned") + + cleaned = CleanLabelName("cor!@#$%^&*()rect__ LABEL.name") + require.EqualValues(t, "correct__LABEL.name", cleaned, + "expect label name w/ inside chars to be cleaned") + + cleaned = CleanLabelName("correct") + require.EqualValues(t, "correct", cleaned, + "expect label name without chars to be correct") + + cleaned = CleanLabelName("") + require.EqualValues(t, "", cleaned, + "expect label name as empty without chars to be correct") + + cleaned = CleanLabelName("-_!@#$%-^&*.()<>?._-&*.") + require.EqualValues(t, "", cleaned, + "expect label name as empty as contains all bad chars") + + cleaned = CleanLabelName("-_!@#$%-^&*.()<>?._-&*.X") + require.EqualValues(t, "X", cleaned, + "expect label name as last char only") + + cleaned = CleanLabelName("Y-_!@#$%-^&*.()<>?._-&*.") + require.EqualValues(t, "Y", cleaned, + "expect label name as first char only") +} + +func TestWhitelistRegex(t *testing.T) { + + var whitelistRegex = regexp.MustCompile(`(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?`) + var unclean = "+!*(-_)cor @#$%^&rect _ LABEL.name-1=<>_?,." + var regexpResult = whitelistRegex.FindAllString(strings.Replace(unclean, " ", "", -1), -1) + require.EqualValues(t, "correct_LABEL.name-1", strings.Join(regexpResult, "")) + + unclean = "+!*(-_)cor @#$ %^&re _c-t-.LABEL.name-1=<>_?,." + regexpResult = whitelistRegex.FindAllString(strings.Replace(unclean, " ", "", -1), -1) + require.EqualValues(t, "corre_c-t-.LABEL.name-1", strings.Join(regexpResult, "")) +}