Move responsibility of ls/inspect to volume driver
Makes `docker volume ls` and `docker volume inspect` ask the volume drivers rather than only using what is cached locally. Previously in order to use a volume from an external driver, one would either have to use `docker volume create` or have a container that is already using that volume for it to be visible to the other volume API's. For keeping uniqueness of volume names in the daemon, names are bound to a driver on a first come first serve basis. If two drivers have a volume with the same name, the first one is chosen, and a warning is logged about the second one. Adds 2 new methods to the plugin API, `List` and `Get`. If a plugin does not implement these endpoints, a user will not be able to find the specified volumes as well requests go through the drivers. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
		
							parent
							
								
									5548d51a76
								
							
						
					
					
						commit
						390876ba18
					
				
					 2 changed files with 78 additions and 5 deletions
				
			
		|  | @ -25,6 +25,38 @@ func newLocalRegistry() localRegistry { | |||
| 	return localRegistry{} | ||||
| } | ||||
| 
 | ||||
| // Scan scans all the plugin paths and returns all the names it found | ||||
| func Scan() ([]string, error) { | ||||
| 	var names []string | ||||
| 	if err := filepath.Walk(socketsPath, func(path string, fi os.FileInfo, err error) error { | ||||
| 		if err != nil { | ||||
| 			return nil | ||||
| 		} | ||||
| 
 | ||||
| 		if fi.Mode()&os.ModeSocket != 0 { | ||||
| 			name := strings.TrimSuffix(fi.Name(), filepath.Ext(fi.Name())) | ||||
| 			names = append(names, name) | ||||
| 		} | ||||
| 		return nil | ||||
| 	}); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	for _, path := range specsPaths { | ||||
| 		if err := filepath.Walk(path, func(p string, fi os.FileInfo, err error) error { | ||||
| 			if err != nil || fi.IsDir() { | ||||
| 				return nil | ||||
| 			} | ||||
| 			name := strings.TrimSuffix(fi.Name(), filepath.Ext(fi.Name())) | ||||
| 			names = append(names, name) | ||||
| 			return nil | ||||
| 		}); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	return names, nil | ||||
| } | ||||
| 
 | ||||
| // Plugin returns the plugin registered with the given name (or returns an error). | ||||
| func (l *localRegistry) Plugin(name string) (*Plugin, error) { | ||||
| 	socketpaths := pluginPaths(socketsPath, name, ".sock") | ||||
|  |  | |||
|  | @ -108,6 +108,15 @@ func (p *Plugin) activateWithLock() error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *Plugin) implements(kind string) bool { | ||||
| 	for _, driver := range p.Manifest.Implements { | ||||
| 		if driver == kind { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func load(name string) (*Plugin, error) { | ||||
| 	return loadWithRetry(name, true) | ||||
| } | ||||
|  | @ -166,12 +175,10 @@ func Get(name, imp string) (*Plugin, error) { | |||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for _, driver := range pl.Manifest.Implements { | ||||
| 		logrus.Debugf("%s implements: %s", name, driver) | ||||
| 		if driver == imp { | ||||
| 	if pl.implements(imp) { | ||||
| 		logrus.Debugf("%s implements: %s", name, imp) | ||||
| 		return pl, nil | ||||
| 	} | ||||
| 	} | ||||
| 	return nil, ErrNotImplements | ||||
| } | ||||
| 
 | ||||
|  | @ -179,3 +186,37 @@ func Get(name, imp string) (*Plugin, error) { | |||
| func Handle(iface string, fn func(string, *Client)) { | ||||
| 	extpointHandlers[iface] = fn | ||||
| } | ||||
| 
 | ||||
| // GetAll returns all the plugins for the specified implementation | ||||
| func GetAll(imp string) ([]*Plugin, error) { | ||||
| 	pluginNames, err := Scan() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	type plLoad struct { | ||||
| 		pl  *Plugin | ||||
| 		err error | ||||
| 	} | ||||
| 
 | ||||
| 	chPl := make(chan plLoad, len(pluginNames)) | ||||
| 	for _, name := range pluginNames { | ||||
| 		go func(name string) { | ||||
| 			pl, err := loadWithRetry(name, false) | ||||
| 			chPl <- plLoad{pl, err} | ||||
| 		}(name) | ||||
| 	} | ||||
| 
 | ||||
| 	var out []*Plugin | ||||
| 	for i := 0; i < len(pluginNames); i++ { | ||||
| 		pl := <-chPl | ||||
| 		if pl.err != nil { | ||||
| 			logrus.Error(err) | ||||
| 			continue | ||||
| 		} | ||||
| 		if pl.pl.implements(imp) { | ||||
| 			out = append(out, pl.pl) | ||||
| 		} | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue