github.com/ttys3/engine@v17.12.1-ce-rc2+incompatible/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 "sync" 13 ) 14 15 var ( 16 // ErrNotFound plugin not found 17 ErrNotFound = errors.New("plugin not found") 18 socketsPath = "/run/docker/plugins" 19 ) 20 21 // localRegistry defines a registry that is local (using unix socket). 22 type localRegistry struct{} 23 24 func newLocalRegistry() localRegistry { 25 return localRegistry{} 26 } 27 28 // Scan scans all the plugin paths and returns all the names it found 29 func Scan() ([]string, error) { 30 var names []string 31 if err := filepath.Walk(socketsPath, func(path string, fi os.FileInfo, err error) error { 32 if err != nil { 33 return nil 34 } 35 36 if fi.Mode()&os.ModeSocket != 0 { 37 name := strings.TrimSuffix(fi.Name(), filepath.Ext(fi.Name())) 38 names = append(names, name) 39 } 40 return nil 41 }); err != nil { 42 return nil, err 43 } 44 45 for _, path := range specsPaths { 46 if err := filepath.Walk(path, func(p string, fi os.FileInfo, err error) error { 47 if err != nil || fi.IsDir() { 48 return nil 49 } 50 name := strings.TrimSuffix(fi.Name(), filepath.Ext(fi.Name())) 51 names = append(names, name) 52 return nil 53 }); err != nil { 54 return nil, err 55 } 56 } 57 return names, nil 58 } 59 60 // Plugin returns the plugin registered with the given name (or returns an error). 61 func (l *localRegistry) Plugin(name string) (*Plugin, error) { 62 socketpaths := pluginPaths(socketsPath, name, ".sock") 63 64 for _, p := range socketpaths { 65 if fi, err := os.Stat(p); err == nil && fi.Mode()&os.ModeSocket != 0 { 66 return NewLocalPlugin(name, "unix://"+p), nil 67 } 68 } 69 70 var txtspecpaths []string 71 for _, p := range specsPaths { 72 txtspecpaths = append(txtspecpaths, pluginPaths(p, name, ".spec")...) 73 txtspecpaths = append(txtspecpaths, pluginPaths(p, name, ".json")...) 74 } 75 76 for _, p := range txtspecpaths { 77 if _, err := os.Stat(p); err == nil { 78 if strings.HasSuffix(p, ".json") { 79 return readPluginJSONInfo(name, p) 80 } 81 return readPluginInfo(name, p) 82 } 83 } 84 return nil, ErrNotFound 85 } 86 87 func readPluginInfo(name, path string) (*Plugin, error) { 88 content, err := ioutil.ReadFile(path) 89 if err != nil { 90 return nil, err 91 } 92 addr := strings.TrimSpace(string(content)) 93 94 u, err := url.Parse(addr) 95 if err != nil { 96 return nil, err 97 } 98 99 if len(u.Scheme) == 0 { 100 return nil, fmt.Errorf("Unknown protocol") 101 } 102 103 return NewLocalPlugin(name, addr), nil 104 } 105 106 func readPluginJSONInfo(name, path string) (*Plugin, error) { 107 f, err := os.Open(path) 108 if err != nil { 109 return nil, err 110 } 111 defer f.Close() 112 113 var p Plugin 114 if err := json.NewDecoder(f).Decode(&p); err != nil { 115 return nil, err 116 } 117 p.name = name 118 if p.TLSConfig != nil && len(p.TLSConfig.CAFile) == 0 { 119 p.TLSConfig.InsecureSkipVerify = true 120 } 121 p.activateWait = sync.NewCond(&sync.Mutex{}) 122 123 return &p, nil 124 } 125 126 func pluginPaths(base, name, ext string) []string { 127 return []string{ 128 filepath.Join(base, name+ext), 129 filepath.Join(base, name, name+ext), 130 } 131 }