Files
steampipe/pkg/filepaths/plugin_path.go
2024-01-23 09:01:51 +00:00

85 lines
2.7 KiB
Go

package filepaths
import (
"fmt"
"log"
"os"
"path/filepath"
"github.com/turbot/steampipe-plugin-sdk/v5/sperr"
"github.com/turbot/steampipe/pkg/constants"
"github.com/turbot/steampipe/pkg/utils"
)
func GetPluginPath(pluginImageRef, pluginAlias string) (string, error) {
// the fully qualified name of the plugin is the relative path of the folder containing the plugin
// calculate absolute folder path
pluginFolder := filepath.Join(EnsurePluginDir(), pluginImageRef)
// if the plugin folder is missing, it is possible the plugin path was truncated to create a schema name
// - so search for a folder which when truncated would match the schema
if _, err := os.Stat(pluginFolder); os.IsNotExist(err) {
log.Printf("[TRACE] plugin path %s not found - searching for folder using hashed name\n", pluginFolder)
if pluginFolder, err = FindPluginFolder(pluginImageRef); err != nil {
return "", err
} else if pluginFolder == "" {
return "", fmt.Errorf("no plugin installed matching %s", pluginAlias)
}
}
// there should be just 1 file with extension pluginExtension (".plugin")
entries, err := os.ReadDir(pluginFolder)
if err != nil {
return "", fmt.Errorf("failed to load plugin %s: %v", pluginImageRef, err)
}
var matches []string
for _, entry := range entries {
if filepath.Ext(entry.Name()) == constants.PluginExtension {
matches = append(matches, entry.Name())
}
}
if len(matches) != 1 {
return "", fmt.Errorf("plugin folder %s should contain a single plugin file. %d plugins were found ", pluginFolder, len(matches))
}
return filepath.Join(pluginFolder, matches[0]), nil
}
// FindPluginFolder searches for a folder which when hashed would match the schema
func FindPluginFolder(remoteSchema string) (string, error) {
pluginDir := EnsurePluginDir()
// first try searching by prefix - trim the schema name
globPattern := filepath.Join(pluginDir, utils.TrimSchemaName(remoteSchema)) + "*"
matches, err := filepath.Glob(globPattern)
if err != nil {
return "", err
}
// there was no match
if len(matches) == 0 {
return "", sperr.WrapWithMessage(os.ErrNotExist, "no plugin installed matching %s", remoteSchema)
}
// we found a match
if len(matches) == 1 {
return matches[0], nil
}
// when there are multiple matches,
// find the first match which has the same hashed name as the schema
for _, match := range matches {
// get the relative path to this match from the plugin folder
folderRelativePath, err := filepath.Rel(pluginDir, match)
if err != nil {
// do not fail on error here
continue
}
hashedName := utils.PluginFQNToSchemaName(folderRelativePath)
if hashedName == remoteSchema {
return filepath.Join(pluginDir, folderRelativePath), nil
}
}
return "", nil
}