mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-16 01:44:03 +03:00
489835eb36
- modified the `dry-run` flag of metadata apply command. - added new flag `o` which takes "json" or "yaml" as parameters for metadata apply command. - added new flag `o` which takes "json" or "yaml" as parameters for metadata export command. It outputs the metadata from server to stdout in form of json or yaml and won't change the project's metadata. - added deprecation warnings for `--from-file` flag - added info message for describing change of behavior of `--dry-run` flag - v3 metadata objects like `rest_endpoints` was also added to list of metadata objects in config v2 (fix) - the order in which metadata objects are appended to metadata objects list matter when using `--dry-run` flag, refactored this order to match server metadata. - `metadata apply` command can now accept json/yaml metadata from io pipe - config v3 `metadata apply` didn't show any information to user when applied metadata is inconsistent, this is addressed. - removed `github.com/ghodss/yaml` dependency from repo - version metadata object was added twice during intialization (fix) Co-authored-by: Aravind K P <8335904+scriptonist@users.noreply.github.com> GitOrigin-RevId: 2316f519eb40645efd86ffee2a85d3c90543ec17
138 lines
3.5 KiB
Go
138 lines
3.5 KiB
Go
package plugins
|
|
|
|
/*
|
|
some of the code here is borrowed from the krew codebse (kubernetes)
|
|
and the copyright belongs to the respective authors.
|
|
|
|
source: https://github.com/kubernetes-sigs/krew/tree/master/internal
|
|
*/
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/goccy/go-yaml"
|
|
"github.com/hasura/graphql-engine/cli/plugins/paths"
|
|
"github.com/pkg/errors"
|
|
"github.com/spf13/afero"
|
|
)
|
|
|
|
func (c *Config) findPluginManifestFiles(indexDir string) ([]string, error) {
|
|
c.Logger.Debugf("finding plugin manifest files in directory %v", indexDir)
|
|
var out []string
|
|
fs := afero.Afero{
|
|
Fs: afero.NewOsFs(),
|
|
}
|
|
fs.Walk(indexDir, func(path string, info os.FileInfo, err error) error {
|
|
if info == nil {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
if info.Mode().IsRegular() && filepath.Ext(info.Name()) == paths.ManifestExtension {
|
|
out = append(out, path)
|
|
}
|
|
return nil
|
|
})
|
|
|
|
return out, nil
|
|
}
|
|
|
|
// LoadPluginListFromFS will parse and retrieve all plugin files.
|
|
func (c *Config) LoadPluginListFromFS(indexDir string) (Plugins, error) {
|
|
indexDir, err := filepath.EvalSymlinks(indexDir)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
files, err := c.findPluginManifestFiles(indexDir)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to scan plugins in index directory")
|
|
}
|
|
|
|
return c.LoadPlugins(files), nil
|
|
}
|
|
|
|
// LoadPluginByName loads a plugins index file by its name. When plugin
|
|
// file not found, it returns an error that can be checked with os.IsNotExist.
|
|
func (c *Config) LoadPluginByName(pluginName string) (*PluginVersions, error) {
|
|
c.Logger.Debugf("loading plugin %s", pluginName)
|
|
if !IsSafePluginName(pluginName) {
|
|
return nil, errors.Errorf("plugin name %q not allowed", pluginName)
|
|
}
|
|
|
|
files, err := c.findPluginManifestFiles(c.Paths.IndexPluginsPath())
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to scan plugins in index directory")
|
|
}
|
|
|
|
ps := c.LoadPlugins(files, pluginName)
|
|
if _, ok := ps[pluginName]; !ok {
|
|
return nil, os.ErrNotExist
|
|
}
|
|
|
|
return ps[pluginName], nil
|
|
}
|
|
|
|
func (c *Config) LoadPlugins(files []string, pluginName ...string) Plugins {
|
|
c.Logger.Debugf("loading plugins")
|
|
ps := Plugins{}
|
|
for _, file := range files {
|
|
p, err := c.ReadPluginFromFile(file)
|
|
if err != nil {
|
|
c.Logger.Debugf("failed to read or parse plugin manifest: %v", err)
|
|
continue
|
|
}
|
|
if p.ParsedVersion == nil {
|
|
c.Logger.Debugf("version of plugin %s cannot be nil", p.Name)
|
|
continue
|
|
}
|
|
if len(pluginName) != 0 {
|
|
var isFound bool
|
|
for _, name := range pluginName {
|
|
if name == p.Name {
|
|
isFound = true
|
|
break
|
|
}
|
|
}
|
|
if !isFound {
|
|
continue
|
|
}
|
|
}
|
|
if _, ok := ps[p.Name]; !ok {
|
|
ps[p.Name] = NewPluginVersions()
|
|
}
|
|
err = ps[p.Name].Append(p)
|
|
if err != nil {
|
|
c.Logger.Debugf("failed to append version %s for plugin %s: %v", p.Version, p.Name, err)
|
|
continue
|
|
}
|
|
}
|
|
return ps
|
|
}
|
|
|
|
// ReadPluginFromFile loads a file from the FS. When plugin file not found, it
|
|
// returns an error that can be checked with os.IsNotExist.
|
|
func (c *Config) ReadPluginFromFile(path string) (Plugin, error) {
|
|
f, err := os.Open(path)
|
|
if os.IsNotExist(err) {
|
|
return Plugin{}, err
|
|
} else if err != nil {
|
|
return Plugin{}, errors.Wrap(err, "failed to open index file")
|
|
}
|
|
defer f.Close()
|
|
var plugin Plugin
|
|
b, err := ioutil.ReadAll(f)
|
|
if err != nil {
|
|
return plugin, err
|
|
}
|
|
err = yaml.Unmarshal(b, &plugin)
|
|
if err != nil {
|
|
return plugin, errors.Wrap(err, "failed to decode plugin manifest")
|
|
}
|
|
plugin.ParseVersion()
|
|
return plugin, errors.Wrap(plugin.ValidatePlugin(plugin.Name), "plugin manifest validation error")
|
|
}
|