@@ -3,6 +3,7 @@ use crate::encrypt::ResourceTransformers;
33use crate :: etcd_encoding;
44use anyhow:: { bail, ensure, Context , Result } ;
55use etcd_client:: { Client as EtcdClient , GetOptions } ;
6+ use etcd_encoding:: Encoding ;
67use futures_util:: future:: join_all;
78use serde_json:: Value ;
89use std:: collections:: { HashMap , HashSet } ;
@@ -22,7 +23,7 @@ pub(crate) struct EtcdResult {
2223/// have to go through etcd for every single edit.
2324pub ( crate ) struct InMemoryK8sEtcd {
2425 pub ( crate ) etcd_client : Option < Arc < EtcdClient > > ,
25- etcd_keyvalue_hashmap : Mutex < HashMap < String , Vec < u8 > > > ,
26+ etcd_keyvalue_hashmap : Mutex < HashMap < String , ( Encoding , Vec < u8 > ) > > ,
2627 edited : Mutex < HashMap < String , Vec < u8 > > > ,
2728 deleted_keys : Mutex < HashSet < String > > ,
2829 decrypt_resource_transformers : Option < ResourceTransformers > ,
@@ -105,10 +106,10 @@ impl InMemoryK8sEtcd {
105106 continue ;
106107 }
107108 let key = key. clone ( ) ;
108- let value = value. clone ( ) ;
109+ let ( encoding , value) = value. clone ( ) ;
109110 let etcd_client = Arc :: clone ( etcd_client) ;
110111
111- let mut value = etcd_encoding:: encode ( value. as_slice ( ) ) . await . context ( "encoding value" ) ?;
112+ let mut value = etcd_encoding:: encode ( value. as_slice ( ) , encoding ) . await . context ( "encoding value" ) ?;
112113
113114 if let Some ( resource_transformers) = & self . encrypt_resource_transformers {
114115 // https://github.com/kubernetes/apiserver/blob/3423727e46efe7dfa40dcdb1a9c5c5027b07303d/pkg/storage/value/transformer.go#L172
@@ -184,7 +185,7 @@ impl InMemoryK8sEtcd {
184185
185186 {
186187 let hashmap = self . etcd_keyvalue_hashmap . lock ( ) . await ;
187- if let Some ( value) = hashmap. get ( & key) {
188+ if let Some ( ( _encoding , value) ) = hashmap. get ( & key) {
188189 result. value . clone_from ( value) ;
189190 return Ok ( Some ( result) ) ;
190191 }
@@ -195,7 +196,7 @@ impl InMemoryK8sEtcd {
195196 if let Some ( value) = get_result. kvs ( ) . first ( ) {
196197 let raw_etcd_value = value. value ( ) ;
197198
198- let mut decoded_value = etcd_encoding:: decode ( raw_etcd_value) . await . context ( "decoding value" ) ?;
199+ let ( mut decoded_value, mut encoding ) = etcd_encoding:: decode ( raw_etcd_value) . await . context ( "decoding value" ) ?;
199200
200201 if let Some ( resource_transformers) = & self . decrypt_resource_transformers {
201202 // https://github.com/kubernetes/apiserver/blob/3423727e46efe7dfa40dcdb1a9c5c5027b07303d/pkg/storage/value/transformer.go#L110
@@ -209,7 +210,7 @@ impl InMemoryK8sEtcd {
209210 . decrypt ( key. to_string ( ) , raw_etcd_value. to_vec ( ) )
210211 . await
211212 . context ( "decrypting etcd value" ) ?;
212- decoded_value = etcd_encoding:: decode ( & plaintext_value) . await . context ( "decoding value" ) ?;
213+ ( decoded_value, encoding ) = etcd_encoding:: decode ( & plaintext_value) . await . context ( "decoding value" ) ?;
213214 break ;
214215 }
215216 }
@@ -219,7 +220,7 @@ impl InMemoryK8sEtcd {
219220 self . etcd_keyvalue_hashmap
220221 . lock ( )
221222 . await
222- . insert ( key. to_string ( ) , decoded_value. clone ( ) ) ;
223+ . insert ( key. to_string ( ) , ( encoding , decoded_value. clone ( ) ) ) ;
223224
224225 result. value = decoded_value;
225226 return Ok ( Some ( result) ) ;
@@ -228,10 +229,18 @@ impl InMemoryK8sEtcd {
228229 Ok ( None )
229230 }
230231
231- pub ( crate ) async fn put ( & self , key : & str , value : Vec < u8 > ) {
232- self . etcd_keyvalue_hashmap . lock ( ) . await . insert ( key. to_string ( ) , value. clone ( ) ) ;
232+ pub ( crate ) async fn put ( & self , key : & str , value : Vec < u8 > ) -> Result < ( ) > {
233+ let mut hashmap = self . etcd_keyvalue_hashmap . lock ( ) . await ;
234+
235+ // Only put if the key already exists in the cache, preserving the encoding
236+ let ( encoding, _) = hashmap. get ( key) . context ( format ! ( "key '{}' not found in cache" , key) ) ?;
237+ let encoding = encoding. clone ( ) ; // Clone the encoding
238+ hashmap. insert ( key. to_string ( ) , ( encoding, value. clone ( ) ) ) ;
239+ drop ( hashmap) ; // Release the lock early
240+
233241 self . deleted_keys . lock ( ) . await . remove ( key) ;
234242 self . edited . lock ( ) . await . insert ( key. to_string ( ) , value) ;
243+ Ok ( ( ) )
235244 }
236245
237246 pub ( crate ) async fn list_keys ( & self , resource_kind : & str ) -> Result < Vec < String > > {
@@ -337,6 +346,7 @@ pub(crate) async fn get_etcd_json(client: &InMemoryK8sEtcd, k8slocation: &K8sRes
337346pub ( crate ) async fn put_etcd_yaml ( client : & InMemoryK8sEtcd , k8slocation : & K8sResourceLocation , value : Value ) -> Result < ( ) > {
338347 client
339348 . put ( & k8slocation. as_etcd_key ( ) , serde_json:: to_string ( & value) ?. as_bytes ( ) . into ( ) )
340- . await ;
349+ . await
350+ . context ( "putting in etcd" ) ?;
341351 Ok ( ( ) )
342352}
0 commit comments