@@ -478,16 +478,33 @@ def camelCaseify(s):
478478c .CryptKeeper .keys  =  get_secret_value ("hub.config.CryptKeeper.keys" ).split (";" )
479479
480480# load hub.config values, except potentially seeded secrets already loaded 
481- for  app , cfg  in  get_config ("hub.config" , {}).items ():
482-     if  app  ==  "JupyterHub" :
481+ for  section , cfg  in  get_config ("hub.config" , {}).items ():
482+     if  section  ==  "JupyterHub" :
483483        cfg .pop ("proxy_auth_token" , None )
484484        cfg .pop ("cookie_secret" , None )
485485        cfg .pop ("services" , None )
486-     elif  app  ==  "ConfigurableHTTPProxy" :
486+     elif  section  ==  "ConfigurableHTTPProxy" :
487487        cfg .pop ("auth_token" , None )
488-     elif  app  ==  "CryptKeeper" :
488+     elif  section  ==  "CryptKeeper" :
489489        cfg .pop ("keys" , None )
490-     c [app ].update (cfg )
490+ 
491+     if  not  section [:1 ].isupper ():
492+         # traitlets config sections are Configurable class names 
493+         # that MUST start with upper-case 
494+         # if it starts with lowercase, it must be a mistake 
495+         # (e.g. putting `hub.loadRoles` under `hub.config.loadRoles`), 
496+         # and will have no effect, so warn or raise here 
497+         print (
498+             f"FATAL: Invalid hub.config section name: { section }  ." 
499+             " hub.config sections must be Configurable class names (e.g. JupyterHub)." 
500+             " Maybe misplaced or misspelled config?" ,
501+             file = sys .stderr ,
502+         )
503+         # make this fatal: 
504+         sys .exit (1 )
505+ 
506+     print (f"Loading pass-through config section hub.config.{ section }  " )
507+     c [section ].update (cfg )
491508
492509# load /usr/local/etc/jupyterhub/jupyterhub_config.d config files 
493510config_dir  =  "/usr/local/etc/jupyterhub/jupyterhub_config.d" 
0 commit comments