@@ -90,8 +90,7 @@ func (c *conditionUpdater) WithEventRecorder(recorder record.EventRecorder, verb
9090func (c * conditionUpdater ) UpdateCondition (conType string , status metav1.ConditionStatus , observedGeneration int64 , reason , message string ) * conditionUpdater {
9191 if reason == "" {
9292 // the metav1.Condition type requires a reason, so let's add a dummy if none is given
93- // the type field allows dots ('.'), while the reason field does not, so replace them with colons (':') (which are not allowed in the type field)
94- reason = strings .ReplaceAll (conType , "." , ":" ) + "_" + string (status )
93+ reason = ReplaceIllegalCharsInConditionReason (conType + "_" + string (status ))
9594 }
9695 con := metav1.Condition {
9796 Type : conType ,
@@ -263,3 +262,79 @@ func (c *conditionUpdater) Record(obj runtime.Object) *conditionUpdater {
263262
264263 return c
265264}
265+
266+ // ReplaceIllegalCharsInConditionType replaces all characters in the given string that are not allowed in condition types with underscores.
267+ func ReplaceIllegalCharsInConditionType (s string ) string {
268+ if s == "" {
269+ return s
270+ }
271+
272+ result := make ([]rune , 0 , len (s ))
273+ for _ , r := range s {
274+ // Valid characters for condition types are:
275+ // - lowercase letters (a-z)
276+ // - uppercase letters (A-Z)
277+ // - digits (0-9)
278+ // - underscore (_)
279+ // - hyphen (-)
280+ // - dot (.)
281+ // All other characters are replaced with underscore
282+ if (r >= 'a' && r <= 'z' ) ||
283+ (r >= 'A' && r <= 'Z' ) ||
284+ (r >= '0' && r <= '9' ) ||
285+ r == '_' ||
286+ r == '-' ||
287+ r == '.' {
288+ result = append (result , r )
289+ } else {
290+ result = append (result , '_' )
291+ }
292+ }
293+ return ensureStartsAndEndsWithLetter (string (result ), 'T' , 't' )
294+ }
295+
296+ // ReplaceIllegalCharsInConditionReason replaces all characters in the given string that are not allowed in condition reasons with underscores.
297+ func ReplaceIllegalCharsInConditionReason (s string ) string {
298+ if s == "" {
299+ return s
300+ }
301+
302+ result := make ([]rune , 0 , len (s ))
303+ for _ , r := range s {
304+ // Valid characters for condition types are:
305+ // - lowercase letters (a-z)
306+ // - uppercase letters (A-Z)
307+ // - digits (0-9)
308+ // - underscore (_)
309+ // - colon (:)
310+ //- comma (,)
311+ // All other characters are replaced with underscore
312+ if (r >= 'a' && r <= 'z' ) ||
313+ (r >= 'A' && r <= 'Z' ) ||
314+ (r >= '0' && r <= '9' ) ||
315+ r == '_' ||
316+ r == ':' ||
317+ r == ',' {
318+ result = append (result , r )
319+ } else {
320+ result = append (result , '_' )
321+ }
322+ }
323+ return ensureStartsAndEndsWithLetter (string (result ), 'R' , 'r' )
324+ }
325+
326+ func ensureStartsAndEndsWithLetter (s string , start , end rune ) string {
327+ if s == "" {
328+ return s
329+ }
330+ runes := []rune (s )
331+ // Ensure starts with letter
332+ if (runes [0 ] < 'a' || runes [0 ] > 'z' ) && (runes [0 ] < 'A' || runes [0 ] > 'Z' ) {
333+ runes = append ([]rune {start }, runes ... )
334+ }
335+ // Ensure ends with letter
336+ if (runes [len (runes )- 1 ] < 'a' || runes [len (runes )- 1 ] > 'z' ) && (runes [len (runes )- 1 ] < 'A' || runes [len (runes )- 1 ] > 'Z' ) {
337+ runes = append (runes , end )
338+ }
339+ return string (runes )
340+ }
0 commit comments