Browse code

dynamic service binding.

Signed-off-by: Dong Chen <dongluo.chen@docker.com>

Dong Chen authored on 2016/09/18 15:30:39
Showing 5 changed files
... ...
@@ -27,6 +27,8 @@ type Backend interface {
27 27
 	ContainerStart(name string, hostConfig *container.HostConfig, validateHostname bool, checkpoint string, checkpointDir string) error
28 28
 	ContainerStop(name string, seconds *int) error
29 29
 	ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
30
+	ActivateContainerServiceBinding(containerName string) error
31
+	DeactivateContainerServiceBinding(containerName string) error
30 32
 	UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error
31 33
 	ContainerInspectCurrent(name string, size bool) (*types.ContainerJSON, error)
32 34
 	ContainerWaitWithContext(ctx context.Context, name string) error
... ...
@@ -331,6 +331,14 @@ func (c *containerAdapter) createVolumes(ctx context.Context) error {
331 331
 	return nil
332 332
 }
333 333
 
334
+func (c *containerAdapter) activateServiceBinding() error {
335
+	return c.backend.ActivateContainerServiceBinding(c.container.name())
336
+}
337
+
338
+func (c *containerAdapter) deactivateServiceBinding() error {
339
+	return c.backend.DeactivateContainerServiceBinding(c.container.name())
340
+}
341
+
334 342
 // todo: typed/wrapped errors
335 343
 func isContainerCreateNameConflict(err error) bool {
336 344
 	return strings.Contains(err.Error(), "Conflict. The name")
... ...
@@ -183,6 +183,10 @@ func (r *controller) Start(ctx context.Context) error {
183 183
 
184 184
 	// no health check
185 185
 	if ctnr.Config == nil || ctnr.Config.Healthcheck == nil {
186
+		if err := r.adapter.activateServiceBinding(); err != nil {
187
+			log.G(ctx).WithError(err).Errorf("failed to activate service binding for container %s which has no healthcheck config", r.adapter.container.name())
188
+			return err
189
+		}
186 190
 		return nil
187 191
 	}
188 192
 
... ...
@@ -225,6 +229,10 @@ func (r *controller) Start(ctx context.Context) error {
225 225
 				// set health check error, and wait for container to fully exit ("die" event)
226 226
 				healthErr = ErrContainerUnhealthy
227 227
 			case "health_status: healthy":
228
+				if err := r.adapter.activateServiceBinding(); err != nil {
229
+					log.G(ctx).WithError(err).Errorf("failed to activate service binding for container %s after healthy event", r.adapter.container.name())
230
+					return err
231
+				}
228 232
 				return nil
229 233
 			}
230 234
 		case <-ctx.Done():
... ...
@@ -290,6 +298,12 @@ func (r *controller) Shutdown(ctx context.Context) error {
290 290
 		r.cancelPull()
291 291
 	}
292 292
 
293
+	// remove container from service binding
294
+	if err := r.adapter.deactivateServiceBinding(); err != nil {
295
+		log.G(ctx).WithError(err).Errorf("failed to deactivate service binding for container %s", r.adapter.container.name())
296
+		return err
297
+	}
298
+
293 299
 	if err := r.adapter.shutdown(ctx); err != nil {
294 300
 		if isUnknownContainer(err) || isStoppedContainer(err) {
295 301
 			return nil
... ...
@@ -719,6 +719,13 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName
719 719
 		return err
720 720
 	}
721 721
 
722
+	if !container.Managed {
723
+		// add container name/alias to DNS
724
+		if err := daemon.ActivateContainerServiceBinding(container.Name); err != nil {
725
+			return fmt.Errorf("Activate container service binding for %s failed: %v", container.Name, err)
726
+		}
727
+	}
728
+
722 729
 	if err := container.UpdateJoinInfo(n, ep); err != nil {
723 730
 		return fmt.Errorf("Updating join info failed: %v", err)
724 731
 	}
... ...
@@ -987,3 +994,29 @@ func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, netw
987 987
 	}
988 988
 	return nil
989 989
 }
990
+
991
+// ActivateContainerServiceBinding puts this container into load balancer active rotation and DNS response
992
+func (daemon *Daemon) ActivateContainerServiceBinding(containerName string) error {
993
+	container, err := daemon.GetContainer(containerName)
994
+	if err != nil {
995
+		return err
996
+	}
997
+	sb := daemon.getNetworkSandbox(container)
998
+	if sb == nil {
999
+		return fmt.Errorf("network sandbox not exists for container %s", containerName)
1000
+	}
1001
+	return sb.EnableService()
1002
+}
1003
+
1004
+// DeactivateContainerServiceBinding remove this container fromload balancer active rotation, and DNS response
1005
+func (daemon *Daemon) DeactivateContainerServiceBinding(containerName string) error {
1006
+	container, err := daemon.GetContainer(containerName)
1007
+	if err != nil {
1008
+		return err
1009
+	}
1010
+	sb := daemon.getNetworkSandbox(container)
1011
+	if sb == nil {
1012
+		return fmt.Errorf("network sandbox not exists for container %s", containerName)
1013
+	}
1014
+	return sb.DisableService()
1015
+}
... ...
@@ -178,6 +178,10 @@ func (daemon *Daemon) SetupIngress(create clustertypes.NetworkCreateRequest, nod
178 178
 		if err := ep.Join(sb, nil); err != nil {
179 179
 			logrus.Errorf("Failed joining ingress sandbox to ingress endpoint: %v", err)
180 180
 		}
181
+
182
+		if err := sb.EnableService(); err != nil {
183
+			logrus.WithError(err).Error("Failed enabling service for ingress sandbox")
184
+		}
181 185
 	}()
182 186
 
183 187
 	return nil