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

Added handling of terminationGracePeriodSeconds to creation of systemd units #138

Merged
merged 3 commits into from
Apr 23, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 62 additions & 6 deletions src/provider/systemdmanager/systemdunit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ lazy_static! {
].iter().cloned().collect();
}

/// The default timeout for stopping a service, after this has passed systemd will terminate
/// the process
const DEFAULT_TERMINATION_TIMEOUT_SECS: i64 = 30;

/// List of sections in the systemd unit
///
/// The sections are written in the same order as listed here into the unit file.
Expand Down Expand Up @@ -190,14 +194,23 @@ impl SystemDUnit {
sections: Default::default(),
};

let restart_policy = match &pod.as_kube_pod().spec {
// if no restart policy is present we default to "never"
Some(spec) => spec.restart_policy.as_deref().unwrap_or("Never"),
None => "Never",
// Kubernetes does not allow creating pods without a spec, so if we do not get one here
//something is definitely seriously amiss
let pod_spec = match &pod.as_kube_pod().spec {
Some(spec) => spec,
None => {
return Err(PodValidationError {
msg: format!("Got pod without spec: [{}]", unit.name),
})
}
};

// if however one is specified but we do not know about this policy then we do not default
// to never but fail the service instead to avoid unpredictable behavior
// Get restart policy from pod, if none is specified default to "Never"
let restart_policy = pod_spec.restart_policy.as_deref().unwrap_or("Never");

// Lookup the equivalent systemd restart policy for the configured one
// If this lookup fails (which means a restart policy was specified which we do not know
// about) then we fail the entire service to avoid unpredictable behavior
let restart_policy = match RESTART_POLICY_MAP.get(restart_policy) {
Some(policy) => policy,
None => {
Expand All @@ -212,6 +225,29 @@ impl SystemDUnit {

unit.add_property(Section::Service, "Restart", restart_policy);

// If `terminationGracePeriodSeconds` was specified in the PodSpec set the value as
// 'TimeOutStopSec` on the systemd unit
// This means that the service will be killed after this period if it does not shutdown
// after receiving a stop command
// If it was not specified we use the default value for 'terminationGracePeriodSeconds' of
// 30 seconds, as this differs from the systemd default for 'TimeOutStopSec` which is 90
// seconds.
let termination_timeout = match pod_spec.termination_grace_period_seconds {
None => DEFAULT_TERMINATION_TIMEOUT_SECS,
Some(specified_timeout) => specified_timeout,
}
.to_string();

unit.add_property(Section::Service, "TimeoutStopSec", &termination_timeout);

if let Some(stop_timeout) = pod_spec.termination_grace_period_seconds {
unit.add_property(
Section::Service,
"TimeoutStopSec",
stop_timeout.to_string().as_str(),
);
}

if let Some(user_name) = SystemDUnit::get_user_name_from_pod_security_context(pod)? {
if !user_mode {
unit.add_property(Section::Service, "User", user_name);
Expand Down Expand Up @@ -478,6 +514,7 @@ mod test {
indoc! {"
[Service]
Restart=always
TimeoutStopSec=30
User=pod-user"}
)]
#[case::with_container_on_system_bus(
Expand Down Expand Up @@ -517,6 +554,7 @@ mod test {
Restart=no
StandardError=journal
StandardOutput=journal
TimeoutStopSec=30
User=container-user

[Install]
Expand Down Expand Up @@ -550,10 +588,28 @@ mod test {
Restart=no
StandardError=journal
StandardOutput=journal
TimeoutStopSec=30

[Install]
WantedBy=multi-user.target"#}
)]
#[case::set_termination_timeout(
BusType::System,
indoc! {"
apiVersion: v1
kind: Pod
metadata:
name: stackable
spec:
terminationGracePeriodSeconds: 10
containers: []"},
"stackable.service",
indoc! {"
[Service]
Restart=no
TimeoutStopSec=10"}
)]

fn create_unit_from_pod(
#[case] bus_type: BusType,
#[case] pod_config: &str,
Expand Down