Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
byrnedo committed Jul 31, 2024
1 parent f83c657 commit a817985
Show file tree
Hide file tree
Showing 13 changed files with 254 additions and 91 deletions.
9 changes: 9 additions & 0 deletions hack/test-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
kind: Secret
metadata:
name: test
namespace: foo
type: Opaque
data:
username: dXNlcg==
password: NTRmNDFkMTJlOGZh
5 changes: 4 additions & 1 deletion src/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub enum DeleteCommands {
Node(DeleteResourceArgs),
Ingress(DeleteResourceArgs),
Cronjob(DeleteResourceArgs),
Secret(DeleteResourceArgs),
}

#[derive(Debug, Args)]
Expand All @@ -39,6 +40,8 @@ pub async fn delete(args: DeleteArgs) -> Result<(), Box<dyn Error>> {
DeleteCommands::Node(args) => delete_node(args).await?,
DeleteCommands::Ingress(args) => delete_resource(ResourceType::Ingress, args).await?,
DeleteCommands::Cronjob(args) => delete_resource(ResourceType::CronJob, args).await?,
DeleteCommands::Secret(args) => delete_resource(ResourceType::Secret, args).await?,
_ => todo!()
}
Ok(())
}
Expand All @@ -65,7 +68,7 @@ async fn delete_resource(r_type: ResourceType, args: DeleteResourceArgs) -> Resu
match conn.remove_resource(r_type.clone(), &args.name, &args.namespace).await {
Ok(result) => {
results.push(result)
},
}
Err(e) => errors.push(e.to_string())
}
}
Expand Down
18 changes: 16 additions & 2 deletions src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use anyhow::anyhow;
use handlebars::Handlebars;

use k8s_openapi::api::batch::v1::CronJob;
use k8s_openapi::api::core::v1::Pod;
use k8s_openapi::api::core::v1::{Pod, Secret};
use k8s_openapi::api::networking::v1::Ingress;
use serde_json::{json, Value};

Expand Down Expand Up @@ -271,6 +271,20 @@ impl DefaultExecutor {

Ok(())
}

fn remove_secret(&self, secret: Secret) -> Result<(), Box<dyn Error>> {
let fqn = format!("{}.{}", secret.metadata.name.unwrap(), secret.metadata.namespace.unwrap());

let _output = process::Command::new("podman")
.args(["secret", "rm", &fqn])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.output()
.expect("failed to remove secret");

Ok(())
}

