Signed-off-by: Madhu Venugopal <madhu@docker.com>
| ... | ... |
@@ -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 |
+} |