Skip to content

Commit

Permalink
Test deployment plan
Browse files Browse the repository at this point in the history
  • Loading branch information
byrnedo committed Oct 28, 2024
1 parent c94bf61 commit d3faf45
Show file tree
Hide file tree
Showing 14 changed files with 174 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/filestore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub struct FileStore {
}


#[derive(Tabled, Debug, Clone, Deserialize, Serialize)]
#[derive(Tabled, Debug, Clone, PartialEq, Deserialize, Serialize)]
#[tabled(rename_all = "UPPERCASE")]
pub struct ObjectListItem {
pub resource_type: ResourceType,
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ mod rollout;
mod resource;
mod exec;
pub mod deps;
mod test_mocks;
mod test_helpers;

pub use skate::skate;
pub use skate::AllDeps;
Expand Down
1 change: 0 additions & 1 deletion src/refresh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ impl<D: RefreshDeps> Refresh<D> {
Ok(state) => state,
Err(_) => ClusterState {
cluster_name: cluster_name.to_string(),
hash: "".to_string(),
nodes: vec![],
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub enum ResourceType {
ClusterIssuer,
}

#[derive(Debug, Serialize, Deserialize, Display, Clone)]
#[derive(Debug, PartialEq, Serialize, Deserialize, Display, Clone)]
pub enum SupportedResources {
#[strum(serialize = "Pod")]
Pod(Pod),
Expand Down
93 changes: 87 additions & 6 deletions src/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl OpType {
}
}

#[derive(Debug, Clone)]
#[derive(Debug, PartialEq, Clone)]
pub struct ScheduledOperation {
pub resource: SupportedResources,
pub node: Option<NodeState>,
Expand Down Expand Up @@ -88,6 +88,7 @@ impl ScheduledOperation {
}
}

#[derive(Debug, PartialEq)]
pub struct ApplyPlan {
pub actions: HashMap<NamespacedName, Vec<ScheduledOperation>>,
}
Expand Down Expand Up @@ -215,7 +216,6 @@ impl DefaultScheduler {
actions.insert(name, vec!(op));
}
};

}
}

Expand Down Expand Up @@ -754,10 +754,9 @@ impl DefaultScheduler {

remove_result
}


