@@ -39,6 +39,7 @@ type merger func(any, any, tree.Path) (any, error)
3939var mergeSpecials = map [tree.Path ]merger {}
4040
4141func init () {
42+ mergeSpecials ["networks.*.ipam.config" ] = mergeIPAMConfig
4243 mergeSpecials ["services.*.annotations" ] = mergeToSequence
4344 mergeSpecials ["services.*.build" ] = mergeBuild
4445 mergeSpecials ["services.*.build.args" ] = mergeToSequence
@@ -197,6 +198,41 @@ func mergeUlimit(_ any, o any, p tree.Path) (any, error) {
197198 return o , nil
198199}
199200
201+ func mergeIPAMConfig (c any , o any , path tree.Path ) (any , error ) {
202+ var ipamConfigs []any
203+ for _ , original := range c .([]any ) {
204+ right := convertIntoMapping (original , nil )
205+ for _ , override := range o .([]any ) {
206+ left := convertIntoMapping (override , nil )
207+ if left ["subnet" ] != right ["subnet" ] {
208+ // check if left is already in ipamConfigs, add it if not and continue with the next config
209+ if ! slices .ContainsFunc (ipamConfigs , func (a any ) bool {
210+ return a .(map [string ]any )["subnet" ] == left ["subnet" ]
211+ }) {
212+ ipamConfigs = append (ipamConfigs , left )
213+ continue
214+ }
215+ }
216+ merged , err := mergeMappings (right , left , path )
217+ if err != nil {
218+ return nil , err
219+ }
220+ // find index of potential previous config with the same subnet in ipamConfigs
221+ indexIfExist := slices .IndexFunc (ipamConfigs , func (a any ) bool {
222+ return a .(map [string ]any )["subnet" ] == merged ["subnet" ]
223+ })
224+ // if a previous config is already in ipamConfigs, replace it
225+ if indexIfExist >= 0 {
226+ ipamConfigs [indexIfExist ] = merged
227+ } else {
228+ // or add the new config to ipamConfigs
229+ ipamConfigs = append (ipamConfigs , merged )
230+ }
231+ }
232+ }
233+ return ipamConfigs , nil
234+ }
235+
200236func convertIntoMapping (a any , defaultValue any ) map [string ]any {
201237 switch v := a .(type ) {
202238 case map [string ]any :
0 commit comments