1+ use axum:: extract:: Path ;
12use axum:: { Json , extract:: State } ;
23use std:: sync:: Arc ;
34use std:: time:: Instant ;
@@ -22,3 +23,101 @@ pub async fn kubelet_stats_summary(
2223 . await ;
2324 Json ( "ok" . to_string ( ) )
2425}
26+
27+ /// Store the raw check_mk_agent output for a node, verbatim, keyed by node
28+ /// name. No parsing/validation is done here or by the caller.
29+ pub async fn linux_agent (
30+ State ( state) : State < AppState < impl TokenValidator > > ,
31+ Path ( node_name) : Path < String > ,
32+ body : String ,
33+ ) -> Json < String > {
34+ state
35+ . linux_agent_cache
36+ . insert ( node_name, Arc :: new ( body) )
37+ . await ;
38+ Json ( "ok" . to_string ( ) )
39+ }
40+
41+ #[ cfg( test) ]
42+ mod tests {
43+ use axum:: body:: Body ;
44+ use axum:: http:: { Request , StatusCode } ;
45+ use k8s_openapi:: api:: authentication:: v1:: { TokenReview , TokenReviewStatus , UserInfo } ;
46+ use tower:: ServiceExt ;
47+
48+ use crate :: auth:: pull_agent:: PullAgentMiddlewareConfig ;
49+ use crate :: handlers:: app;
50+ use crate :: state:: tests:: { MockValidator , test_app_state_with_validator} ;
51+
52+ fn no_pull_agent ( ) -> PullAgentMiddlewareConfig {
53+ PullAgentMiddlewareConfig {
54+ auth_enabled : false ,
55+ shared_secret : None ,
56+ }
57+ }
58+
59+ fn authenticated_review ( username : & str ) -> TokenReview {
60+ TokenReview {
61+ status : Some ( TokenReviewStatus {
62+ authenticated : Some ( true ) ,
63+ user : Some ( UserInfo {
64+ username : Some ( username. to_string ( ) ) ,
65+ ..Default :: default ( )
66+ } ) ,
67+ ..Default :: default ( )
68+ } ) ,
69+ ..Default :: default ( )
70+ }
71+ }
72+
73+ #[ tokio:: test]
74+ async fn linux_agent_ingest_populates_cache_and_returns_ok ( ) {
75+ let state = test_app_state_with_validator ( MockValidator {
76+ response : Ok ( authenticated_review (
77+ "system:serviceaccount:test-ns:test-writer" ,
78+ ) ) ,
79+ } ) ;
80+ let cache = state. linux_agent_cache . clone ( ) ;
81+ let app = app ( state, no_pull_agent ( ) ) ;
82+
83+ let resp = app
84+ . oneshot (
85+ Request :: builder ( )
86+ . method ( "POST" )
87+ . uri ( "/ingest/linux_agent/node-1" )
88+ . header ( "Authorization" , "Bearer test-token" )
89+ . body ( Body :: from ( "<<<check_mk>>>\n Version: 2.5.0\n " ) )
90+ . unwrap ( ) ,
91+ )
92+ . await
93+ . unwrap ( ) ;
94+
95+ assert_eq ! ( resp. status( ) , StatusCode :: OK ) ;
96+ cache. run_pending_tasks ( ) . await ;
97+ assert_eq ! (
98+ cache. get( "node-1" ) . await . map( |v| ( * v) . clone( ) ) ,
99+ Some ( "<<<check_mk>>>\n Version: 2.5.0\n " . to_string( ) )
100+ ) ;
101+ }
102+
103+ #[ tokio:: test]
104+ async fn linux_agent_ingest_requires_auth ( ) {
105+ let state = test_app_state_with_validator ( MockValidator {
106+ response : Ok ( TokenReview :: default ( ) ) ,
107+ } ) ;
108+ let app = app ( state, no_pull_agent ( ) ) ;
109+
110+ let resp = app
111+ . oneshot (
112+ Request :: builder ( )
113+ . method ( "POST" )
114+ . uri ( "/ingest/linux_agent/node-1" )
115+ . body ( Body :: from ( "<<<check_mk>>>\n " ) )
116+ . unwrap ( ) ,
117+ )
118+ . await
119+ . unwrap ( ) ;
120+
121+ assert_eq ! ( resp. status( ) , StatusCode :: UNAUTHORIZED ) ;
122+ }
123+ }
0 commit comments