Repository: moby/moby (language: go)

Issue:
Incorrect swagger API definitions for network IPAM configuration
**Description**

The Swagger API definitions for network IPAM configuration do not match the possible types returned.

The swagger definition records the IPAM config as being a map with string keys and string values: https://github.com/moby/moby/blob/c72c1ca62cd20e74582a01b8a54a58ae7f646d4c/api/swagger.yaml
But `AuxiliaryAddresses` has a value that is itself a map: https://github.com/moby/moby/blob/c72c1ca62cd20e74582a01b8a54a58ae7f646d4c/api/types/network/network.go#L24

This is causing downstream SDKs that are auto-generated from the swagger definitions to fail when trying to parse these blocks (e.g. https://github.com/fussybeaver/bollard/issues/201).

**Steps to reproduce the issue:**
1. Create an macvlan docker network with some aux-addresses.
2. Perform a list networks API call and compare the results to the swagger API definitions.

**Describe the results you received:**

The following json is retrieved. Note the IPAM Config block containing a map as the value for AuxiliaryAddresses. This does not match the swagger definitions.

```json
{
    "Name": "services",
    "Id": "18e9cdac5d71b5b050b804b6d9d07aaa4104a986bf478e89057a088724c6328e",
    "Created": "2022-02-19T16:14:03.323536217Z",
    "Scope": "local",
    "Driver": "macvlan",
    "EnableIPv6": false,
    "IPAM": {
      "Driver": "default",
      "Options": null,
      "Config": [
        {
          "Subnet": "10.10.0.0/20",
          "IPRange": "10.10.12.0/24",
          "Gateway": "10.10.15.254",
          "AuxiliaryAddresses": { "bad": "10.10.12.0", "host": "10.10.12.1" }
        }
      ]
    },
    "Internal": false,
    "Attachable": true,
    "Ingress": false,
    "ConfigFrom": { "Network": "" },
    "ConfigOnly": false,
    "Containers": {},
    "Options": {
      "com.docker.network.bridge.name": "services",
      "parent": "enp1s0"
    },
    "Labels": {
      "com.docker.compose.network": "services",
      "com.docker.compose.project": "srv",
      "com.docker.compose.version": "1.24.1"
    }
  }
```

**Describe the results you expected:**

Resultant json should match the swagger definitions.

**Output of `docker version`:**

```
Client: Docker Engine - Community
 Version:           20.10.12
 API version:       1.41
 Go version:        go1.16.12
 Git commit:        e91ed57
 Built:             Mon Dec 13 11:45:33 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.12
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.12
  Git commit:       459d0df
  Built:            Mon Dec 13 11:43:42 2021
  OS/Arch:          linux/amd64
  Experimental:     true
 containerd:
  Version:          1.4.12
  GitCommit:        7b11cfaabd73bb80907dd23182b9347b4245eb5d
 runc:
  Version:          1.0.2
  GitCommit:        v1.0.2-0-g52b36a2
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
```

**Output of `docker info`:**

```
Client:
 Context:    default
 Debug Mode: false
 Plugins:
  app: Docker App (Docker Inc., v0.9.1-beta3)
  buildx: Docker Buildx (Docker Inc., v0.7.1-docker)
  scan: Docker Scan (Docker Inc., v0.12.0)

Server:
 Containers: 9
  Running: 9
  Paused: 0
  Stopped: 0
 Images: 11
 Server Version: 20.10.12
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 7b11cfaabd73bb80907dd23182b9347b4245eb5d
 runc version: v1.0.2-0-g52b36a2
 init version: de40ad0
 Security Options:
  apparmor
  seccomp
   Profile: default
  cgroupns
 Kernel Version: 5.13.0-28-generic
 Operating System: Ubuntu 21.10
 OSType: linux
 Architecture: x86_64
 CPUs: 4
 Total Memory: 14.83GiB
 Name: mandelbrot
 ID: ST3P:ZF23:DLND:YAX2:GKEZ:XWPF:2AP6:5UGM:WHGN:XSXV:GSE2:C7B4
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Username: mossop
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: true
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false
```



Discussion / hints:
I don't think the swagger 2.0 supports `anyOf`, so I wonder how this can be supported.

Fix patch:
diff --git a/api/swagger.yaml b/api/swagger.yaml
index 28f08cc3a3b08..8074303215b27 100644
--- a/api/swagger.yaml
+++ b/api/swagger.yaml
@@ -2035,15 +2035,27 @@ definitions:
           ```
         type: "array"
         items:
-          type: "object"
-          additionalProperties:
-            type: "string"
+          $ref: "#/definitions/IPAMConfig"
       Options:
         description: "Driver-specific options, specified as a map."
         type: "object"
         additionalProperties:
           type: "string"
 
+  IPAMConfig:
+    type: "object"
+    properties:
+      Subnet:
+        type: "string"
+      IPRange:
+        type: "string"
+      Gateway:
+        type: "string"
+      AuxiliaryAddresses:
+        type: "object"
+        additionalProperties:
+          type: "string"
+
   NetworkContainer:
     type: "object"
     properties:
diff --git a/docs/api/v1.41.yaml b/docs/api/v1.41.yaml
index 3da9a9fdf9882..cb742c66c84f5 100644
--- a/docs/api/v1.41.yaml
+++ b/docs/api/v1.41.yaml
@@ -2035,15 +2035,27 @@ definitions:
           ```
         type: "array"
         items:
-          type: "object"
-          additionalProperties:
-            type: "string"
+          $ref: "#/definitions/IPAMConfig"
       Options:
         description: "Driver-specific options, specified as a map."
         type: "object"
         additionalProperties:
           type: "string"
 
+  IPAMConfig:
+    type: "object"
+    properties:
+      Subnet:
+        type: "string"
+      IPRange:
+        type: "string"
+      Gateway:
+        type: "string"
+      AuxiliaryAddresses:
+        type: "object"
+        additionalProperties:
+          type: "string"
+
   NetworkContainer:
     type: "object"
     properties:


Test patch: