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