github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/libnetwork/ipams/remote/remote_test.go (about) 1 package remote 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "net" 9 "net/http" 10 "net/http/httptest" 11 "os" 12 "testing" 13 14 "github.com/docker/docker/pkg/plugins" 15 "github.com/docker/libnetwork/ipamapi" 16 _ "github.com/docker/libnetwork/testutils" 17 ) 18 19 func decodeToMap(r *http.Request) (res map[string]interface{}, err error) { 20 err = json.NewDecoder(r.Body).Decode(&res) 21 return 22 } 23 24 func handle(t *testing.T, mux *http.ServeMux, method string, h func(map[string]interface{}) interface{}) { 25 mux.HandleFunc(fmt.Sprintf("/%s.%s", ipamapi.PluginEndpointType, method), func(w http.ResponseWriter, r *http.Request) { 26 ask, err := decodeToMap(r) 27 if err != nil && err != io.EOF { 28 t.Fatal(err) 29 } 30 answer := h(ask) 31 err = json.NewEncoder(w).Encode(&answer) 32 if err != nil { 33 t.Fatal(err) 34 } 35 }) 36 } 37 38 func setupPlugin(t *testing.T, name string, mux *http.ServeMux) func() { 39 if err := os.MkdirAll("/etc/docker/plugins", 0755); err != nil { 40 t.Fatal(err) 41 } 42 43 server := httptest.NewServer(mux) 44 if server == nil { 45 t.Fatal("Failed to start an HTTP Server") 46 } 47 48 if err := ioutil.WriteFile(fmt.Sprintf("/etc/docker/plugins/%s.spec", name), []byte(server.URL), 0644); err != nil { 49 t.Fatal(err) 50 } 51 52 mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) { 53 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 54 fmt.Fprintf(w, `{"Implements": ["%s"]}`, ipamapi.PluginEndpointType) 55 }) 56 57 return func() { 58 if err := os.RemoveAll("/etc/docker/plugins"); err != nil { 59 t.Fatal(err) 60 } 61 server.Close() 62 } 63 } 64 65 func TestGetCapabilities(t *testing.T) { 66 var plugin = "test-ipam-driver-capabilities" 67 68 mux := http.NewServeMux() 69 defer setupPlugin(t, plugin, mux)() 70 71 handle(t, mux, "GetCapabilities", func(msg map[string]interface{}) interface{} { 72 return map[string]interface{}{ 73 "RequiresMACAddress": true, 74 } 75 }) 76 77 p, err := plugins.Get(plugin, ipamapi.PluginEndpointType) 78 if err != nil { 79 t.Fatal(err) 80 } 81 82 d := newAllocator(plugin, p.Client()) 83 84 caps, err := d.(*allocator).getCapabilities() 85 if err != nil { 86 t.Fatal(err) 87 } 88 89 if !caps.RequiresMACAddress || caps.RequiresRequestReplay { 90 t.Fatalf("Unexpected capability: %v", caps) 91 } 92 } 93 94 func TestGetCapabilitiesFromLegacyDriver(t *testing.T) { 95 var plugin = "test-ipam-legacy-driver" 96 97 mux := http.NewServeMux() 98 defer setupPlugin(t, plugin, mux)() 99 100 p, err := plugins.Get(plugin, ipamapi.PluginEndpointType) 101 if err != nil { 102 t.Fatal(err) 103 } 104 105 d := newAllocator(plugin, p.Client()) 106 107 if _, err := d.(*allocator).getCapabilities(); err == nil { 108 t.Fatalf("Expected error, but got Success %v", err) 109 } 110 } 111 112 func TestGetDefaultAddressSpaces(t *testing.T) { 113 var plugin = "test-ipam-driver-addr-spaces" 114 115 mux := http.NewServeMux() 116 defer setupPlugin(t, plugin, mux)() 117 118 handle(t, mux, "GetDefaultAddressSpaces", func(msg map[string]interface{}) interface{} { 119 return map[string]interface{}{ 120 "LocalDefaultAddressSpace": "white", 121 "GlobalDefaultAddressSpace": "blue", 122 } 123 }) 124 125 p, err := plugins.Get(plugin, ipamapi.PluginEndpointType) 126 if err != nil { 127 t.Fatal(err) 128 } 129 130 d := newAllocator(plugin, p.Client()) 131 132 l, g, err := d.(*allocator).GetDefaultAddressSpaces() 133 if err != nil { 134 t.Fatal(err) 135 } 136 137 if l != "white" || g != "blue" { 138 t.Fatalf("Unexpected default local and global address spaces: %s, %s", l, g) 139 } 140 } 141 142 func TestRemoteDriver(t *testing.T) { 143 var plugin = "test-ipam-driver" 144 145 mux := http.NewServeMux() 146 defer setupPlugin(t, plugin, mux)() 147 148 handle(t, mux, "GetDefaultAddressSpaces", func(msg map[string]interface{}) interface{} { 149 return map[string]interface{}{ 150 "LocalDefaultAddressSpace": "white", 151 "GlobalDefaultAddressSpace": "blue", 152 } 153 }) 154 155 handle(t, mux, "RequestPool", func(msg map[string]interface{}) interface{} { 156 as := "white" 157 if v, ok := msg["AddressSpace"]; ok && v.(string) != "" { 158 as = v.(string) 159 } 160 161 pl := "172.18.0.0/16" 162 sp := "" 163 if v, ok := msg["Pool"]; ok && v.(string) != "" { 164 pl = v.(string) 165 } 166 if v, ok := msg["SubPool"]; ok && v.(string) != "" { 167 sp = v.(string) 168 } 169 pid := fmt.Sprintf("%s/%s", as, pl) 170 if sp != "" { 171 pid = fmt.Sprintf("%s/%s", pid, sp) 172 } 173 return map[string]interface{}{ 174 "PoolID": pid, 175 "Pool": pl, 176 "Data": map[string]string{"DNS": "8.8.8.8"}, 177 } 178 }) 179 180 handle(t, mux, "ReleasePool", func(msg map[string]interface{}) interface{} { 181 if _, ok := msg["PoolID"]; !ok { 182 t.Fatalf("Missing PoolID in Release request") 183 } 184 return map[string]interface{}{} 185 }) 186 187 handle(t, mux, "RequestAddress", func(msg map[string]interface{}) interface{} { 188 if _, ok := msg["PoolID"]; !ok { 189 t.Fatalf("Missing PoolID in address request") 190 } 191 prefAddr := "" 192 if v, ok := msg["Address"]; ok { 193 prefAddr = v.(string) 194 } 195 ip := prefAddr 196 if ip == "" { 197 ip = "172.20.0.34" 198 } 199 ip = fmt.Sprintf("%s/16", ip) 200 return map[string]interface{}{ 201 "Address": ip, 202 } 203 }) 204 205 handle(t, mux, "ReleaseAddress", func(msg map[string]interface{}) interface{} { 206 if _, ok := msg["PoolID"]; !ok { 207 t.Fatalf("Missing PoolID in address request") 208 } 209 if _, ok := msg["Address"]; !ok { 210 t.Fatalf("Missing Address in release address request") 211 } 212 return map[string]interface{}{} 213 }) 214 215 p, err := plugins.Get(plugin, ipamapi.PluginEndpointType) 216 if err != nil { 217 t.Fatal(err) 218 } 219 220 d := newAllocator(plugin, p.Client()) 221 222 l, g, err := d.(*allocator).GetDefaultAddressSpaces() 223 if err != nil { 224 t.Fatal(err) 225 } 226 if l != "white" || g != "blue" { 227 t.Fatalf("Unexpected default local/global address spaces: %s, %s", l, g) 228 } 229 230 // Request any pool 231 poolID, pool, _, err := d.RequestPool("white", "", "", nil, false) 232 if err != nil { 233 t.Fatal(err) 234 } 235 if poolID != "white/172.18.0.0/16" { 236 t.Fatalf("Unexpected pool id: %s", poolID) 237 } 238 if pool == nil || pool.String() != "172.18.0.0/16" { 239 t.Fatalf("Unexpected pool: %s", pool) 240 } 241 242 // Request specific pool 243 poolID2, pool2, ops, err := d.RequestPool("white", "172.20.0.0/16", "", nil, false) 244 if err != nil { 245 t.Fatal(err) 246 } 247 if poolID2 != "white/172.20.0.0/16" { 248 t.Fatalf("Unexpected pool id: %s", poolID2) 249 } 250 if pool2 == nil || pool2.String() != "172.20.0.0/16" { 251 t.Fatalf("Unexpected pool: %s", pool2) 252 } 253 if dns, ok := ops["DNS"]; !ok || dns != "8.8.8.8" { 254 t.Fatalf("Missing options") 255 } 256 257 // Request specific pool and subpool 258 poolID3, pool3, _, err := d.RequestPool("white", "172.20.0.0/16", "172.20.3.0/24" /*nil*/, map[string]string{"culo": "yes"}, false) 259 if err != nil { 260 t.Fatal(err) 261 } 262 if poolID3 != "white/172.20.0.0/16/172.20.3.0/24" { 263 t.Fatalf("Unexpected pool id: %s", poolID3) 264 } 265 if pool3 == nil || pool3.String() != "172.20.0.0/16" { 266 t.Fatalf("Unexpected pool: %s", pool3) 267 } 268 269 // Request any address 270 addr, _, err := d.RequestAddress(poolID2, nil, nil) 271 if err != nil { 272 t.Fatal(err) 273 } 274 if addr == nil || addr.String() != "172.20.0.34/16" { 275 t.Fatalf("Unexpected address: %s", addr) 276 } 277 278 // Request specific address 279 addr2, _, err := d.RequestAddress(poolID2, net.ParseIP("172.20.1.45"), nil) 280 if err != nil { 281 t.Fatal(err) 282 } 283 if addr2 == nil || addr2.String() != "172.20.1.45/16" { 284 t.Fatalf("Unexpected address: %s", addr2) 285 } 286 287 // Release address 288 err = d.ReleaseAddress(poolID, net.ParseIP("172.18.1.45")) 289 if err != nil { 290 t.Fatal(err) 291 } 292 }