Browse code

Pass network driver option in docker network command

Signed-off-by: Madhu Venugopal <madhu@docker.com>

Madhu Venugopal authored on 2015/10/15 10:49:27
Showing 6 changed files
... ...
@@ -34,6 +34,7 @@ func (cli *DockerCli) CmdNetwork(args ...string) error {
34 34
 func (cli *DockerCli) CmdNetworkCreate(args ...string) error {
35 35
 	cmd := Cli.Subcmd("network create", []string{"NETWORK-NAME"}, "Creates a new network with a name specified by the user", false)
36 36
 	flDriver := cmd.String([]string{"d", "-driver"}, "bridge", "Driver to manage the Network")
37
+	flOpts := opts.NewMapOpts(nil, nil)
37 38
 
38 39
 	flIpamDriver := cmd.String([]string{"-ipam-driver"}, "default", "IP Address Management Driver")
39 40
 	flIpamSubnet := opts.NewListOpts(nil)
... ...
@@ -41,10 +42,11 @@ func (cli *DockerCli) CmdNetworkCreate(args ...string) error {
41 41
 	flIpamGateway := opts.NewListOpts(nil)
42 42
 	flIpamAux := opts.NewMapOpts(nil, nil)
43 43
 
44
-	cmd.Var(&flIpamSubnet, []string{"-subnet"}, "Subnet in CIDR format that represents a network segment")
44
+	cmd.Var(&flIpamSubnet, []string{"-subnet"}, "subnet in CIDR format that represents a network segment")
45 45
 	cmd.Var(&flIpamIPRange, []string{"-ip-range"}, "allocate container ip from a sub-range")
46 46
 	cmd.Var(&flIpamGateway, []string{"-gateway"}, "ipv4 or ipv6 Gateway for the master subnet")
47
-	cmd.Var(flIpamAux, []string{"-aux-address"}, "Auxiliary ipv4 or ipv6 addresses used by network driver")
47
+	cmd.Var(flIpamAux, []string{"-aux-address"}, "auxiliary ipv4 or ipv6 addresses used by Network driver")
48
+	cmd.Var(flOpts, []string{"o", "-opt"}, "set driver specific options")
48 49
 
49 50
 	cmd.Require(flag.Exact, 1)
50 51
 	err := cmd.ParseFlags(args, true)
... ...
@@ -62,6 +64,7 @@ func (cli *DockerCli) CmdNetworkCreate(args ...string) error {
62 62
 		Name:           cmd.Arg(0),
63 63
 		Driver:         *flDriver,
64 64
 		IPAM:           network.IPAM{Driver: *flIpamDriver, Config: ipamCfg},
65
+		Options:        flOpts.GetAll(),
65 66
 		CheckDuplicate: true,
66 67
 	}
67 68
 	obj, _, err := readBody(cli.call("POST", "/networks/create", nc, nil))
... ...
@@ -96,7 +96,7 @@ func (n *networkRouter) postNetworkCreate(ctx context.Context, w http.ResponseWr
96 96
 		warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID())
97 97
 	}
98 98
 
99
-	nw, err = n.daemon.CreateNetwork(create.Name, create.Driver, create.IPAM)
99
+	nw, err = n.daemon.CreateNetwork(create.Name, create.Driver, create.IPAM, create.Options)
100 100
 	if err != nil {
101 101
 		return err
102 102
 	}
... ...
@@ -174,6 +174,7 @@ func buildNetworkResource(nw libnetwork.Network) *types.NetworkResource {
174 174
 	r.ID = nw.ID()
175 175
 	r.Scope = nw.Info().Scope()
176 176
 	r.Driver = nw.Type()
177
+	r.Options = nw.Info().DriverOptions()
177 178
 	r.Containers = make(map[string]types.EndpointResource)
178 179
 	buildIpamResources(r, nw)
179 180
 
... ...
@@ -319,6 +319,7 @@ type NetworkResource struct {
319 319
 	Driver     string                      `json:"driver"`
320 320
 	IPAM       network.IPAM                `json:"ipam"`
321 321
 	Containers map[string]EndpointResource `json:"containers"`
322
+	Options    map[string]string           `json:"options"`
322 323
 }
323 324
 
324 325
 //EndpointResource contains network resources allocated and usd for a container in a network
... ...
@@ -331,10 +332,11 @@ type EndpointResource struct {
331 331
 
332 332
 // NetworkCreate is the expected body of the "create network" http request message
333 333
 type NetworkCreate struct {
334
-	Name           string       `json:"name"`
335
-	CheckDuplicate bool         `json:"check_duplicate"`
336
-	Driver         string       `json:"driver"`
337
-	IPAM           network.IPAM `json:"ipam"`
334
+	Name           string            `json:"name"`
335
+	CheckDuplicate bool              `json:"check_duplicate"`
336
+	Driver         string            `json:"driver"`
337
+	IPAM           network.IPAM      `json:"ipam"`
338
+	Options        map[string]string `json:"options"`
338 339
 }
339 340
 
340 341
 // NetworkCreateResponse is the response message sent by the server for network create call
... ...
@@ -80,7 +80,7 @@ func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
80 80
 }
81 81
 
82 82
 // CreateNetwork creates a network with the given name, driver and other optional parameters
83
-func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM) (libnetwork.Network, error) {
83
+func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM, options map[string]string) (libnetwork.Network, error) {
84 84
 	c := daemon.netController
85 85
 	if driver == "" {
86 86
 		driver = c.Config().Daemon.DefaultDriver
... ...
@@ -96,6 +96,7 @@ func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM) (lib
96 96
 	if len(ipam.Config) > 0 {
97 97
 		nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf))
98 98
 	}
99
+	nwOptions = append(nwOptions, libnetwork.NetworkOptionDriverOpts(options))
99 100
 	return c.NewNetwork(driver, name, nwOptions...)
100 101
 }
101 102
 
... ...
@@ -74,9 +74,10 @@ func (s *DockerSuite) TestApiNetworkInspect(c *check.C) {
74 74
 		Config: []network.IPAMConfig{{Subnet: "172.28.0.0/16", IPRange: "172.28.5.0/24", Gateway: "172.28.5.254"}},
75 75
 	}
76 76
 	config := types.NetworkCreate{
77
-		Name:   "br0",
78
-		Driver: "bridge",
79
-		IPAM:   ipam,
77
+		Name:    "br0",
78
+		Driver:  "bridge",
79
+		IPAM:    ipam,
80
+		Options: map[string]string{"foo": "bar", "opts": "dopts"},
80 81
 	}
81 82
 	id0 := createNetwork(c, config, true)
82 83
 	c.Assert(isNetworkAvailable(c, "br0"), checker.Equals, true)
... ...
@@ -86,6 +87,9 @@ func (s *DockerSuite) TestApiNetworkInspect(c *check.C) {
86 86
 	c.Assert(nr.IPAM.Config[0].Subnet, checker.Equals, "172.28.0.0/16")
87 87
 	c.Assert(nr.IPAM.Config[0].IPRange, checker.Equals, "172.28.5.0/24")
88 88
 	c.Assert(nr.IPAM.Config[0].Gateway, checker.Equals, "172.28.5.254")
89
+	c.Assert(nr.Options["foo"], checker.Equals, "bar")
90
+	c.Assert(nr.Options["opts"], checker.Equals, "dopts")
91
+
89 92
 	// delete the network and make sure it is deleted
90 93
 	deleteNetwork(c, id0, true)
91 94
 	c.Assert(isNetworkAvailable(c, "br0"), checker.Equals, false)
... ...
@@ -15,11 +15,15 @@ import (
15 15
 	"github.com/docker/docker/api/types"
16 16
 	"github.com/docker/docker/pkg/integration/checker"
17 17
 	"github.com/docker/libnetwork/driverapi"
18
+	remoteapi "github.com/docker/libnetwork/drivers/remote/api"
19
+	"github.com/docker/libnetwork/netlabel"
18 20
 	"github.com/go-check/check"
19 21
 )
20 22
 
21 23
 const dummyNetworkDriver = "dummy-network-driver"
22 24
 
25
+var remoteDriverNetworkRequest remoteapi.CreateNetworkRequest
26
+
23 27
 func init() {
24 28
 	check.Suite(&DockerNetworkSuite{
25 29
 		ds: &DockerSuite{},
... ...
@@ -57,6 +61,11 @@ func (s *DockerNetworkSuite) SetUpSuite(c *check.C) {
57 57
 	})
58 58
 
59 59
 	mux.HandleFunc(fmt.Sprintf("/%s.CreateNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
60
+		err := json.NewDecoder(r.Body).Decode(&remoteDriverNetworkRequest)
61
+		if err != nil {
62
+			http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest)
63
+			return
64
+		}
60 65
 		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
61 66
 		fmt.Fprintf(w, "null")
62 67
 	})
... ...
@@ -256,3 +265,16 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpamInvalidCombinations(c *check.C
256 256
 	c.Assert(err, check.NotNil)
257 257
 	dockerCmd(c, "network", "rm", "test0")
258 258
 }
259
+
260
+func (s *DockerNetworkSuite) TestDockerNetworkDriverOptions(c *check.C) {
261
+	dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, "-o", "opt1=drv1", "-o", "opt2=drv2", "testopt")
262
+	assertNwIsAvailable(c, "testopt")
263
+	gopts := remoteDriverNetworkRequest.Options[netlabel.GenericData]
264
+	c.Assert(gopts, checker.NotNil)
265
+	opts, ok := gopts.(map[string]interface{})
266
+	c.Assert(ok, checker.Equals, true)
267
+	c.Assert(opts["opt1"], checker.Equals, "drv1")
268
+	c.Assert(opts["opt2"], checker.Equals, "drv2")
269
+	dockerCmd(c, "network", "rm", "testopt")
270
+
271
+}