depl 2.4.3

Toolkit for a bunch of local and remote CI/CD actions
Documentation
//! Systemd service options module.

use serde::{Deserialize, Serialize};

/// Pipeline run user.
#[derive(Deserialize, Serialize, PartialEq, Eq, Clone, Default)]
#[serde(rename_all = "snake_case", tag = "type")]
pub enum SystemdRunUser {
  /// Root user. Tells not to specify `User` field in systemd service file.
  Root {
    /// Use current user's cache && storage folders.
    #[serde(default = "crate::utils::yes", skip_serializing_if = "crate::utils::is_true")]
    preserve_current_cache: bool,
  },
  /// Specifies `User` field in systemd service file as current user (who run `depl export pipeline my-pipe --systemd`).
  #[default]
  CurrentUser,
  /// Another user. Specifies `User` field in systemd service file.
  Another {
    /// User name.
    username: String,
    /// Use current user's cache & storage folders.
    #[serde(default = "crate::utils::yes", skip_serializing_if = "crate::utils::is_true")]
    preserve_current_cache: bool,
  },
}

impl SystemdRunUser {
  /// Specifies to use cache & storage options or not.
  pub fn preserve_current_cache_rule(&self) -> bool {
    match self {
      Self::CurrentUser => false,
      Self::Root { preserve_current_cache } => *preserve_current_cache,
      Self::Another {
        preserve_current_cache, ..
      } => *preserve_current_cache,
    }
  }

  /// Returns `User` systemd service string if needed, or just an empty string.
  /// If specified `SystemdRunUser::CurrentUser`, tries to get current Linux user.
  pub fn user_name_rule(&self) -> anyhow::Result<String> {
    match self {
      Self::Root { .. } => Ok(String::new()),
      Self::Another { username, .. } => Ok(format!("User={username}")),
      Self::CurrentUser => {
        let user_uid = nix::unistd::getuid();
        let user = nix::unistd::User::from_uid(user_uid)?.expect("Can't get current user name by UID!");
        Ok(format!("User={}", user.name))
      }
    }
  }
}

/// Systemd service options.
#[derive(Deserialize, Serialize, PartialEq, Eq, Clone)]
pub struct SystemdOpts {
  /// Use shell specified in `DEPLOYER_SH_PATH` environment variable. Default is true.
  #[serde(default = "crate::utils::yes", skip_serializing_if = "crate::utils::is_true")]
  pub use_defined_shell: bool,
  /// Pipeline options (e.g., run in Docker/Podman or with Ansible, see `depl run --help` for other options).
  #[serde(default, skip_serializing_if = "String::is_empty")]
  pub cli_options: String,
  /// Run as user. Default is `root` or your main administrator.
  #[serde(default)]
  pub user: SystemdRunUser,
  /// Dependencies (`After` field in `Unit` section).
  #[serde(default, skip_serializing_if = "Vec::is_empty")]
  pub after: Vec<String>,
  /// Restart interval for periodic re-runs (e.g., "30s", "5m", "2h"). When set, the service will automatically restart after each execution.
  #[serde(default, skip_serializing_if = "Option::is_none")]
  pub restart_interval: Option<String>,
}

impl Default for SystemdOpts {
  fn default() -> Self {
    Self {
      use_defined_shell: true,
      user: SystemdRunUser::default(),
      cli_options: Default::default(),
      after: Default::default(),
      restart_interval: None,
    }
  }
}