@@ -209,3 +209,88 @@ func TestValidateLabelValue(t *testing.T) {
209209 }
210210 }
211211}
212+
213+ // TestValidateDomain tests that only correct DNS subdomain names are accepted
214+ func TestValidateDomain (t * testing.T ) {
215+ cases := []struct {
216+ In string
217+ Valid bool
218+ }{
219+ // Valid domains
220+ {"" , true }, // empty is valid (means use default)
221+ {"example.com" , true }, // standard domain
222+ {"api.example.com" , true }, // subdomain
223+ {"my-app.example.com" , true }, // subdomain with hyphen
224+ {"app-123.example.com" , true }, // subdomain with number
225+ {"123.example.com" , true }, // label starting with number
226+ {"a.b.c.d.e.com" , true }, // many subdomains
227+ {"localhost" , true }, // single label (valid)
228+ {"cluster.local" , true }, // Kubernetes internal domain
229+ {"my-app-123.staging.example.com" , true }, // complex valid domain
230+ {"app.staging.v1.example.com" , true }, // multi-level subdomain
231+ {"example-app.com" , true }, // hyphen in domain
232+ {"a.co" , true }, // short domain
233+ {"123app.example.com" , true }, // label starting with number
234+ // Invalid domains
235+ {"Example.Com" , false }, // uppercase not allowed
236+ {"MY-APP.COM" , false }, // uppercase not allowed
237+ {"my_app.com" , false }, // underscore not allowed
238+ {"my app.com" , false }, // space not allowed
239+ {"invalid domain.com" , false }, // space not allowed
240+ {"my@app.com" , false }, // @ not allowed
241+ {"app!.com" , false }, // ! not allowed
242+ {"-example.com" , false }, // cannot start with hyphen
243+ {"example-.com" , false }, // label cannot end with hyphen
244+ {"example.-com.com" , false }, // label cannot start with hyphen
245+ {"my..app.com" , false }, // consecutive dots not allowed
246+ {".example.com" , false }, // cannot start with dot
247+ {"my:app.com" , false }, // colon not allowed
248+ {"my;app.com" , false }, // semicolon not allowed
249+ {"my,app.com" , false }, // comma not allowed
250+ {"my*app.com" , false }, // asterisk not allowed
251+ {" example.com" , false }, // leading whitespace not allowed
252+ {"example.com " , false }, // trailing whitespace not allowed
253+ {"example.com." , false }, // trailing dot not allowed
254+ {"example@domain.com" , false }, // @ not allowed
255+ {"ex!ample.com" , false }, // ! not allowed
256+ }
257+
258+ for _ , c := range cases {
259+ err := ValidateDomain (c .In )
260+ if err != nil && c .Valid {
261+ t .Fatalf ("Unexpected error for valid domain: %v, domain: '%v'" , err , c .In )
262+ }
263+ if err == nil && ! c .Valid {
264+ t .Fatalf ("Expected error for invalid domain: '%v'" , c .In )
265+ }
266+ }
267+ }
268+
269+ func TestValidateDomainErrMsg (t * testing.T ) {
270+ invalidDomain := "my@app.com"
271+ errMsgPrefix := fmt .Sprintf ("Domain '%v'" , invalidDomain )
272+
273+ err := ValidateDomain (invalidDomain )
274+ if err != nil {
275+ if ! strings .HasPrefix (err .Error (), errMsgPrefix ) {
276+ t .Fatalf ("Unexpected error message: %v, the message should start with '%v' string" , err .Error (), errMsgPrefix )
277+ }
278+ } else {
279+ t .Fatalf ("Expected error for invalid domain: %v" , invalidDomain )
280+ }
281+ }
282+
283+ // TestValidateDomainEmptyString ensures empty string is handled specially
284+ func TestValidateDomainEmptyString (t * testing.T ) {
285+ // Empty string should be valid (means use cluster default)
286+ err := ValidateDomain ("" )
287+ if err != nil {
288+ t .Fatalf ("Empty string should be valid (means use default): %v" , err )
289+ }
290+
291+ // String with only whitespace should error
292+ err = ValidateDomain (" " )
293+ if err == nil {
294+ t .Fatal ("String with only whitespace should be invalid" )
295+ }
296+ }
0 commit comments