@@ -27,6 +27,10 @@ lazy_static! {
2727 ] . iter( ) . cloned( ) . collect( ) ;
2828}
2929
30+ /// The default timeout for stopping a service, after this has passed systemd will terminate
31+ /// the process
32+ const DEFAULT_TERMINATION_TIMEOUT_SECS : i64 = 30 ;
33+
3034/// List of sections in the systemd unit
3135///
3236/// The sections are written in the same order as listed here into the unit file.
@@ -190,14 +194,23 @@ impl SystemDUnit {
190194 sections : Default :: default ( ) ,
191195 } ;
192196
193- let restart_policy = match & pod. as_kube_pod ( ) . spec {
194- // if no restart policy is present we default to "never"
195- Some ( spec) => spec. restart_policy . as_deref ( ) . unwrap_or ( "Never" ) ,
196- None => "Never" ,
197+ // Kubernetes does not allow creating pods without a spec, so if we do not get one here
198+ //something is definitely seriously amiss
199+ let pod_spec = match & pod. as_kube_pod ( ) . spec {
200+ Some ( spec) => spec,
201+ None => {
202+ return Err ( PodValidationError {
203+ msg : format ! ( "Got pod without spec: [{}]" , unit. name) ,
204+ } )
205+ }
197206 } ;
198207
199- // if however one is specified but we do not know about this policy then we do not default
200- // to never but fail the service instead to avoid unpredictable behavior
208+ // Get restart policy from pod, if none is specified default to "Never"
209+ let restart_policy = pod_spec. restart_policy . as_deref ( ) . unwrap_or ( "Never" ) ;
210+
211+ // Lookup the equivalent systemd restart policy for the configured one
212+ // If this lookup fails (which means a restart policy was specified which we do not know
213+ // about) then we fail the entire service to avoid unpredictable behavior
201214 let restart_policy = match RESTART_POLICY_MAP . get ( restart_policy) {
202215 Some ( policy) => policy,
203216 None => {
@@ -212,6 +225,29 @@ impl SystemDUnit {
212225
213226 unit. add_property ( Section :: Service , "Restart" , restart_policy) ;
214227
228+ // If `terminationGracePeriodSeconds` was specified in the PodSpec set the value as
229+ // 'TimeOutStopSec` on the systemd unit
230+ // This means that the service will be killed after this period if it does not shutdown
231+ // after receiving a stop command
232+ // If it was not specified we use the default value for 'terminationGracePeriodSeconds' of
233+ // 30 seconds, as this differs from the systemd default for 'TimeOutStopSec` which is 90
234+ // seconds.
235+ let termination_timeout = match pod_spec. termination_grace_period_seconds {
236+ None => DEFAULT_TERMINATION_TIMEOUT_SECS ,
237+ Some ( specified_timeout) => specified_timeout,
238+ }
239+ . to_string ( ) ;
240+
241+ unit. add_property ( Section :: Service , "TimeoutStopSec" , & termination_timeout) ;
242+
243+ if let Some ( stop_timeout) = pod_spec. termination_grace_period_seconds {
244+ unit. add_property (
245+ Section :: Service ,
246+ "TimeoutStopSec" ,
247+ stop_timeout. to_string ( ) . as_str ( ) ,
248+ ) ;
249+ }
250+
215251 if let Some ( user_name) = SystemDUnit :: get_user_name_from_pod_security_context ( pod) ? {
216252 if !user_mode {
217253 unit. add_property ( Section :: Service , "User" , user_name) ;
@@ -478,6 +514,7 @@ mod test {
478514 indoc! { "
479515 [Service]
480516 Restart=always
517+ TimeoutStopSec=30
481518 User=pod-user" }
482519 ) ]
483520 #[ case:: with_container_on_system_bus(
@@ -517,6 +554,7 @@ mod test {
517554 Restart=no
518555 StandardError=journal
519556 StandardOutput=journal
557+ TimeoutStopSec=30
520558 User=container-user
521559
522560 [Install]
@@ -550,10 +588,28 @@ mod test {
550588 Restart=no
551589 StandardError=journal
552590 StandardOutput=journal
591+ TimeoutStopSec=30
553592
554593 [Install]
555594 WantedBy=multi-user.target"# }
556595 ) ]
596+ #[ case:: set_termination_timeout(
597+ BusType :: System ,
598+ indoc! { "
599+ apiVersion: v1
600+ kind: Pod
601+ metadata:
602+ name: stackable
603+ spec:
604+ terminationGracePeriodSeconds: 10
605+ containers: []" } ,
606+ "stackable.service" ,
607+ indoc! { "
608+ [Service]
609+ Restart=no
610+ TimeoutStopSec=10" }
611+ ) ]
612+
557613 fn create_unit_from_pod (
558614 #[ case] bus_type : BusType ,
559615 #[ case] pod_config : & str ,
0 commit comments