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  }