Support for --publish-service flag in docker run

This commit makes use of the CNM model supported by LibNetwork and
provides an ability to let a container to publish a specified service.
Behind the scenes, if a service with the given name doesnt exist, it is
automatically created on appropriate network and attach the container.

Signed-off-by: Alessandro Boch <aboch@docker.com>
Signed-off-by: Madhu Venugopal <madhu@docker.com>
Upstream-commit: 1ac350a0ecfe9d28c82d6dff6a763a378ff9c472
Component: engine
This commit is contained in:
Madhu Venugopal
2015-06-20 11:03:38 -07:00
parent 4d14f9391a
commit cb3c5d7cf6
5 changed files with 118 additions and 72 deletions
+47 -13
View File
@@ -737,11 +737,23 @@ func (container *Container) buildCreateEndpointOptions() ([]libnetwork.EndpointO
return createOptions, nil
}
func createDefaultNetwork(controller libnetwork.NetworkController) (libnetwork.Network, error) {
func parseService(controller libnetwork.NetworkController, service string) (string, string, string) {
dn := controller.Config().Daemon.DefaultNetwork
dd := controller.Config().Daemon.DefaultDriver
snd := strings.Split(service, ".")
if len(snd) > 2 {
return strings.Join(snd[:len(snd)-2], "."), snd[len(snd)-2], snd[len(snd)-1]
}
if len(snd) > 1 {
return snd[0], snd[1], dd
}
return snd[0], dn, dd
}
func createNetwork(controller libnetwork.NetworkController, dnet string, driver string) (libnetwork.Network, error) {
createOptions := []libnetwork.NetworkOption{}
genericOption := options.Generic{}
dnet := controller.Config().Daemon.DefaultNetwork
driver := controller.Config().Daemon.DefaultDriver
// Bridge driver is special due to legacy reasons
if runconfig.NetworkMode(driver).IsBridge() {
@@ -763,31 +775,53 @@ func (container *Container) AllocateNetwork() error {
return nil
}
var networkDriver string
service := container.Config.PublishService
networkName := mode.NetworkName()
if mode.IsDefault() {
networkName = controller.Config().Daemon.DefaultNetwork
if service != "" {
service, networkName, networkDriver = parseService(controller, service)
} else {
networkName = controller.Config().Daemon.DefaultNetwork
networkDriver = controller.Config().Daemon.DefaultDriver
}
} else if service != "" {
return fmt.Errorf("conflicting options: publishing a service and network mode")
}
if service == "" {
service = strings.Replace(container.Name, ".", "-", -1)
}
var err error
n, err := controller.NetworkByName(networkName)
if err != nil {
if !mode.IsDefault() {
return fmt.Errorf("error locating network with name %s: %v", networkName, err)
// Create Network automatically only in default mode
if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok || !mode.IsDefault() {
return err
}
if n, err = createDefaultNetwork(controller); err != nil {
if n, err = createNetwork(controller, networkName, networkDriver); err != nil {
return err
}
}
createOptions, err := container.buildCreateEndpointOptions()
ep, err := n.EndpointByName(service)
if err != nil {
return err
}
if _, ok := err.(libnetwork.ErrNoSuchEndpoint); !ok {
return err
}
ep, err := n.CreateEndpoint(container.Name, createOptions...)
if err != nil {
return err
createOptions, err := container.buildCreateEndpointOptions()
if err != nil {
return err
}
ep, err = n.CreateEndpoint(service, createOptions...)
if err != nil {
return err
}
}
if err := container.updateNetworkSettings(n, ep); err != nil {