Skip to content
This repository was archived by the owner on Dec 21, 2021. It is now read-only.

Commit 0401637

Browse files
authored
Added handling of terminationGracePeriodSeconds to creation of systemd units (#138)
Added handling of terminationGracePeriodSeconds to creation of systemd units. The value for this field from the PodSpec is translated to the systemd config TimeoutStopSec This will cause the service to be killed by systemd if it does not shutdown within the time in seconds specified by this parameter. Default value for this parameter is 30 seconds, if terminationGracePeriodSeconds this is not specified in the unit file and this default stays in effect.
1 parent 654bed0 commit 0401637

File tree

1 file changed

+62
-6
lines changed

1 file changed

+62
-6
lines changed

src/provider/systemdmanager/systemdunit.rs

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)