2828//! };
2929//! ```
3030
31+ use k8s_openapi:: api:: core:: v1:: Pod as KubePod ;
32+ use kube:: api:: DeleteParams ;
33+ use kube:: Api ;
34+ use kube:: Config as KubeConfig ;
3135use kubelet:: handle:: { key_from_pod, pod_key} ;
3236use kubelet:: module_store:: ModuleStore ;
3337use kubelet:: provider:: ProviderError ;
3438use kubelet:: Pod ;
35- use log:: { debug, info} ;
39+ use log:: { debug, error , info, trace } ;
3640use std:: collections:: HashMap ;
3741use std:: sync:: Arc ;
3842use tokio:: sync:: RwLock ;
@@ -47,14 +51,16 @@ const TARGET_WASM32_WASI: &str = "wasm32-wasi";
4751pub struct Provider < S > {
4852 pods : Arc < RwLock < HashMap < String , HashMap < String , Runtime > > > > ,
4953 store : S ,
54+ kubeconfig : KubeConfig ,
5055}
5156
5257impl < S : ModuleStore + Send + Sync > Provider < S > {
5358 /// Create a new wasi provider from a module store and a kubelet config
54- pub fn new ( store : S ) -> Self {
59+ pub fn new ( store : S , kubeconfig : KubeConfig ) -> Self {
5560 Self {
5661 pods : Default :: default ( ) ,
5762 store,
63+ kubeconfig,
5864 }
5965 }
6066}
@@ -79,7 +85,8 @@ impl<S: ModuleStore + Send + Sync> kubelet::Provider for Provider<S> {
7985 . remove ( & container. name )
8086 . expect ( "FATAL ERROR: module map not properly populated" ) ;
8187
82- let mut runtime = Runtime :: new ( module_data, 1 as u32 ) ;
88+ // TODO: expose this as a feature flag (--stack-size)
89+ let mut runtime = Runtime :: new ( module_data, ( 1024 * 60 ) as u32 ) ;
8390
8491 debug ! ( "Starting container {} on thread" , container. name) ;
8592 runtime. start ( ) ?;
@@ -100,12 +107,75 @@ impl<S: ModuleStore + Send + Sync> kubelet::Provider for Provider<S> {
100107 Ok ( ( ) )
101108 }
102109
103- async fn modify ( & self , _pod : Pod ) -> anyhow:: Result < ( ) > {
104- unimplemented ! ( )
110+ async fn modify ( & self , pod : Pod ) -> anyhow:: Result < ( ) > {
111+ // The only things we care about are:
112+ // 1. metadata.deletionTimestamp => signal all containers to stop and then mark them
113+ // as terminated
114+ // 2. spec.containers[*].image, spec.initContainers[*].image => stop the currently
115+ // running containers and start new ones?
116+ // 3. spec.activeDeadlineSeconds => Leaving unimplemented for now
117+ // TODO: Determine what the proper behavior should be if labels change
118+ debug ! (
119+ "Got pod modified event for {} in namespace {}" ,
120+ pod. name( ) ,
121+ pod. namespace( )
122+ ) ;
123+ trace ! ( "Modified pod spec: {:#?}" , pod. as_kube_pod( ) ) ;
124+ if let Some ( _timestamp) = pod. deletion_timestamp ( ) {
125+ let mut pods = self . pods . write ( ) . await ;
126+ match pods. get_mut ( & key_from_pod ( & pod) ) {
127+ Some ( h) => {
128+ for ( _name, runtime) in h {
129+ runtime. stop ( ) ?;
130+ }
131+ // Follow up with a delete when everything is stopped
132+ let dp = DeleteParams {
133+ grace_period_seconds : Some ( 0 ) ,
134+ ..Default :: default ( )
135+ } ;
136+ let pod_client: Api < KubePod > = Api :: namespaced (
137+ kube:: client:: Client :: new ( self . kubeconfig . clone ( ) ) ,
138+ pod. namespace ( ) ,
139+ ) ;
140+ match pod_client. delete ( pod. name ( ) , & dp) . await {
141+ Ok ( _) => Ok ( ( ) ) ,
142+ Err ( e) => Err ( e. into ( ) ) ,
143+ }
144+ }
145+ None => {
146+ // This isn't an error with the pod, so don't return an error (otherwise it will
147+ // get updated in its status). This is an unlikely case to get into and means
148+ // that something is likely out of sync, so just log the error
149+ error ! (
150+ "Unable to find pod {} in namespace {} when trying to stop all containers" ,
151+ pod. name( ) ,
152+ pod. namespace( )
153+ ) ;
154+ Ok ( ( ) )
155+ }
156+ }
157+ } else {
158+ Ok ( ( ) )
159+ }
160+ // TODO: Implement behavior for stopping old containers and restarting when the container
161+ // image changes
105162 }
106163
107- async fn delete ( & self , _pod : Pod ) -> anyhow:: Result < ( ) > {
108- unimplemented ! ( )
164+ async fn delete ( & self , pod : Pod ) -> anyhow:: Result < ( ) > {
165+ let mut pods = self . pods . write ( ) . await ;
166+ match pods. remove ( & key_from_pod ( & pod) ) {
167+ Some ( _) => debug ! (
168+ "Pod {} in namespace {} removed" ,
169+ pod. name( ) ,
170+ pod. namespace( )
171+ ) ,
172+ None => info ! (
173+ "unable to find pod {} in namespace {}, it was likely already deleted" ,
174+ pod. name( ) ,
175+ pod. namespace( )
176+ ) ,
177+ }
178+ Ok ( ( ) )
109179 }
110180
111181 async fn logs (
@@ -116,7 +186,7 @@ impl<S: ModuleStore + Send + Sync> kubelet::Provider for Provider<S> {
116186 _sender : kubelet:: LogSender ,
117187 ) -> anyhow:: Result < ( ) > {
118188 let mut pods = self . pods . write ( ) . await ;
119- let _pod = pods
189+ let _containers = pods
120190 . get_mut ( & pod_key ( & namespace, & pod_name) )
121191 . ok_or_else ( || ProviderError :: PodNotFound {
122192 pod_name : pod_name. clone ( ) ,
0 commit comments