Skip to content

Commit

Permalink
Rust scheduler: Config specification and parsing
Browse files Browse the repository at this point in the history
CMK-14520
  • Loading branch information
jherbel committed Sep 21, 2023
1 parent d0d4ce6 commit 8af73c6
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 54 deletions.
43 changes: 21 additions & 22 deletions v2/data/retry_rcc/windows.json
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
{
"working_directory": "/tmp/outputdir",
"results_directory": "/tmp/results",
"log_directory": "/tmp/logs",
"environment": {
"rcc_binary_path": "C:\\Users\\vagrant\\AppData\\Local\\Microsoft\\WindowsApps\\rcc.exe",
"scheduler_robot_yaml_path": "C:\\robotmk\\v2\\data\\scheduler_rcc\\robot.yaml"
},
"working_directory": "C:\\tmp\\output",
"results_directory": "C:\\tmp\\results",
"suites": {
"test": {
"execution_interval_seconds": 10,
"robot_target": "C:\\robotmk\\v2\\data\\retry_suite\\/tasks.robot",
"variants": [
{
"variablefile": null,
"argumentfile": null
},
{
"variablefile": "C:\\robotmk\\v2\\data\\retry_suite\\/retry_variables.yaml",
"argumentfile": null
}
],
"retry_strategy": "incremental",
"robot_yaml_path": "C:\\robotmk\\v2\\data\\retry_rcc\\/robot.yaml",
"session": null
"robot_framework_config": {
"robot_target": "C:\\robotmk\\v2\\data\\retry_suite\\tasks.robot",
"variable_file": "C:\\robotmk\\v2\\data\\retry_suite\\retry_variables.yaml",
"argument_file": null,
"retry_strategy": "Incremental"
},
"execution_config": {
"n_retries_max": 1,
"execution_interval_seconds": 10,
"timeout": 5
},
"environment_config": {
"type": "Rcc",
"binary_path": "C:\\Users\\vagrant\\AppData\\Local\\Microsoft\\WindowsApps\\rcc.exe",
"robocorp_home_path": "C:\\tmp\\ROBOCORP_HOME",
"robot_yaml_path": "C:\\robotmk\\v2\\data\\retry_rcc\\robot.yaml",
"build_timeout": 120
},
"session_config": {"type": "Current"}
}
}
}
29 changes: 13 additions & 16 deletions v2/data/retry_suite/windows.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
{
"working_directory": "/tmp/outputdir",
"results_directory": "/tmp/results",
"log_directory": "/tmp/logs",
"environment": "system_python",
"suites": {
"test": {
"execution_interval_seconds": 10,
"robot_target": "C:\\robotmk\\v2\\data\\retry_suite\\/tasks.robot",
"variants": [
{
"variablefile": null,
"argumentfile": null
},
{
"variablefile": "C:\\robotmk\\v2\\data\\retry_suite\\/retry_variables.yaml",
"argumentfile": null
}
],
"retry_strategy": "incremental",
"session": null
"robot_framework_config": {
"robot_target": "C:\\robotmk\\v2\\data\\retry_suite\\tasks.robot",
"variable_file": "C:\\robotmk\\v2\\data\\retry_suite\\retry_variables.yaml",
"argument_file": null,
"retry_strategy": "Incremental"
},
"execution_config": {
"n_retries_max": 1,
"execution_interval_seconds": 10,
"timeout": 5
},
"environment_config": {"type": "System"},
"session_config": {"type": "Current"}
}
}
}
48 changes: 36 additions & 12 deletions v2/rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion v2/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ clap = { version = "*", features = ["derive"] }
flexi_logger = "*"
log = "*"
quick-xml = { version = "0.30.0", features = ["serialize"] }
serde = { version = "1.0.188", features = ["serde_derive"] }
serde = { version = "1.0.188", features = ["derive"] }
serde_json = "*"
136 changes: 136 additions & 0 deletions v2/rust/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
use serde::Deserialize;
use serde_json::from_str;
use std::collections::HashMap;
use std::fs::read_to_string;
use std::path::{Path, PathBuf};

