Skip to content

Commit

Permalink
fix!: tracer doesn't delete objects on restart
Browse files Browse the repository at this point in the history
  • Loading branch information
drmorr0 committed Nov 14, 2024
1 parent 4c719c2 commit 12a09b5
Show file tree
Hide file tree
Showing 32 changed files with 364 additions and 214 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion sk-cli/src/xray/view/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use chrono::TimeDelta;
use kube::api::DynamicObject;
use lazy_static::lazy_static;
use ratatui::prelude::*;
use sk_core::k8s::KubeResourceExt;
use sk_core::prelude::*;

use crate::validation::{
AnnotatedTraceEvent,
Expand Down
3 changes: 2 additions & 1 deletion sk-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ readme.workspace = true
edition.workspace = true

[features]
testutils = ["dep:http", "dep:httpmock", "dep:mockall", "dep:rstest"]
testutils = ["dep:http", "dep:httpmock", "dep:lazy_static", "dep:mockall", "dep:rstest"]

[dependencies]
anyhow = { workspace = true }
Expand Down Expand Up @@ -37,6 +37,7 @@ url = { workspace = true }
# testutils dependencies
http = { workspace = true, optional = true }
httpmock = { workspace = true, optional = true }
lazy_static = { workspace = true, optional = true }
mockall = { workspace = true, optional = true }
rstest = { workspace = true, optional = true }

Expand Down
9 changes: 9 additions & 0 deletions sk-core/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ pub const ERROR_RETRY_DELAY_SECONDS: u64 = 30;

#[cfg(feature = "testutils")]
mod test_constants {
use lazy_static::lazy_static;

use crate::k8s::GVK;

pub const EMPTY_OBJ_HASH: u64 = 15130871412783076140;
pub const EMPTY_POD_SPEC_HASH: u64 = 17506812802394981455;
pub const TEST_DEPLOYMENT: &str = "the-deployment";
Expand All @@ -40,6 +44,11 @@ mod test_constants {
pub const TEST_DRIVER_ROOT_NAME: &str = "sk-test-driver-12345-root";
pub const TEST_VIRT_NS_PREFIX: &str = "virt-test";
pub const TEST_CTRL_NAMESPACE: &str = "ctrl-ns";

lazy_static! {
pub static ref DEPL_GVK: GVK = GVK::new("apps", "v1", "Deployment");
pub static ref DS_GVK: GVK = GVK::new("apps", "v1", "DaemonSet");
}
}

#[cfg(feature = "testutils")]
Expand Down
1 change: 1 addition & 0 deletions sk-core/src/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use tokio::io::{
BufWriter,
};
use tokio::process::Command;
use tracing::*;

use crate::prelude::*;

Expand Down
2 changes: 2 additions & 0 deletions sk-core/src/k8s/container_state.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use tracing::*;

use super::*;
use crate::prelude::*;

Expand Down
28 changes: 21 additions & 7 deletions sk-core/src/k8s/gvk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::ops::Deref;
use kube::api::{
DynamicObject,
GroupVersionKind,
TypeMeta,
};
use serde::{
de,
Expand Down Expand Up @@ -49,6 +50,13 @@ impl GVK {
bail!("invalid format for api_version: {}", rf.api_version);
}
}

pub fn into_type_meta(&self) -> TypeMeta {
TypeMeta {
api_version: self.0.api_version(),
kind: self.0.kind.clone(),
}
}
}

// Impl Deref lets a GVK act like a GroupVersionKind anywhere one of those is expected
Expand All @@ -60,18 +68,24 @@ impl Deref for GVK {
}
}

impl Serialize for GVK {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
impl fmt::Display for GVK {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut group = Cow::from(&self.0.group);
if !group.is_empty() {
group.to_mut().push('/');
}

let skey = format!("{group}{}.{}", self.0.version, self.0.kind);
serializer.serialize_str(&skey)
write!(f, "{group}{}.{}", self.0.version, self.0.kind)
}
}

impl Serialize for GVK {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
// reuse the display impl for serializing
serializer.serialize_str(&format!("{self}"))
}
}

