github.com/yamamoto-febc/docker@v1.9.0/pkg/plugins/discovery.go (about) 1 package plugins 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "io/ioutil" 8 "net/url" 9 "os" 10 "path/filepath" 11 "strings" 12 ) 13 14 var ( 15 // ErrNotFound plugin not found 16 ErrNotFound = errors.New("Plugin not found") 17 socketsPath = "/run/docker/plugins" 18 specsPaths = []string{"/etc/docker/plugins", "/usr/lib/docker/plugins"} 19 ) 20 21 // Registry defines behavior of a registry of plugins. 22 type Registry interface { 23 // Plugins lists all plugins. 24 Plugins() ([]*Plugin, error) 25 // Plugin returns the plugin registered with the given name (or returns an error). 26 Plugin(name string) (*Plugin, error) 27 } 28 29 // LocalRegistry defines a registry that is local (using unix socket). 30 type LocalRegistry struct{} 31 32 func newLocalRegistry() LocalRegistry { 33 return LocalRegistry{} 34 } 35 36 // Plugin returns the plugin registered with the given name (or returns an error). 37 func (l *LocalRegistry) Plugin(name string) (*Plugin, error) { 38 socketpaths := pluginPaths(socketsPath, name, ".sock") 39 40 for _, p := range socketpaths { 41 if fi, err := os.Stat(p); err == nil && fi.Mode()&os.ModeSocket != 0 { 42 return newLocalPlugin(name, "unix://"+p), nil 43 } 44 } 45 46 var txtspecpaths []string 47 for _, p := range specsPaths { 48 txtspecpaths = append(txtspecpaths, pluginPaths(p, name, ".spec")...) 49 txtspecpaths = append(txtspecpaths, pluginPaths(p, name, ".json")...) 50 } 51 52 for _, p := range txtspecpaths { 53 if _, err := os.Stat(p); err == nil { 54 if strings.HasSuffix(p, ".json") { 55 return readPluginJSONInfo(name, p) 56 } 57 return readPluginInfo(name, p) 58 } 59 } 60 return nil, ErrNotFound 61 } 62 63 func readPluginInfo(name, path string) (*Plugin, error) { 64 content, err := ioutil.ReadFile(path) 65 if err != nil { 66 return nil, err 67 } 68 addr := strings.TrimSpace(string(content)) 69 70 u, err := url.Parse(addr) 71 if err != nil { 72 return nil, err 73 } 74 75 if len(u.Scheme) == 0 { 76 return nil, fmt.Errorf("Unknown protocol") 77 } 78 79 return newLocalPlugin(name, addr), nil 80 } 81 82 func readPluginJSONInfo(name, path string) (*Plugin, error) { 83 f, err := os.Open(path) 84 if err != nil { 85 return nil, err 86 } 87 defer f.Close() 88 89 var p Plugin 90 if err := json.NewDecoder(f).Decode(&p); err != nil { 91 return nil, err 92 } 93 p.Name = name 94 if len(p.TLSConfig.CAFile) == 0 { 95 p.TLSConfig.InsecureSkipVerify = true 96 } 97 98 return &p, nil 99 } 100 101 func pluginPaths(base, name, ext string) []string { 102 return []string{ 103 filepath.Join(base, name+ext), 104 filepath.Join(base, name, name+ext), 105 } 106 }