async fn apply(plan: ApplyPlan, conns: &SshClients, state: &mut ClusterState, dry_run:bool) -> Result<Vec<ScheduledOperation>, Box<dyn Error>> {


async fn apply(plan: ApplyPlan, conns: &SshClients, state: &mut ClusterState, dry_run: bool) -> Result<Vec<ScheduledOperation>, Box<dyn Error>> {
let mut result: Vec<ScheduledOperation> = vec!();

for (_name, ops) in plan.actions {
Expand Down Expand Up @@ -877,7 +876,7 @@ impl DefaultScheduler {
if plan.actions.is_empty() {
return Err(anyhow!("failed to schedule resources, no planned actions").into());
}

Self::apply(plan, conns, state, dry_run).await
}
}
Expand All @@ -903,3 +902,85 @@ impl Scheduler for DefaultScheduler {
Ok(results)
}
}

#[cfg(test)]
mod tests {
use k8s_openapi::api::apps::v1::DeploymentSpec;
use k8s_openapi::api::core::v1::{Container, PodSpec, PodTemplateSpec};
use crate::test_helpers;
use super::*;

#[test]
fn test_plan_deployment() {

let state = ClusterState {
cluster_name: "test".to_string(),
nodes: vec!(
test_helpers::objects::node_state("node-1"),
test_helpers::objects::node_state("node-2"),
),
};

let pod_template = PodTemplateSpec {
metadata: Some(NamespacedName::new("dpl-foo-1", "foo_namespace").into()),
spec: Some(PodSpec {
containers: vec![
Container {
args: Some(vec!("arg1".to_string())),
command: Some(vec!("cmd".to_string())),
name: "container1".to_string(),
..Default::default()
}
],
..Default::default()
}),
};

let deployment = Deployment {
metadata: NamespacedName::new("foo", "foo-namespace").into(),
spec: Some(DeploymentSpec {
replicas: Some(2),
template: pod_template.clone(),
..Default::default()
}),
..Default::default()
};


let result = DefaultScheduler::plan_deployment(&state, &deployment);
assert_eq!(true, result.is_ok());


let ns_name = NamespacedName { name: "foo".to_string(), namespace: "foo-namespace".to_string() };

let result = &result.unwrap();
assert_eq!(1, result.actions.len());

let ops = result.actions.get(&ns_name);
assert_eq!(true, ops.is_some());

let ops = ops.unwrap();
assert_eq!(4, ops.len());

let deployment_ops =ops.iter().filter(|o| match o.resource {
SupportedResources::Deployment(_) => true,
_ => false,
}).collect_vec();
assert_eq!(2, deployment_ops.len());
assert_eq!(true, deployment_ops.iter().all(|o|
o.operation == OpType::Create
&& o.node.is_some() && !o.node.as_ref().unwrap().node_name.is_empty()
));

let pod_ops =ops.iter().filter(|o| match o.resource {
SupportedResources::Pod(_) => true,
_ => false,
}).collect_vec();
assert_eq!(2, pod_ops.len());
assert_eq!(true, pod_ops.iter().all(|o|
o.operation == OpType::Create
&& o.node.is_none()
));

}
}
7 changes: 4 additions & 3 deletions src/skate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ pub async fn skate<D: AllDeps>(deps: D) -> Result<(), SkateError> {
}


#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq,Default, Serialize, Deserialize)]
pub struct Platform {
pub arch: String,
pub distribution: Distribution,
Expand All @@ -149,8 +149,9 @@ impl Display for Platform {
}
}

#[derive(Debug, Clone, Serialize, Deserialize, Display)]
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize, Display)]
pub enum Distribution {
#[default]
Unknown,
Debian,
Raspbian,
Expand Down Expand Up @@ -184,7 +185,7 @@ mod tests {
use crate::rollout::RolloutDeps;
use crate::skate::{skate_with_args, Cli, ConfigFileArgs};
use crate::skate::Commands::Refresh;
use crate::test_mocks::MockSshManager;
use crate::test_helpers::ssh_mocks::MockSshManager;

struct TestDeps{}

Expand Down
4 changes: 2 additions & 2 deletions src/skatelet/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ pub async fn system<D: SystemDeps>(deps: D, args: SystemArgs) -> Result<(), Skat
Ok(())
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DiskInfo {
pub available_space_mib: u64,
pub total_space_mib: u64,
pub disk_kind: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SystemInfo {
pub platform: Platform,
pub total_memory_mib: u64,
Expand Down
4 changes: 2 additions & 2 deletions src/skatelet/system/podman.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl PodmanPodStatus {
}
}

#[derive(Tabled, Debug, Clone, Serialize, Deserialize)]
#[derive(Tabled, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
#[tabled(rename_all = "UPPERCASE")]
pub struct PodmanPodInfo {
Expand Down Expand Up @@ -210,7 +210,7 @@ impl From<PodmanPodInfo> for Pod {
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct PodmanContainerInfo {
pub id: String,
Expand Down
2 changes: 1 addition & 1 deletion src/ssh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub struct SshClients {



#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct HostInfo {
pub node_name: String,
pub hostname: String,
Expand Down
12 changes: 5 additions & 7 deletions src/state/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,17 @@ use crate::skatelet::SystemInfo;
use crate::spec::cert::ClusterIssuer;
use crate::ssh::HostInfo;
use crate::state::state::NodeStatus::{Healthy, Unhealthy, Unknown};
use crate::util::{hash_string, metadata_name, slugify};
use crate::util::{metadata_name, slugify};

#[derive(Serialize, Deserialize, Clone, Debug, Display, PartialEq)]
#[derive(Serialize, Deserialize, Clone, Debug, Display, PartialEq, Default)]
pub enum NodeStatus {
#[default]
Unknown,
Healthy,
Unhealthy,
}

#[derive(Tabled, Serialize, Deserialize, Debug, Clone)]
#[derive(Tabled, Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
#[tabled(rename_all = "UPPERCASE")]
pub struct NodeState {
pub node_name: String,
Expand Down Expand Up @@ -292,10 +293,9 @@ impl NodeState {
}
}

#[derive(Serialize, Deserialize, Clone, Debug)]
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct ClusterState {
pub cluster_name: String,
pub hash: String,
pub nodes: Vec<NodeState>,
}

Expand Down Expand Up @@ -351,7 +351,6 @@ impl ClusterState {
Err(_e) => {
let state = ClusterState {
cluster_name: cluster_name.to_string(),
hash: "".to_string(),
nodes: vec![],
};
Ok(state)
Expand Down Expand Up @@ -391,7 +390,6 @@ impl ClusterState {

pub fn reconcile_all_nodes(&mut self, cluster_name: &str, config: &Config, host_info: &[HostInfo]) -> Result<ReconciledResult, Box<dyn Error>> {
let cluster = config.active_cluster(Some(cluster_name.to_string()))?;
self.hash = hash_string(cluster);

let state_hosts: HashSet<String> = self.nodes.iter().map(|n| n.node_name.clone()).collect();

Expand Down
3 changes: 3 additions & 0 deletions src/test_helpers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

pub mod ssh_mocks;
pub mod objects;
64 changes: 64 additions & 0 deletions src/test_helpers/objects.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use std::collections::BTreeMap;
use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta;
use crate::skate::{Distribution, Platform};
use crate::skatelet::system::DiskInfo;
use crate::skatelet::SystemInfo;
use crate::ssh::HostInfo;
use crate::state::state::NodeState;
use crate::state::state::NodeStatus::Healthy;
use crate::util::NamespacedName;

pub fn node_state(name: &str) -> NodeState{
NodeState{
node_name: name.to_string(),
status: Healthy,
host_info: Some(HostInfo{
node_name: name.to_string(),
hostname: name.to_string(),
platform: Platform{ arch: "x86_84".to_string(), distribution: Distribution::Ubuntu},
skatelet_version: Some("1.0.0".to_string()),
system_info: Some(SystemInfo{
platform: Platform{ arch: "x86_84".to_string(), distribution: Distribution::Ubuntu},
total_memory_mib: 1000,
used_memory_mib: 0,
total_swap_mib: 0,
used_swap_mib: 0,
num_cpus: 1,
root_disk: Some(DiskInfo{
available_space_mib: 30_000,
total_space_mib: 40_000,
disk_kind: "ssd".to_string(),
}),
pods: None,
ingresses: None,
cronjobs: None,
secrets: None,
services: None,
cluster_issuers: None,
deployments: None,
daemonsets: None,
cpu_freq_mhz: 2,
cpu_usage: 0.0,
cpu_brand: "Intel".to_string(),
cpu_vendor_id: "".to_string(),
internal_ip_address: None,
hostname: name.to_string(),
cordoned: false,
}),
podman_version: Some("3.6.0".to_string()),
ovs_version: Some("1.0.0".to_string()),
}),
}
}

impl From<NamespacedName> for ObjectMeta {
fn from(ns_name: NamespacedName) -> Self {
ObjectMeta{
labels: Some(BTreeMap::from([
("skate.io/name".to_string(), ns_name.name),
("skate.io/namespace".to_string(), ns_name.namespace),
])),
..Default::default()
}
}
}
File renamed without changes.
6 changes: 3 additions & 3 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ impl Display for NamespacedName {
}

impl NamespacedName {
pub fn new(name: String, namespace: String) -> Self {
NamespacedName { name, namespace }
pub fn new(name: &str, namespace: &str) -> Self {
NamespacedName { name: name.to_string(), namespace: namespace.to_string() }
}
}

Expand All @@ -159,7 +159,7 @@ pub fn metadata_name(obj: &impl Metadata<Ty=ObjectMeta>) -> NamespacedName
panic!("metadata missing skate.io/namespace label")
}

NamespacedName::new(name.unwrap().clone(), ns.unwrap().clone())
NamespacedName::new(name.unwrap(), ns.unwrap())
}

// hash_k8s_resource hashes a k8s resource and adds the hash to the labels, also returning it
Expand Down

0 comments on commit d3faf45

Please sign in to comment.