Browse Source

Cleanup fallback to V1 plugins logic.

handleLegacy is a flag to indicate whether daemon is supporting legacy
plugins. When the time comes to remove support for legacy plugins,
flipping this bool is all that will be needed to remove legacy plugin
support. This can be a global variable rather than be embedded in the
manager, thereby cleaning up code.

Also rename to allowV1PluginsFallback for clarity.

Signed-off-by: Anusha Ragunathan <anusha@docker.com>
Anusha Ragunathan 9 years ago
parent
commit
031a2a5c4b
1 changed files with 37 additions and 27 deletions
  1. 37 27
      plugin/manager.go

+ 37 - 27
plugin/manager.go

@@ -24,7 +24,15 @@ import (
 
 
 const defaultPluginRuntimeDestination = "/run/docker/plugins"
 const defaultPluginRuntimeDestination = "/run/docker/plugins"
 
 
-var manager *Manager
+var (
+	manager *Manager
+
+	/* allowV1PluginsFallback determines daemon's support for V1 plugins.
+	 * When the time comes to remove support for V1 plugins, flipping
+	 * this bool is all that will be needed.
+	 */
+	allowV1PluginsFallback = true
+)
 
 
 // ErrNotFound indicates that a plugin was not found locally.
 // ErrNotFound indicates that a plugin was not found locally.
 type ErrNotFound string
 type ErrNotFound string
@@ -103,7 +111,6 @@ type Manager struct {
 	handlers          map[string]func(string, *plugins.Client)
 	handlers          map[string]func(string, *plugins.Client)
 	containerdClient  libcontainerd.Client
 	containerdClient  libcontainerd.Client
 	registryService   registry.Service
 	registryService   registry.Service
-	handleLegacy      bool
 	liveRestore       bool
 	liveRestore       bool
 	shutdown          bool
 	shutdown          bool
 	pluginEventLogger eventLogger
 	pluginEventLogger eventLogger
@@ -129,7 +136,6 @@ func Init(root string, remote libcontainerd.Remote, rs registry.Service, liveRes
 		nameToID:          make(map[string]string),
 		nameToID:          make(map[string]string),
 		handlers:          make(map[string]func(string, *plugins.Client)),
 		handlers:          make(map[string]func(string, *plugins.Client)),
 		registryService:   rs,
 		registryService:   rs,
-		handleLegacy:      true,
 		liveRestore:       liveRestore,
 		liveRestore:       liveRestore,
 		pluginEventLogger: evL,
 		pluginEventLogger: evL,
 	}
 	}
@@ -151,7 +157,7 @@ func Init(root string, remote libcontainerd.Remote, rs registry.Service, liveRes
 func Handle(capability string, callback func(string, *plugins.Client)) {
 func Handle(capability string, callback func(string, *plugins.Client)) {
 	pluginType := fmt.Sprintf("docker.%s/1", strings.ToLower(capability))
 	pluginType := fmt.Sprintf("docker.%s/1", strings.ToLower(capability))
 	manager.handlers[pluginType] = callback
 	manager.handlers[pluginType] = callback
-	if manager.handleLegacy {
+	if allowV1PluginsFallback {
 		plugins.Handle(capability, callback)
 		plugins.Handle(capability, callback)
 	}
 	}
 }
 }
@@ -175,12 +181,15 @@ func (pm *Manager) get(name string) (*plugin, error) {
 
 
 // FindWithCapability returns a list of plugins matching the given capability.
 // FindWithCapability returns a list of plugins matching the given capability.
 func FindWithCapability(capability string) ([]Plugin, error) {
 func FindWithCapability(capability string) ([]Plugin, error) {
-	handleLegacy := true
 	result := make([]Plugin, 0, 1)
 	result := make([]Plugin, 0, 1)
+
+	/* Daemon start always calls plugin.Init thereby initializing a manager.
+	 * So manager on experimental builds can never be nil, even while
+	 * handling legacy plugins. However, there are legacy plugin unit
+	 * tests where volume subsystem directly talks with the plugin,
+	 * bypassing the daemon. For such tests, this check is necessary.*/
 	if manager != nil {
 	if manager != nil {
-		handleLegacy = manager.handleLegacy
 		manager.RLock()
 		manager.RLock()
-		defer manager.RUnlock()
 		for _, p := range manager.plugins {
 		for _, p := range manager.plugins {
 			for _, typ := range p.PluginObj.Manifest.Interface.Types {
 			for _, typ := range p.PluginObj.Manifest.Interface.Types {
 				if strings.EqualFold(typ.Capability, capability) && typ.Prefix == "docker" {
 				if strings.EqualFold(typ.Capability, capability) && typ.Prefix == "docker" {
@@ -189,16 +198,17 @@ func FindWithCapability(capability string) ([]Plugin, error) {
 				}
 				}
 			}
 			}
 		}
 		}
+		manager.RUnlock()
 	}
 	}
-	if handleLegacy {
+
+	// Lookup with legacy model.
+	if allowV1PluginsFallback {
 		pl, err := plugins.GetAll(capability)
 		pl, err := plugins.GetAll(capability)
 		if err != nil {
 		if err != nil {
 			return nil, fmt.Errorf("legacy plugin: %v", err)
 			return nil, fmt.Errorf("legacy plugin: %v", err)
 		}
 		}
 		for _, p := range pl {
 		for _, p := range pl {
-			if _, ok := manager.nameToID[p.Name()]; !ok {
-				result = append(result, p)
-			}
+			result = append(result, p)
 		}
 		}
 	}
 	}
 	return result, nil
 	return result, nil
@@ -210,7 +220,8 @@ func LookupWithCapability(name, capability string) (Plugin, error) {
 		p   *plugin
 		p   *plugin
 		err error
 		err error
 	)
 	)
-	handleLegacy := true
+
+	// Lookup using new model.
 	if manager != nil {
 	if manager != nil {
 		fullName := name
 		fullName := name
 		if named, err := reference.ParseNamed(fullName); err == nil { // FIXME: validate
 		if named, err := reference.ParseNamed(fullName); err == nil { // FIXME: validate
@@ -224,31 +235,30 @@ func LookupWithCapability(name, capability string) (Plugin, error) {
 			fullName = ref.String()
 			fullName = ref.String()
 		}
 		}
 		p, err = manager.get(fullName)
 		p, err = manager.get(fullName)
-		if err != nil {
-			if _, ok := err.(ErrNotFound); !ok {
-				return nil, err
+		if err == nil {
+			capability = strings.ToLower(capability)
+			for _, typ := range p.PluginObj.Manifest.Interface.Types {
+				if typ.Capability == capability && typ.Prefix == "docker" {
+					return p, nil
+				}
 			}
 			}
-			handleLegacy = manager.handleLegacy
-		} else {
-			handleLegacy = false
+			return nil, ErrInadequateCapability{name, capability}
+		}
+		if _, ok := err.(ErrNotFound); !ok {
+			return nil, err
 		}
 		}
 	}
 	}
-	if handleLegacy {
+
+	// Lookup using legacy model
+	if allowV1PluginsFallback {
 		p, err := plugins.Get(name, capability)
 		p, err := plugins.Get(name, capability)
 		if err != nil {
 		if err != nil {
 			return nil, fmt.Errorf("legacy plugin: %v", err)
 			return nil, fmt.Errorf("legacy plugin: %v", err)
 		}
 		}
 		return p, nil
 		return p, nil
-	} else if err != nil {
-		return nil, err
 	}
 	}
 
 
-	for _, typ := range p.PluginObj.Manifest.Interface.Types {
-		if strings.EqualFold(typ.Capability, capability) && typ.Prefix == "docker" {
-			return p, nil
-		}
-	}
-	return nil, ErrInadequateCapability{name, capability}
+	return nil, err
 }
 }
 
 
 // StateChanged updates plugin internals using libcontainerd events.
 // StateChanged updates plugin internals using libcontainerd events.