pub fn load(path: &Path) -> anyhow::Result<Config> {
Ok(from_str(&read_to_string(path)?)?)
}

#[derive(Deserialize)]
pub struct Config {
pub working_directory: PathBuf,
pub results_directory: PathBuf,
suites: HashMap<String, SuiteConfig>,
}

#[derive(Deserialize)]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub struct SuiteConfig {
pub robot_framework_config: RobotFrameworkConfig,
pub execution_config: ExecutionConfig,
pub environment_config: EnvironmentConfig,
pub session_config: SessionConfig,
}

#[derive(Deserialize)]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub struct RobotFrameworkConfig {
pub robot_target: PathBuf,
pub variable_file: Option<PathBuf>,
pub argument_file: Option<PathBuf>,
pub retry_strategy: RetryStrategy,
}

#[derive(Deserialize)]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub enum RetryStrategy {
Incremental,
Complete,
}

#[derive(Deserialize)]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub struct ExecutionConfig {
pub n_retries_max: usize,
pub execution_interval_seconds: u64,
pub timeout: u64,
}

#[derive(Deserialize)]
#[serde(tag = "type")]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub enum EnvironmentConfig {
System,
Rcc(RCCEnvironmentConfig),
}

#[derive(Deserialize)]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub struct RCCEnvironmentConfig {
pub binary_path: PathBuf,
pub robocorp_home_path: PathBuf,
pub robot_yaml_path: PathBuf,
pub build_timeout: u64,
}

#[derive(Deserialize)]
#[serde(tag = "type")]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub enum SessionConfig {
Current,
SpecificUser(UserSessionConfig),
}

#[derive(Deserialize)]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub struct UserSessionConfig {
pub user_name: String,
}

impl Config {
/// Return suites sorted by suite name
///
/// This makes environment reproducible, provided that you start with the same configuration.
pub fn suites(&self) -> Vec<(&String, &SuiteConfig)> {
let mut suites: Vec<(&String, &SuiteConfig)> = self.suites.iter().collect();
suites.sort_by_key(|(suite_name, _suite_config)| suite_name.to_string());
suites
}
}

#[cfg(test)]
mod tests {
use super::*;

fn create_suite_config(suite_name: &str) -> SuiteConfig {
SuiteConfig {
robot_framework_config: RobotFrameworkConfig {
robot_target: PathBuf::from(format!("/suite/{}/tasks.robot", suite_name)),
variable_file: None,
argument_file: None,
retry_strategy: RetryStrategy::Complete,
},
execution_config: ExecutionConfig {
n_retries_max: 1,
execution_interval_seconds: 300,
timeout: 60,
},
environment_config: EnvironmentConfig::System,
session_config: SessionConfig::Current,
}
}

fn create_config() -> Config {
Config {
working_directory: PathBuf::from("/working"),
results_directory: PathBuf::from("/results"),
suites: HashMap::from([
(String::from("suite_b"), create_suite_config("b")),
(String::from("suite_a"), create_suite_config("a")),
]),
}
}

#[test]
fn suites_sorted() {
assert_eq!(
create_config().suites(),
[
(&String::from("suite_a"), &create_suite_config("a")),
(&String::from("suite_b"), &create_suite_config("b"))
]
);
}
}
14 changes: 11 additions & 3 deletions v2/rust/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
#![allow(dead_code)]
pub mod attempt;
mod cli;
mod config;
mod logging;
pub mod parse_xml;

use anyhow::Context;
use clap::Parser;
use log::info;
pub mod parse_xml;
use log::{debug, info};
use logging::log_and_return_error;

fn main() -> anyhow::Result<()> {
let args = cli::Args::parse();
logging::init(args.log_specification(), &args.log_path)?;
info!("Program started and logging set up");

Ok(()).map_err(logging::log_and_return_error)
let _config = config::load(&args.config_path)
.context("Configuration loading failed")
.map_err(log_and_return_error)?;
debug!("Configuration loaded");

Ok(())
}

0 comments on commit 8af73c6

Please sign in to comment.