]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blobdiff - vendor/github.com/hashicorp/terraform/plugin/discovery/find.go
vendor: github.com/hashicorp/terraform/...@v0.10.0
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / plugin / discovery / find.go
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/find.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/find.go
new file mode 100644 (file)
index 0000000..f5bc4c1
--- /dev/null
@@ -0,0 +1,168 @@
+package discovery
+
+import (
+       "io/ioutil"
+       "log"
+       "path/filepath"
+       "strings"
+)
+
+// FindPlugins looks in the given directories for files whose filenames
+// suggest that they are plugins of the given kind (e.g. "provider") and
+// returns a PluginMetaSet representing the discovered potential-plugins.
+//
+// Currently this supports two different naming schemes. The current
+// standard naming scheme is a subdirectory called $GOOS-$GOARCH containing
+// files named terraform-$KIND-$NAME-V$VERSION. The legacy naming scheme is
+// files directly in the given directory whose names are like
+// terraform-$KIND-$NAME.
+//
+// Only one plugin will be returned for each unique plugin (name, version)
+// pair, with preference given to files found in earlier directories.
+//
+// This is a convenience wrapper around FindPluginPaths and ResolvePluginsPaths.
+func FindPlugins(kind string, dirs []string) PluginMetaSet {
+       return ResolvePluginPaths(FindPluginPaths(kind, dirs))
+}
+
+// FindPluginPaths looks in the given directories for files whose filenames
+// suggest that they are plugins of the given kind (e.g. "provider").
+//
+// The return value is a list of absolute paths that appear to refer to
+// plugins in the given directories, based only on what can be inferred
+// from the naming scheme. The paths returned are ordered such that files
+// in later dirs appear after files in earlier dirs in the given directory
+// list. Within the same directory plugins are returned in a consistent but
+// undefined order.
+func FindPluginPaths(kind string, dirs []string) []string {
+       // This is just a thin wrapper around findPluginPaths so that we can
+       // use the latter in tests with a fake machineName so we can use our
+       // test fixtures.
+       return findPluginPaths(kind, dirs)
+}
+
+func findPluginPaths(kind string, dirs []string) []string {
+       prefix := "terraform-" + kind + "-"
+
+       ret := make([]string, 0, len(dirs))
+
+       for _, dir := range dirs {
+               items, err := ioutil.ReadDir(dir)
+               if err != nil {
+                       // Ignore missing dirs, non-dirs, etc
+                       continue
+               }
+
+               log.Printf("[DEBUG] checking for %s in %q", kind, dir)
+
+               for _, item := range items {
+                       fullName := item.Name()
+
+                       if !strings.HasPrefix(fullName, prefix) {
+                               log.Printf("[DEBUG] skipping %q, not a %s", fullName, kind)
+                               continue
+                       }
+
+                       // New-style paths must have a version segment in filename
+                       if strings.Contains(strings.ToLower(fullName), "_v") {
+                               absPath, err := filepath.Abs(filepath.Join(dir, fullName))
+                               if err != nil {
+                                       log.Printf("[ERROR] plugin filepath error: %s", err)
+                                       continue
+                               }
+
+                               log.Printf("[DEBUG] found %s %q", kind, fullName)
+                               ret = append(ret, filepath.Clean(absPath))
+                               continue
+                       }
+
+                       // Legacy style with files directly in the base directory
+                       absPath, err := filepath.Abs(filepath.Join(dir, fullName))
+                       if err != nil {
+                               log.Printf("[ERROR] plugin filepath error: %s", err)
+                               continue
+                       }
+
+                       log.Printf("[WARNING] found legacy %s %q", kind, fullName)
+
+                       ret = append(ret, filepath.Clean(absPath))
+               }
+       }
+
+       return ret
+}
+
+// ResolvePluginPaths takes a list of paths to plugin executables (as returned
+// by e.g. FindPluginPaths) and produces a PluginMetaSet describing the
+// referenced plugins.
+//
+// If the same combination of plugin name and version appears multiple times,
+// the earlier reference will be preferred. Several different versions of
+// the same plugin name may be returned, in which case the methods of
+// PluginMetaSet can be used to filter down.
+func ResolvePluginPaths(paths []string) PluginMetaSet {
+       s := make(PluginMetaSet)
+
+       type nameVersion struct {
+               Name    string
+               Version string
+       }
+       found := make(map[nameVersion]struct{})
+
+       for _, path := range paths {
+               baseName := strings.ToLower(filepath.Base(path))
+               if !strings.HasPrefix(baseName, "terraform-") {
+                       // Should never happen with reasonable input
+                       continue
+               }
+
+               baseName = baseName[10:]
+               firstDash := strings.Index(baseName, "-")
+               if firstDash == -1 {
+                       // Should never happen with reasonable input
+                       continue
+               }
+
+               baseName = baseName[firstDash+1:]
+               if baseName == "" {
+                       // Should never happen with reasonable input
+                       continue
+               }
+
+               // Trim the .exe suffix used on Windows before we start wrangling
+               // the remainder of the path.
+               if strings.HasSuffix(baseName, ".exe") {
+                       baseName = baseName[:len(baseName)-4]
+               }
+
+               parts := strings.SplitN(baseName, "_v", 2)
+               name := parts[0]
+               version := VersionZero
+               if len(parts) == 2 {
+                       version = parts[1]
+               }
+
+               // Auto-installed plugins contain an extra name portion representing
+               // the expected plugin version, which we must trim off.
+               if underX := strings.Index(version, "_x"); underX != -1 {
+                       version = version[:underX]
+               }
+
+               if _, ok := found[nameVersion{name, version}]; ok {
+                       // Skip duplicate versions of the same plugin
+                       // (We do this during this step because after this we will be
+                       // dealing with sets and thus lose our ordering with which to
+                       // decide preference.)
+                       continue
+               }
+
+               s.Add(PluginMeta{
+                       Name:    name,
+                       Version: VersionStr(version),
+                       Path:    path,
+               })
+               found[nameVersion{name, version}] = struct{}{}
+       }
+
+       return s
+}