fn remove_pod(&self, id: &str, _namespace: &str, grace_period: Option<usize>) -> Result<(), Box<dyn Error>> {
if id.is_empty() {
return Err(anyhow!("no metadata.name found").into());
Expand Down Expand Up @@ -349,7 +363,7 @@ impl Executor for DefaultExecutor {
self.remove_cron(cron)
}
SupportedResources::Secret(secret) => {
todo!()
self.remove_secret(secret)
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod deployment;
mod cronjob;
mod pod;
mod lister;
mod daemonset;


use std::error::Error;
Expand All @@ -21,6 +22,7 @@ use crate::skate::{ConfigFileArgs};
use crate::{ssh};

use crate::get::cronjob::CronjobsLister;
use crate::get::daemonset::DaemonsetLister;
use crate::get::deployment::DeploymentLister;
use crate::get::ingress::IngresssLister;
use crate::get::lister::Lister;
Expand Down Expand Up @@ -118,6 +120,11 @@ async fn get_deployment(global_args: GetArgs, args: GetObjectArgs) -> Result<(),
get_objects(global_args, args, &lister).await
}

async fn get_daemonsets(global_args: GetArgs, args: GetObjectArgs) -> Result<(), Box<dyn Error>> {
let lister = DaemonsetLister {};
get_objects(global_args, args, &lister).await
}

async fn get_pod(global_args: GetArgs, args: GetObjectArgs) -> Result<(), Box<dyn Error>> {
let lister = PodLister {};
get_objects(global_args, args, &lister).await
Expand Down
78 changes: 78 additions & 0 deletions src/get/daemonset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use std::collections::HashMap;
use chrono::{Local, SecondsFormat};
use itertools::Itertools;
use crate::get::{GetObjectArgs, IdCommand, Lister};
use crate::skatelet::{PodmanPodInfo, PodmanPodStatus, SystemInfo};
use crate::state::state::ClusterState;

pub(crate) struct DaemonsetLister {}

impl Lister<(String, PodmanPodInfo)> for DaemonsetLister {
fn selector(&self, _si: &SystemInfo, _ns: &str, _id: &str) -> Option<Vec<(String, PodmanPodInfo)>> {
todo!()
}
fn list(&self, args: &GetObjectArgs, state: &ClusterState) -> Vec<(String, PodmanPodInfo)> {
let pods: Vec<_> = state.nodes.iter().filter_map(|n| {
let items: Vec<_> = n.host_info.clone()?.system_info?.pods.unwrap_or_default().into_iter().filter_map(|p| {
let ns = args.namespace.clone().unwrap_or("default".to_string());
let id = match args.id.clone() {
Some(cmd) => match cmd {
IdCommand::Id(ids) => Some(ids.into_iter().next().unwrap_or("".to_string()))
}
None => None
};
let daemonset = p.labels.get("skate.io/daemonset").and_then(|n| Some(n.clone())).unwrap_or_default();
if daemonset == "" {
return None;
}
let daemonset_ns = p.labels.get("skate.io/namespace").unwrap_or(&"".to_string()).clone();


let match_ns = ns == daemonset_ns;

let match_id = match id.clone() {
Some(id) => {
id == daemonset
}
None => false
};
if match_ns || match_id || (id.is_none() && ns == "" && daemonset_ns != "skate" ) {
return Some((daemonset, p));
}
None
}).collect();
match items.len() {
0 => None,
_ => Some(items)
}
}).flatten().collect();
pods
}

fn print(&self, items: Vec<(String, PodmanPodInfo)>) {
println!(
"{0: <30} {1: <10} {2: <10} {3: <10} {4: <30}",
"NAME", "READY", "STATUS", "RESTARTS", "CREATED"
);
let pods = items.into_iter().fold(HashMap::<String, Vec<PodmanPodInfo>>::new(), |mut acc, (depl, pod)| {
acc.entry(depl).or_insert(vec![]).push(pod);
acc
});

for (deployment, pods) in pods {
let health_pods = pods.iter().filter(|p| PodmanPodStatus::Running == p.status).collect_vec().len();
let all_pods = pods.len();
let created = pods.iter().fold(Local::now(), |acc, item| {
if item.created < acc {
return item.created;
}
return acc;
});

println!(
"{0: <30} {1: <10} {2: <10} {3: <10} {4: <30}",
deployment, format!("{}/{}", health_pods, all_pods), "", "", created.to_rfc3339_opts(SecondsFormat::Secs, true)
)
}
}
}
7 changes: 4 additions & 3 deletions src/get/deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::get::{GetObjectArgs, IdCommand, Lister};
use crate::skatelet::{PodmanPodInfo, PodmanPodStatus, SystemInfo};
use crate::state::state::ClusterState;

pub (crate) struct DeploymentLister {}
pub(crate) struct DeploymentLister {}

impl Lister<(String, PodmanPodInfo)> for DeploymentLister {
fn selector(&self, _si: &SystemInfo, _ns: &str, _id: &str) -> Option<Vec<(String, PodmanPodInfo)>> {
Expand All @@ -22,11 +22,12 @@ impl Lister<(String, PodmanPodInfo)> for DeploymentLister {
None => None
};
let deployment = p.labels.get("skate.io/deployment");
let pod_ns = p.labels.get("skate.io/namespace").unwrap_or(&"default".to_string()).clone();
match deployment {
Some(deployment) => {
let match_ns = match ns.clone() {
Some(ns) => {
ns == p.labels.get("skate.io/namespace").unwrap_or(&"".to_string()).clone()
ns == pod_ns
}
None => false
};
Expand All @@ -36,7 +37,7 @@ impl Lister<(String, PodmanPodInfo)> for DeploymentLister {
}
None => false
};
if match_ns || match_id || (id.is_none() && ns.is_none()) {
if match_ns || match_id || (id.is_none() && ns.is_none() && pod_ns != "skate") {
return Some((deployment.clone(), p));
}
None
Expand Down
2 changes: 1 addition & 1 deletion src/get/ingress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub(crate) struct IngresssLister {}
impl Lister<ObjectListItem> for IngresssLister {
fn selector(&self, si: &SystemInfo, ns: &str, id: &str) -> Option<Vec<ObjectListItem>> {
si.ingresses.as_ref().and_then(|jobs| Some(jobs.iter().filter(|j| {
let filterable: Box<dyn NameFilters> = Box::new(j.clone());
let filterable: Box<dyn NameFilters> = Box::new(*j);
return filterable.filter_names(id, ns);
}).map(|p| p.clone()).collect()))
}
Expand Down
27 changes: 25 additions & 2 deletions src/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use itertools::Itertools;

use k8s_openapi::api::apps::v1::{DaemonSet, Deployment};
use k8s_openapi::api::batch::v1::CronJob;
use k8s_openapi::api::core::v1::{Node as K8sNode, Pod};
use k8s_openapi::api::core::v1::{Node as K8sNode, Pod, Secret};
use k8s_openapi::api::networking::v1::Ingress;
use k8s_openapi::Metadata;

Expand Down Expand Up @@ -393,6 +393,29 @@ impl DefaultScheduler {



Ok(ApplyPlan {
actions,
})
}

// just apply on all nodes
fn plan_secret(state: &ClusterState, secret: &Secret) -> Result<ApplyPlan, Box<dyn Error>> {

let mut actions = vec!();

for node in state.nodes.iter() {

actions.extend([
ScheduledOperation{
resource: SupportedResources::Secret(secret.clone()),
error: None,
operation: OpType::Create,
node: Some(node.clone()),
}
]);
}


Ok(ApplyPlan {
actions,
})
Expand Down Expand Up @@ -469,7 +492,7 @@ impl DefaultScheduler {
SupportedResources::DaemonSet(ds) => Self::plan_daemonset(state, ds),
SupportedResources::Ingress(ingress) => Self::plan_ingress(state, ingress),
SupportedResources::CronJob(cron) => Self::plan_cronjob(state, cron),
SupportedResources::Secret(secret) => todo!(),
SupportedResources::Secret(secret) => Self::plan_secret(state, secret),
}
}

Expand Down
12 changes: 11 additions & 1 deletion src/skate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ pub enum ResourceType {
DaemonSet,
Ingress,
CronJob,
Secret,
}

#[derive(Debug, Serialize, Deserialize, Display, Clone)]
Expand Down Expand Up @@ -153,7 +154,16 @@ impl SupportedResources {
let mut resource = self.clone();
let resource = match resource {
SupportedResources::Secret(ref mut s) => {
// TODO
let original_name = s.metadata.name.clone().unwrap_or("".to_string());
if original_name.is_empty() {
return Err(anyhow!("metadata.name is empty").into());
}
if s.metadata.namespace.is_none() {
return Err(anyhow!("metadata.namespace is empty").into());
}

s.metadata = Self::fixup_metadata(s.metadata.clone(), None)?;
s.metadata.name = Some(format!("{}.{}", original_name, s.metadata.namespace.clone().unwrap()));
resource
}
SupportedResources::CronJob(ref mut c) => {
Expand Down
79 changes: 0 additions & 79 deletions src/skatelet/apply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,82 +50,3 @@ pub fn apply(apply_args: ApplyArgs) -> Result<(), Box<dyn Error>> {
executor.apply(&manifest)
}

#[derive(Debug, Args, Clone)]
pub struct DeleteResourceArgs {
#[arg(long, long_help = "Name of the resource.")]
pub name: String,
#[arg(long, long_help = "Name of the resource.")]
pub namespace: String,
}

#[derive(Debug, Subcommand, Clone)]
pub enum DeleteResourceCommands {
#[command(flatten)]
StdinCommand(StdinCommand),
Ingress(DeleteResourceArgs),
Cronjob(DeleteResourceArgs)
}

#[derive(Debug, Args, Clone)]
pub struct DeleteArgs {
#[arg(short, long, long_help("Number of seconds to wait before hard killing."))]
termination_grace_period: Option<usize>,
#[command(subcommand)]
command: DeleteResourceCommands,
}

pub fn delete(args: DeleteArgs) -> Result<(), Box<dyn Error>> {
match &args.command {
DeleteResourceCommands::Ingress(resource_args) => delete_ingress(args.clone(), resource_args.clone()),
DeleteResourceCommands::StdinCommand(_) => delete_stdin(args),
DeleteResourceCommands::Cronjob(resource_args) => delete_cronjob(args.clone(), resource_args.clone()),
}
}


pub fn delete_ingress(delete_args: DeleteArgs, resource_args: DeleteResourceArgs) -> Result<(), Box<dyn Error>> {
let executor = DefaultExecutor::new();
let mut meta = ObjectMeta::default();
meta.name = Some(resource_args.name.clone());
meta.namespace = Some(resource_args.namespace.clone());
meta.labels = Some(BTreeMap::from([
("skate.io/name".to_string(), resource_args.name),
("skate.io/namespace".to_string(), resource_args.namespace),
]));

executor.manifest_delete(Ingress(K8sIngress {
metadata: meta,
spec: None,
status: None,
}), delete_args.termination_grace_period)
}

pub fn delete_cronjob(delete_args: DeleteArgs, resource_args: DeleteResourceArgs) -> Result<(), Box<dyn Error>> {
let executor = DefaultExecutor::new();
let mut meta = ObjectMeta::default();
meta.name = Some(resource_args.name.clone());
meta.namespace = Some(resource_args.namespace.clone());
meta.labels = Some(BTreeMap::from([
("skate.io/name".to_string(), resource_args.name),
("skate.io/namespace".to_string(), resource_args.namespace),
]));

executor.manifest_delete(CronJob(K8sCronJob {
metadata: meta,
spec: None,
status: None,
}), delete_args.termination_grace_period)
}

pub fn delete_stdin(args: DeleteArgs) -> Result<(), Box<dyn Error>> {
let manifest = {
let mut stdin = io::stdin();
let mut buffer = String::new();
stdin.read_to_string(&mut buffer)?;
buffer
};

let executor = DefaultExecutor::new();
let object: SupportedResources = serde_yaml::from_str(&manifest).expect("failed to deserialize manifest");
executor.manifest_delete(object, args.termination_grace_period)
}
Loading

0 comments on commit a817985

Please sign in to comment.