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  }