Expand Down
1 change: 1 addition & 0 deletions sk-core/src/k8s/lease.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use k8s_openapi::api::coordination::v1 as coordinationv1;
use kube::api::Patch;
use kube::ResourceExt;
use serde_json::json;
use tracing::*;

use crate::k8s::{
build_object_meta,
Expand Down
1 change: 1 addition & 0 deletions sk-core/src/k8s/pod_lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::cmp::{

use clockabilly::Clockable;
use kube::ResourceExt;
use tracing::*;

use super::*;
use crate::prelude::*;
Expand Down
11 changes: 2 additions & 9 deletions sk-core/src/k8s/testutils/objs.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
use kube::api::{
DynamicObject,
GroupVersionKind,
};
use kube::api::DynamicObject;
use kube::discovery::ApiResource;
use rstest::*;

use crate::prelude::*;

#[fixture]
pub fn test_deployment(#[default(TEST_DEPLOYMENT)] name: &str) -> DynamicObject {
DynamicObject::new(
&name,
&ApiResource::from_gvk(&GroupVersionKind::gvk("core".into(), "v1".into(), "deployment".into())),
)
.within(TEST_NAMESPACE)
DynamicObject::new(&name, &ApiResource::from_gvk(&DEPL_GVK)).within(TEST_NAMESPACE)
}
4 changes: 2 additions & 2 deletions sk-core/src/k8s/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ where
});
}

