@@ -193,6 +193,9 @@ def __init__(self, *args, **kwargs):
193193 self .secret_name = self ._expand_user_properties (self .secret_name_template )
194194
195195 self .pvc_name = self ._expand_user_properties (self .pvc_name_template )
196+ self .notebook_container_name = self ._expand_user_properties (
197+ self .notebook_container_name_template
198+ )
196199 if self .working_dir :
197200 self .working_dir = self ._expand_user_properties (self .working_dir )
198201 if self .port == 0 :
@@ -760,6 +763,22 @@ def _deprecated_changed(self, change):
760763 """ ,
761764 )
762765
766+ notebook_container_name_template = Unicode (
767+ 'notebook' ,
768+ config = True ,
769+ help = """
770+ Template to use to form the name of the notebook container in the pod.
771+
772+ `{username}`, `{userid}`, `{servername}`, `{hubnamespace}`,
773+ `{unescaped_username}`, and `{unescaped_servername}` will be expanded if
774+ found within strings of this configuration. The username and servername
775+ come escaped to follow the `DNS label standard
776+ <https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names>`__.
777+
778+ Trailing `-` characters are stripped.
779+ """ ,
780+ )
781+
763782 @validate ('image_pull_secrets' )
764783 def _validate_image_pull_secrets (self , proposal ):
765784 if type (proposal ['value' ]) == str :
@@ -1859,6 +1878,9 @@ def _build_pod_labels(self, extra_labels):
18591878 'hub.jupyter.org/servername' : escapism .escape (
18601879 self .name , safe = self .safe_chars , escape_char = '-'
18611880 ).lower (),
1881+ # we put the container name in a label so if the template is updated we don't
1882+ # lose track of which pods are no longer running and leave stranded pods.
1883+ 'hub.jupyter.org/notebook_container_name' : self .notebook_container_name ,
18621884 }
18631885 )
18641886 return labels
@@ -2031,6 +2053,7 @@ async def get_pod_manifest(self):
20312053 ssl_secret_name = self .secret_name if self .internal_ssl else None ,
20322054 ssl_secret_mount_path = self .secret_mount_path ,
20332055 logger = self .log ,
2056+ notebook_container_name = self .notebook_container_name ,
20342057 )
20352058
20362059 def get_secret_manifest (self , owner_reference ):
@@ -2209,7 +2232,11 @@ async def poll(self):
22092232 return 1
22102233 for c in ctr_stat :
22112234 # return exit code if notebook container has terminated
2212- if c ["name" ] == 'notebook' :
2235+ notebook_container_name = pod ["metadata" ]["labels" ].get (
2236+ "hub.jupyter.org/notebook_container_name" , "notebook"
2237+ )
2238+
2239+ if c ["name" ] == notebook_container_name :
22132240 if "terminated" in c ["state" ]:
22142241 # call self.stop to delete the pod
22152242 if self .delete_stopped_pods :
0 commit comments