use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Runner {
pub id: u64,
pub description: String,
#[serde(default)]
pub ip_address: Option<String>,
pub active: bool,
#[serde(default)]
pub online: bool,
pub status: RunnerStatus,
pub runner_type: RunnerType,
#[serde(default)]
pub is_shared: bool,
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub tag_list: Vec<String>,
#[serde(default)]
pub version: Option<String>,
#[serde(default)]
pub architecture: Option<String>,
#[serde(default)]
pub platform: Option<String>,
#[serde(default)]
pub contacted_at: Option<DateTime<Utc>>,
#[serde(default)]
pub maximum_timeout: Option<u64>,
#[serde(default)]
pub run_untagged: bool,
#[serde(default)]
pub locked: bool,
#[serde(default)]
pub access_level: Option<String>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
pub enum RunnerStatus {
Online,
Offline,
Paused,
#[serde(other)]
Unknown,
}
impl RunnerStatus {
pub fn is_available(self) -> bool {
self == Self::Online
}
}
impl std::fmt::Display for RunnerStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Online => write!(f, "online"),
Self::Offline => write!(f, "offline"),
Self::Paused => write!(f, "paused"),
Self::Unknown => write!(f, "unknown"),
}
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
pub enum RunnerType {
#[serde(rename = "instance_type")]
Instance,
#[serde(rename = "group_type")]
Group,
#[serde(rename = "project_type")]
Project,
}
impl std::fmt::Display for RunnerType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Instance => write!(f, "instance"),
Self::Group => write!(f, "group"),
Self::Project => write!(f, "project"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_runner_status_is_available() {
assert!(RunnerStatus::Online.is_available());
assert!(!RunnerStatus::Offline.is_available());
assert!(!RunnerStatus::Paused.is_available());
}
#[test]
fn test_runner_status_display() {
assert_eq!(RunnerStatus::Online.to_string(), "online");
assert_eq!(RunnerStatus::Offline.to_string(), "offline");
assert_eq!(RunnerStatus::Paused.to_string(), "paused");
}
#[test]
fn test_runner_type_display() {
assert_eq!(RunnerType::Instance.to_string(), "instance");
assert_eq!(RunnerType::Group.to_string(), "group");
assert_eq!(RunnerType::Project.to_string(), "project");
}
#[test]
fn test_runner_status_serialization() {
let status = RunnerStatus::Online;
let json = serde_json::to_string(&status).unwrap();
assert_eq!(json, "\"online\"");
let deserialized: RunnerStatus = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized, RunnerStatus::Online);
}
#[test]
fn test_runner_type_serialization() {
let runner_type = RunnerType::Instance;
let json = serde_json::to_string(&runner_type).unwrap();
assert_eq!(json, "\"instance_type\"");
let deserialized: RunnerType = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized, RunnerType::Instance);
}
}