@@ -94,7 +94,7 @@ pub struct AgentControlConfig {
9494
9595impl AgentControlConfig {
9696 pub fn defaults ( & self ) -> HashMap < String , serde_yaml:: Value > {
97- self . global_defaults . oci . to_hashmap ( )
97+ self . global_defaults . to_hashmap ( )
9898 }
9999}
100100
@@ -114,13 +114,75 @@ pub struct PackagesConfig {
114114 pub signature_verification_enabled : SignatureVerificationEnabled ,
115115}
116116
117- #[ derive( Debug , Deserialize , Default , Clone , PartialEq ) ]
117+ #[ derive( Debug , Deserialize , Serialize , Default , Clone , PartialEq ) ]
118118pub struct GlobalDefaults {
119119 #[ serde( default ) ]
120120 oci : OciConfig ,
121121}
122122
123- #[ derive( Debug , Deserialize , Clone , PartialEq ) ]
123+ impl GlobalDefaults {
124+ /// Flattens the nested structure of GlobalDefaults into a single level HashMap with dot-separated keys.
125+ ///
126+ /// For example, given the following GlobalDefaults:
127+ /// ```
128+ /// GlobalDefaults {
129+ /// oci: OciConfig {
130+ /// registry: "docker.io".to_string(),
131+ /// auth: OciAuth {
132+ /// basic: BasicAuth {
133+ /// username: "user".to_string(),
134+ /// password: "pass".to_string(),
135+ /// },
136+ /// bearer: "".to_string(),
137+ /// }
138+ /// ```
139+ ///
140+ /// This function will produce the following HashMap:
141+ /// ```
142+ /// {
143+ /// "oci.registry": "docker.io",
144+ /// "oci.auth.basic.username": "user",
145+ /// "oci.auth.basic.password": "pass",
146+ /// "oci.auth.bearer": "",
147+ /// }
148+ fn to_hashmap ( & self ) -> HashMap < String , serde_yaml:: Value > {
149+ let value = serde_yaml:: to_value ( self ) . expect ( "GlobalDefaults should serialize to YAML" ) ;
150+
151+ let mut result = HashMap :: new ( ) ;
152+
153+ if let serde_yaml:: Value :: Mapping ( map) = value {
154+ for ( key, val) in map {
155+ if let Some ( key_str) = key. as_str ( ) {
156+ flatten_value ( key_str, & val, & mut result) ;
157+ }
158+ }
159+ }
160+
161+ result
162+ }
163+ }
164+
165+ fn flatten_value (
166+ prefix : & str ,
167+ value : & serde_yaml:: Value ,
168+ result : & mut HashMap < String , serde_yaml:: Value > ,
169+ ) {
170+ match value {
171+ serde_yaml:: Value :: Mapping ( map) => {
172+ for ( key, val) in map {
173+ if let Some ( key_str) = key. as_str ( ) {
174+ let new_prefix = format ! ( "{}.{}" , prefix, key_str) ;
175+ flatten_value ( & new_prefix, val, result) ;
176+ }
177+ }
178+ }
179+ _ => {
180+ result. insert ( prefix. to_string ( ) , value. clone ( ) ) ;
181+ }
182+ }
183+ }
184+
185+ #[ derive( Debug , Deserialize , Serialize , Clone , PartialEq ) ]
124186pub struct OciConfig {
125187 #[ serde( default = "OciConfig::default_registry" ) ]
126188 registry : String ,
@@ -143,42 +205,15 @@ impl OciConfig {
143205 }
144206}
145207
146- impl OciConfig {
147- fn to_hashmap ( & self ) -> HashMap < String , serde_yaml:: Value > {
148- let mut vars = HashMap :: new ( ) ;
149-
150- vars. insert (
151- "oci.registry" . to_string ( ) ,
152- serde_yaml:: Value :: String ( self . registry . clone ( ) ) ,
153- ) ;
154-
155- vars. insert (
156- "oci.auth.basic.username" . to_string ( ) ,
157- serde_yaml:: Value :: String ( self . auth . basic . username . clone ( ) ) ,
158- ) ;
159- vars. insert (
160- "oci.auth.basic.password" . to_string ( ) ,
161- serde_yaml:: Value :: String ( self . auth . basic . password . clone ( ) ) ,
162- ) ;
163-
164- vars. insert (
165- "oci.auth.bearer" . to_string ( ) ,
166- serde_yaml:: Value :: String ( self . auth . bearer . clone ( ) ) ,
167- ) ;
168-
169- vars
170- }
171- }
172-
173- #[ derive( Debug , Deserialize , Default , Clone , PartialEq ) ]
208+ #[ derive( Debug , Deserialize , Serialize , Default , Clone , PartialEq ) ]
174209struct OciAuth {
175210 #[ serde( default ) ]
176211 basic : BasicAuth ,
177212 #[ serde( default ) ]
178213 bearer : String ,
179214}
180215
181- #[ derive( Debug , Deserialize , Default , Clone , PartialEq ) ]
216+ #[ derive( Debug , Deserialize , Serialize , Default , Clone , PartialEq ) ]
182217struct BasicAuth {
183218 username : String ,
184219 password : String ,
@@ -1177,8 +1212,8 @@ k8s:
11771212 }
11781213
11791214 #[ test]
1180- fn test_oci_config_default_values ( ) {
1181- let vars = OciConfig :: default ( ) . to_hashmap ( ) ;
1215+ fn test_global_defaults_base_values ( ) {
1216+ let vars = GlobalDefaults :: default ( ) . to_hashmap ( ) ;
11821217 assert_eq ! ( vars. len( ) , 4 ) ;
11831218 assert ! ( vars. get( "oci.registry" ) . is_some_and( |v| v == "docker.io" ) ) ;
11841219 assert ! ( vars. get( "oci.auth.basic.username" ) . is_some_and( |v| v == "" ) ) ;
@@ -1187,19 +1222,21 @@ k8s:
11871222 }
11881223
11891224 #[ test]
1190- fn test_oci_config_provided_values ( ) {
1191- let oci_config = OciConfig {
1192- registry : "custom.docker.io" . to_string ( ) ,
1193- auth : OciAuth {
1194- basic : BasicAuth {
1195- username : "user" . to_string ( ) ,
1196- password : "pass" . to_string ( ) ,
1225+ fn test_global_defaults_provided_values ( ) {
1226+ let global_defaults = GlobalDefaults {
1227+ oci : OciConfig {
1228+ registry : "custom.docker.io" . to_string ( ) ,
1229+ auth : OciAuth {
1230+ basic : BasicAuth {
1231+ username : "user" . to_string ( ) ,
1232+ password : "pass" . to_string ( ) ,
1233+ } ,
1234+ bearer : "token" . to_string ( ) ,
11971235 } ,
1198- bearer : "token" . to_string ( ) ,
11991236 } ,
12001237 } ;
12011238
1202- let vars = oci_config . to_hashmap ( ) ;
1239+ let vars = global_defaults . to_hashmap ( ) ;
12031240 assert_eq ! ( vars. len( ) , 4 ) ;
12041241 assert ! (
12051242 vars. get( "oci.registry" )
0 commit comments