pub fn build_deletable(ns_name: &str) -> DynamicObject {
pub fn build_deletable(gvk: &GVK, ns_name: &str) -> DynamicObject {
let (ns, name) = split_namespaced_name(ns_name);
DynamicObject {
metadata: metav1::ObjectMeta {
namespace: Some(ns),
name: Some(name),
..Default::default()
},
types: None,
types: Some(gvk.into_type_meta()),
data: json::Value::Null,
}
}
Expand Down
2 changes: 1 addition & 1 deletion sk-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ pub mod prelude {
Simulation,
SimulationRoot,
};
pub use tracing::*;

pub use crate::constants::*;
pub use crate::errors::EmptyResult;
pub use crate::k8s::KubeResourceExt;
}
1 change: 1 addition & 0 deletions sk-ctrl/src/cert_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use serde::{
use sk_core::k8s::build_object_meta;
use sk_core::macros::*;
use sk_core::prelude::*;
use tracing::*;

use crate::context::SimulationContext;

Expand Down
2 changes: 1 addition & 1 deletion sk-ctrl/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ use sk_core::k8s::{
is_terminal,
metrics_ns,
try_claim_lease,
KubeResourceExt,
LeaseState,
};
use sk_core::prelude::*;
use tokio::runtime::Handle;
use tokio::task::block_in_place;
use tokio::time::Duration;
use tracing::*;

use crate::cert_manager;
use crate::context::SimulationContext;
Expand Down
1 change: 1 addition & 0 deletions sk-ctrl/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use kube::runtime::{
};
use sk_core::logging;
use sk_core::prelude::*;
use tracing::*;

use crate::context::SimulationContext;
use crate::controller::{
Expand Down
2 changes: 1 addition & 1 deletion sk-driver/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use sk_core::external_storage::{
};
use sk_core::k8s::{
ApiSet,
KubeResourceExt,
OwnersCache,
};
use sk_core::prelude::*;
Expand All @@ -32,6 +31,7 @@ use sk_store::{
};
use tokio::sync::Mutex;
use tokio::time::sleep;
use tracing::*;

use crate::mutation::MutationData;
use crate::runner::run_trace;
Expand Down
6 changes: 4 additions & 2 deletions sk-driver/src/mutation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ use serde_json::{
};
use sk_core::jsonutils;
use sk_core::k8s::{
KubeResourceExt,
PodExt,
PodLifecycleData,
GVK,
};
use sk_core::prelude::*;
use tracing::*;

use crate::DriverContext;

Expand Down Expand Up @@ -119,8 +120,9 @@ fn add_lifecycle_annotation(
) -> EmptyResult {
if let Some(orig_ns) = pod.annotations().get(ORIG_NAMESPACE_ANNOTATION_KEY) {
for owner in owners {
let gvk = GVK::from_owner_ref(owner)?;
let owner_ns_name = format!("{}/{}", orig_ns, owner.name);
if !ctx.store.has_obj(&owner_ns_name) {
if !ctx.store.has_obj(&gvk, &owner_ns_name) {
continue;
}

Expand Down
1 change: 1 addition & 0 deletions sk-driver/src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use sk_core::k8s::{
use sk_core::macros::*;
use sk_core::prelude::*;
use tokio::time::sleep;
use tracing::*;

use super::*;

Expand Down
4 changes: 3 additions & 1 deletion sk-driver/src/tests/data/trace.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@
}
],
"index": {
"default/nginx-deployment": 2842228259284014139
"apps/v1.Deployment": {
"default/nginx-deployment": 2842228259284014139
}
},
"pod_lifecycles": {}
}
2 changes: 1 addition & 1 deletion sk-driver/src/tests/mutation_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ async fn test_mutate_pod(mut test_pod: corev1::Pod, mut adm_resp: AdmissionRespo
.with(predicate::always(), predicate::eq(EMPTY_POD_SPEC_HASH), predicate::eq(0))
.returning(|_, _, _| PodLifecycleData::Finished(1, 2))
.once();
let _ = store.expect_has_obj().returning(move |o| o == owner_ns_name);
let _ = store.expect_has_obj().returning(move |_gvk, o| o == owner_ns_name);

let ctx = ctx(test_pod.clone(), vec![root.clone(), depl.clone()], store);

Expand Down
86 changes: 86 additions & 0 deletions sk-store/src/event_list.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use std::collections::VecDeque;
use std::ops::Index;

use kube::api::DynamicObject;
use sk_core::prelude::*;
use tracing::*;

use crate::{
TraceAction,
TraceEvent,
};

#[derive(Default)]
pub struct TraceEventList(VecDeque<TraceEvent>);

impl TraceEventList {
pub(crate) fn append(&mut self, ts: i64, obj: &DynamicObject, action: TraceAction) {
info!(
"{:?} @ {ts}: {} {}",
action,
obj.types
.clone()
.map(|tm| format!("{}.{}", tm.api_version, tm.kind))
.unwrap_or("<unknown type>".into()),
obj.namespaced_name(),
);

let obj = obj.clone();
match self.0.back_mut() {
Some(evt) if evt.ts == ts => match action {
TraceAction::ObjectApplied => evt.applied_objs.push(obj),
TraceAction::ObjectDeleted => evt.deleted_objs.push(obj),
},
_ => {
let evt = match action {
TraceAction::ObjectApplied => TraceEvent { ts, applied_objs: vec![obj], ..Default::default() },
TraceAction::ObjectDeleted => TraceEvent { ts, deleted_objs: vec![obj], ..Default::default() },
};
self.0.push_back(evt);
},
}
}

pub(crate) fn back(&self) -> Option<&TraceEvent> {
self.0.back()
}

pub(crate) fn front(&self) -> Option<&TraceEvent> {
self.0.front()
}

pub(crate) fn is_empty(&self) -> bool {
self.0.is_empty()
}

pub(crate) fn len(&self) -> usize {
self.0.len()
}
}

impl Index<usize> for TraceEventList {
type Output = TraceEvent;

fn index(&self, i: usize) -> &Self::Output {
&self.0[i]
}
}

impl From<VecDeque<TraceEvent>> for TraceEventList {
fn from(v: VecDeque<TraceEvent>) -> TraceEventList {
TraceEventList(v)
}
}

impl From<Vec<TraceEvent>> for TraceEventList {
fn from(v: Vec<TraceEvent>) -> TraceEventList {
TraceEventList(v.into())
}
}

#[cfg(test)]
impl FromIterator<TraceEvent> for TraceEventList {
fn from_iter<T: IntoIterator<Item = TraceEvent>>(ii: T) -> Self {
TraceEventList(ii.into_iter().collect())
}
}
2 changes: 1 addition & 1 deletion sk-store/src/trace_filter.rs → sk-store/src/filter.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use kube::api::DynamicObject;
use sk_api::v1::ExportFilters;
use sk_core::k8s::KubeResourceExt;
use sk_core::prelude::*;

use super::TraceEvent;

Expand Down
Loading

0 comments on commit 12a09b5

Please sign in to comment.