@@ -9,6 +9,7 @@ use crate::{
99use bollard:: {
1010 container:: { Config , CreateContainerOptions , ListContainersOptions } ,
1111 models:: { ContainerStateStatusEnum , HostConfig } ,
12+ secret:: { ContainerInspectResponse , ContainerSummary } ,
1213} ;
1314use chrono:: DateTime ;
1415use futures_util:: future:: join_all;
@@ -165,12 +166,8 @@ impl LocalDockerOrchestrator {
165166 ) )
166167 }
167168 #[ expect(
168- clippy:: cast_sign_loss,
169169 clippy:: string_slice,
170- clippy:: cast_precision_loss,
171- clippy:: cast_possible_truncation,
172170 clippy:: indexing_slicing,
173- clippy:: too_many_lines,
174171 reason = r#"
175172 - Timestamp and memory should always have a value > 0
176173 - Container will always have a name with more than 1 character
@@ -210,79 +207,119 @@ impl LocalDockerOrchestrator {
210207 . await
211208 . into_iter ( )
212209 . filter_map ( |result : Result < _ > | {
213- let ( container_name, container_summary, container_spec) = result. ok ( ) ?;
214- let terminated_timestamp =
215- DateTime :: parse_from_rfc3339 ( container_spec. state . as_ref ( ) ?. finished_at . as_ref ( ) ?)
216- . ok ( ) ?
217- . timestamp ( ) ;
218- Some ( (
219- container_name,
220- PodRunInfo {
221- image : container_spec. config . as_ref ( ) ?. image . as_ref ( ) ?. clone ( ) ,
222- created : container_summary. created ? as u64 ,
223- terminated : ( terminated_timestamp > 0 ) . then_some ( terminated_timestamp as u64 ) ,
224- env_vars : container_spec
225- . config
226- . as_ref ( ) ?
227- . env
228- . as_ref ( ) ?
229- . iter ( )
230- . filter_map ( |x| {
231- x. split_once ( '=' )
232- . map ( |( key, value) | ( key. to_owned ( ) , value. to_owned ( ) ) )
233- } )
234- . collect ( ) ,
235- command : [
236- container_spec. config . as_ref ( ) ?. entrypoint . as_ref ( ) ?. clone ( ) ,
237- container_spec. config . as_ref ( ) ?. cmd . as_ref ( ) ?. clone ( ) ,
238- ]
239- . concat ( ) ,
240- status : match (
241- container_spec. state . as_ref ( ) ?. status . as_ref ( ) ?,
242- container_spec. state . as_ref ( ) ?. exit_code ? as i16 ,
243- ) {
244- ( ContainerStateStatusEnum :: RUNNING , _) => PodStatus :: Running ,
245- (
246- ContainerStateStatusEnum :: EXITED
247- | ContainerStateStatusEnum :: REMOVING
248- | ContainerStateStatusEnum :: DEAD ,
249- 0 ,
250- ) => PodStatus :: Completed ,
251- (
252- ContainerStateStatusEnum :: EXITED
253- | ContainerStateStatusEnum :: REMOVING
254- | ContainerStateStatusEnum :: DEAD ,
255- code,
256- ) => PodStatus :: Failed ( code) ,
257- ( _, code) => {
258- todo ! (
259- "Unhandled container state: {}, exit code: {code}." ,
260- container_spec. state. as_ref( ) ?. status. as_ref( ) ?
261- )
262- }
263- } ,
264- mounts : container_spec
265- . mounts
266- . as_ref ( ) ?
267- . iter ( )
268- . map ( |mount_point| {
269- Some ( format ! (
270- "{}:{}{}" ,
271- mount_point. source. as_ref( ) ?,
272- mount_point. destination. as_ref( ) ?,
273- mount_point
274- . mode
275- . as_ref( )
276- . map_or_else( String :: new, |mode| format!( ":{mode}" ) )
277- ) )
278- } )
279- . collect :: < Option < _ > > ( ) ?,
280- labels : container_spec. config . as_ref ( ) ?. labels . as_ref ( ) ?. clone ( ) ,
281- cpu_limit : container_spec. host_config . as_ref ( ) ?. nano_cpus ? as f32
282- / 10_f32 . powi ( 9 ) , // ncpu, ucores=3, mcores=6, cores=9
283- memory_limit : container_spec. host_config . as_ref ( ) ?. memory ? as u64 ,
284- } ,
285- ) )
210+ let ( container_name, container_summary, container_inspect_response) = result. ok ( ) ?;
211+
212+ Self :: extract_run_info ( & container_summary, & container_inspect_response)
213+ . map ( |run_info| ( container_name. clone ( ) , run_info) )
286214 } ) )
287215 }
216+
217+ #[ expect(
218+ clippy:: cast_sign_loss,
219+ clippy:: cast_precision_loss,
220+ clippy:: cast_possible_truncation,
221+ reason = r#"
222+ - Timestamp and memory should always have a value > 0
223+ - Container will always have a name with more than 1 character
224+ - No issue in core casting if between 0 - 3.40e38(f32:MAX)
225+ - No issue in exit code casting if between -3.27e4(i16:MIN) - 3.27e4(i16:MAX)
226+ - Containers will always have at least 1 name with at least 2 characters
227+ - This functions requires a lot of boilerplate code to extract the run info
228+ "#
229+ ) ]
230+ fn extract_run_info (
231+ container_summary : & ContainerSummary ,
232+ container_inspect_response : & ContainerInspectResponse ,
233+ ) -> Option < PodRunInfo > {
234+ let terminated_timestamp = DateTime :: parse_from_rfc3339 (
235+ container_inspect_response
236+ . state
237+ . as_ref ( ) ?
238+ . finished_at
239+ . as_ref ( ) ?,
240+ )
241+ . ok ( ) ?
242+ . timestamp ( ) as u64 ;
243+ Some ( PodRunInfo {
244+ image : container_inspect_response
245+ . config
246+ . as_ref ( ) ?
247+ . image
248+ . as_ref ( ) ?
249+ . clone ( ) ,
250+ created : container_summary. created ? as u64 ,
251+ terminated : ( terminated_timestamp > 0 ) . then_some ( terminated_timestamp) ,
252+ env_vars : container_inspect_response
253+ . config
254+ . as_ref ( ) ?
255+ . env
256+ . as_ref ( ) ?
257+ . iter ( )
258+ . filter_map ( |x| {
259+ x. split_once ( '=' )
260+ . map ( |( key, value) | ( key. to_owned ( ) , value. to_owned ( ) ) )
261+ } )
262+ . collect ( ) ,
263+ command : [
264+ container_inspect_response
265+ . config
266+ . as_ref ( ) ?
267+ . entrypoint
268+ . as_ref ( ) ?
269+ . clone ( ) ,
270+ container_inspect_response
271+ . config
272+ . as_ref ( ) ?
273+ . cmd
274+ . as_ref ( ) ?
275+ . clone ( ) ,
276+ ]
277+ . concat ( ) ,
278+ status : match (
279+ container_inspect_response. state . as_ref ( ) ?. status ?,
280+ container_inspect_response. state . as_ref ( ) ?. exit_code ? as i16 ,
281+ ) {
282+ ( ContainerStateStatusEnum :: RUNNING | ContainerStateStatusEnum :: RESTARTING , _) => {
283+ PodStatus :: Running
284+ }
285+ ( ContainerStateStatusEnum :: EXITED , 0 ) => PodStatus :: Completed ,
286+ ( ContainerStateStatusEnum :: EXITED | ContainerStateStatusEnum :: DEAD , code) => {
287+ PodStatus :: Failed ( code)
288+ }
289+ ( ContainerStateStatusEnum :: CREATED , code) => {
290+ if container_inspect_response. state . as_ref ( ) ?. error . is_some ( ) {
291+ PodStatus :: Failed ( code)
292+ } else {
293+ PodStatus :: Running
294+ }
295+ }
296+ _ => PodStatus :: Undefined ,
297+ } ,
298+ mounts : container_inspect_response
299+ . mounts
300+ . as_ref ( ) ?
301+ . iter ( )
302+ . map ( |mount_point| {
303+ Some ( format ! (
304+ "{}:{}{}" ,
305+ mount_point. source. as_ref( ) ?,
306+ mount_point. destination. as_ref( ) ?,
307+ mount_point
308+ . mode
309+ . as_ref( )
310+ . map_or_else( String :: new, |mode| format!( ":{mode}" ) )
311+ ) )
312+ } )
313+ . collect :: < Option < Vec < _ > > > ( ) ?,
314+ labels : container_inspect_response
315+ . config
316+ . as_ref ( ) ?
317+ . labels
318+ . as_ref ( ) ?
319+ . clone ( ) ,
320+ cpu_limit : container_inspect_response. host_config . as_ref ( ) ?. nano_cpus ? as f32
321+ / 10_f32 . powi ( 9 ) , // ncpu, ucores=3, mcores=6, cores=9
322+ memory_limit : container_inspect_response. host_config . as_ref ( ) ?. memory ? as u64 ,
323+ } )
324+ }
288325}
0 commit comments