use std::{collections::BTreeMap, path::PathBuf}; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct CuddleFile { pub vars: CuddleVars, pub deployment: Option, pub components: Option, pub please: Option, } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct CuddleComponents { pub database: Option, pub assets: Option, pub packages: Option, } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct CuddleAssets { pub volumes: Option>, pub clean: Option, } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct CuddlePlease {} #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct Packages { pub debian: DebianPackages, } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct DebianPackages { pub dev: Vec, pub release: Vec, } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct CuddleAssetInclude { pub from: PathBuf, pub to: PathBuf, } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[serde(untagged)] pub enum CuddleDatabase { Enabled(bool), Values { migrations: PathBuf }, Default {}, } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct CuddleVars { pub service: String, pub registry: String, pub clusters: Option, } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct CuddleDeployment { pub registry: String, pub env: CuddleDeploymentEnv, } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct CuddleDeploymentEnv(pub BTreeMap); #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct CuddleDeploymentCluster { pub clusters: Vec, } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct CuddleClusters(pub BTreeMap); #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct CuddleCluster { pub namespace: String, } impl CuddleFile { pub async fn from_cuddle_file() -> eyre::Result { let cuddle_file_content = tokio::fs::read_to_string("cuddle.yaml").await?; Self::parse_cuddle_file(&cuddle_file_content) } pub fn parse_cuddle_file(content: &str) -> eyre::Result { let cuddle_file: CuddleFile = serde_yaml::from_str(content)?; Ok(cuddle_file) } } #[cfg(test)] mod test { use super::*; #[test] fn parse_file() { let cuddle_file = r#" base: "git@git.front.kjuulh.io:kjuulh/cuddle-base.git" vars: service: "infrastructure-example" registry: kasperhermansen clusters: clank_prod: replicas: "3" namespace: clank_prod deployment: registry: git@git.front.kjuulh.io:kjuulh/clank-clusters env: prod: clusters: - clank_prod components: database: true assets: volumes: - from: somewhere to: somewhere-else packages: debian: dev: - "capnp" release: - "capnp" scripts: render: type: shell args: cluster: name: cluster type: flag image_tag: name: image_tag type: flag"#; let res = CuddleFile::parse_cuddle_file(cuddle_file).expect("to parse file"); let mut clusters = BTreeMap::new(); clusters.insert( "clank_prod".into(), CuddleCluster { namespace: "clank_prod".into(), }, ); let mut deployment = BTreeMap::new(); deployment.insert( "prod".into(), CuddleDeploymentCluster { clusters: vec!["clank_prod".into()], }, ); let expected = CuddleFile { vars: CuddleVars { service: "infrastructure-example".into(), registry: "kasperhermansen".into(), clusters: Some(CuddleClusters(clusters)), }, deployment: Some(crate::cuddle_file::CuddleDeployment { registry: "git@git.front.kjuulh.io:kjuulh/clank-clusters".into(), env: CuddleDeploymentEnv(deployment), }), components: Some(CuddleComponents { database: Some(CuddleDatabase::Enabled(true)), assets: Some(CuddleAssets { volumes: Some(vec![CuddleAssetInclude { from: "somewhere".into(), to: "somewhere-else".into(), }]), clean: None, }), packages: Some(Packages { debian: DebianPackages { dev: vec!["capnp".into()], release: vec!["capnp".into()], }, }), }), please: None, }; pretty_assertions::assert_eq!(expected, res) } #[test] fn cuddle_database_default() { let cuddle_file = r#" base: "git@git.front.kjuulh.io:kjuulh/cuddle-base.git" vars: service: "infrastructure-example" registry: kasperhermansen components: database: {} "#; let res = CuddleFile::parse_cuddle_file(cuddle_file).expect("to parse file"); let expected = CuddleFile { vars: CuddleVars { service: "infrastructure-example".into(), registry: "kasperhermansen".into(), clusters: None, }, deployment: None, components: Some(CuddleComponents { database: Some(CuddleDatabase::Default {}), assets: None, packages: None, }), please: None, }; pretty_assertions::assert_eq!(expected, res) } #[test] fn cuddle_packages() { let cuddle_file = r#" base: "git@git.front.kjuulh.io:kjuulh/cuddle-base.git" vars: service: "infrastructure-example" registry: kasperhermansen components: packages: debian: dev: - "capnp" release: - "capnp" "#; let res = CuddleFile::parse_cuddle_file(cuddle_file).expect("to parse file"); let expected = CuddleFile { vars: CuddleVars { service: "infrastructure-example".into(), registry: "kasperhermansen".into(), clusters: None, }, deployment: None, components: Some(CuddleComponents { database: None, assets: None, packages: Some(Packages { debian: DebianPackages { dev: vec!["capnp".into()], release: vec!["capnp".into()], }, }), }), please: None, }; pretty_assertions::assert_eq!(expected, res) } }