@@ -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,80 @@ 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+ /// # Example
127+ ///
128+ /// Given the following GlobalDefaults structure:
129+ /// ```ignore
130+ /// GlobalDefaults {
131+ /// oci: OciConfig {
132+ /// registry: "docker.io",
133+ /// auth: OciAuth {
134+ /// basic: BasicAuth {
135+ /// username: "user",
136+ /// password: "pass",
137+ /// },
138+ /// bearer: "",
139+ /// },
140+ /// }
141+ /// }
142+ /// ```
143+ ///
144+ /// we get the following HashMap:
145+ /// ```ignore
146+ /// {
147+ /// "oci.registry": "docker.io",
148+ /// "oci.auth.basic.username": "user",
149+ /// "oci.auth.basic.password": "pass",
150+ /// "oci.auth.bearer": "",
151+ /// }
152+ /// ```
153+ fn to_hashmap ( & self ) -> HashMap < String , serde_yaml:: Value > {
154+ let value = serde_yaml:: to_value ( self ) . expect ( "GlobalDefaults should serialize to YAML" ) ;
155+
156+ let mut result = HashMap :: new ( ) ;
157+
158+ if let serde_yaml:: Value :: Mapping ( map) = value {
159+ for ( key, val) in map {
160+ if let Some ( key_str) = key. as_str ( ) {
161+ flatten_value ( key_str, & val, & mut result) ;
162+ }
163+ }
164+ }
165+
166+ result
167+ }
168+ }
169+
170+ fn flatten_value (
171+ prefix : & str ,
172+ value : & serde_yaml:: Value ,
173+ result : & mut HashMap < String , serde_yaml:: Value > ,
174+ ) {
175+ match value {
176+ serde_yaml:: Value :: Mapping ( map) => {
177+ for ( key, val) in map {
178+ if let Some ( key_str) = key. as_str ( ) {
179+ let new_prefix = format ! ( "{}.{}" , prefix, key_str) ;
180+ flatten_value ( & new_prefix, val, result) ;
181+ }
182+ }
183+ }
184+ _ => {
185+ result. insert ( prefix. to_string ( ) , value. clone ( ) ) ;
186+ }
187+ }
188+ }
189+
190+ #[ derive( Debug , Deserialize , Serialize , Clone , PartialEq ) ]
124191pub struct OciConfig {
125192 #[ serde( default = "OciConfig::default_registry" ) ]
126193 registry : String ,
@@ -143,42 +210,15 @@ impl OciConfig {
143210 }
144211}
145212
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 ) ]
213+ #[ derive( Debug , Deserialize , Serialize , Default , Clone , PartialEq ) ]
174214struct OciAuth {
175215 #[ serde( default ) ]
176216 basic : BasicAuth ,
177217 #[ serde( default ) ]
178218 bearer : String ,
179219}
180220
181- #[ derive( Debug , Deserialize , Default , Clone , PartialEq ) ]
221+ #[ derive( Debug , Deserialize , Serialize , Default , Clone , PartialEq ) ]
182222struct BasicAuth {
183223 username : String ,
184224 password : String ,
@@ -1177,8 +1217,8 @@ k8s:
11771217 }
11781218
11791219 #[ test]
1180- fn test_oci_config_default_values ( ) {
1181- let vars = OciConfig :: default ( ) . to_hashmap ( ) ;
1220+ fn test_global_defaults_base_values ( ) {
1221+ let vars = GlobalDefaults :: default ( ) . to_hashmap ( ) ;
11821222 assert_eq ! ( vars. len( ) , 4 ) ;
11831223 assert ! ( vars. get( "oci.registry" ) . is_some_and( |v| v == "docker.io" ) ) ;
11841224 assert ! ( vars. get( "oci.auth.basic.username" ) . is_some_and( |v| v == "" ) ) ;
@@ -1187,19 +1227,21 @@ k8s:
11871227 }
11881228
11891229 #[ 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 ( ) ,
1230+ fn test_global_defaults_provided_values ( ) {
1231+ let global_defaults = GlobalDefaults {
1232+ oci : OciConfig {
1233+ registry : "custom.docker.io" . to_string ( ) ,
1234+ auth : OciAuth {
1235+ basic : BasicAuth {
1236+ username : "user" . to_string ( ) ,
1237+ password : "pass" . to_string ( ) ,
1238+ } ,
1239+ bearer : "token" . to_string ( ) ,
11971240 } ,
1198- bearer : "token" . to_string ( ) ,
11991241 } ,
12001242 } ;
12011243
1202- let vars = oci_config . to_hashmap ( ) ;
1244+ let vars = global_defaults . to_hashmap ( ) ;
12031245 assert_eq ! ( vars. len( ) , 4 ) ;
12041246 assert ! (
12051247 vars. get( "oci.registry" )
0 commit comments