mirror of https://github.com/helm/helm
parent
618b14a772
commit
abd4a326f0
@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The Helm Authors.
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package plugin
|
|
||||||
|
|
||||||
// Descriptor describes a plugin to find
|
|
||||||
type Descriptor struct {
|
|
||||||
// Name is the name of the plugin
|
|
||||||
Name string
|
|
||||||
// Type is the type of the plugin (cli, getter, postrenderer)
|
|
||||||
Type string
|
|
||||||
}
|
|
@ -0,0 +1,216 @@
|
|||||||
|
/*
|
||||||
|
Copyright The Helm Authors.
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Descriptor describes a plugin to find
|
||||||
|
type Descriptor struct {
|
||||||
|
// Name is the name of the plugin
|
||||||
|
Name string
|
||||||
|
// Type is the type of the plugin (cli/v1, getter/v1, postrenderer/v1, etc)
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Catalog is an interface for finding plugins
|
||||||
|
type Catalog interface {
|
||||||
|
FindPlugin(Descriptor) (Plugin, error)
|
||||||
|
FindPlugins(Descriptor) ([]Plugin, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStore creates a new, empty plugin store
|
||||||
|
func NewStore() Store {
|
||||||
|
s := Store{}
|
||||||
|
s.plugins.Store(&sync.Map{})
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store is a concurrent access safe store for plugins
|
||||||
|
// Specifically, it is a wrapper around sync.Map for *PluginRaw
|
||||||
|
// It uses atomic.Value to allow for safe replacement of the underlying sync.Map
|
||||||
|
// Providing concurrency safe iteration over all plugins (for filtering), and name-based lookup
|
||||||
|
type Store struct {
|
||||||
|
plugins atomic.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) Store(pr *PluginRaw) {
|
||||||
|
plugins := s.plugins.Load().(*sync.Map)
|
||||||
|
plugins.Store(pr.Metadata.Name, pr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) LoadOrStore(pr *PluginRaw) (*PluginRaw, bool) {
|
||||||
|
plugins := s.plugins.Load().(*sync.Map)
|
||||||
|
actual, loaded := plugins.LoadOrStore(pr.Metadata.Name, pr)
|
||||||
|
return actual.(*PluginRaw), loaded
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) Load(name string) *PluginRaw {
|
||||||
|
plugins := s.plugins.Load().(*sync.Map)
|
||||||
|
v, ok := plugins.Load(name)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return v.(*PluginRaw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) Range(cb func(*PluginRaw)) {
|
||||||
|
plugins := s.plugins.Load().(*sync.Map)
|
||||||
|
plugins.Range(func(_ any, value any) bool {
|
||||||
|
cb(value.(*PluginRaw))
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) Delete(pluginName string) {
|
||||||
|
plugins := s.plugins.Load().(*sync.Map)
|
||||||
|
plugins.Delete(pluginName)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Manager struct {
|
||||||
|
runtimes map[string]Runtime
|
||||||
|
Store Store
|
||||||
|
}
|
||||||
|
|
||||||
|
// func NewManager(baseDirs []string) *Manager {
|
||||||
|
func NewManager() *Manager {
|
||||||
|
pm := Manager{
|
||||||
|
//baseDirs: baseDirs,
|
||||||
|
runtimes: map[string]Runtime{},
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pm
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) RegisterRuntime(runtimeName string, runtime Runtime) {
|
||||||
|
m.runtimes[runtimeName] = runtime
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) RetriveRuntime(runtimeName string) Runtime {
|
||||||
|
return m.runtimes[runtimeName]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Catalog() Catalog {
|
||||||
|
return &PluginManagerCatalog{Manager: m}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) FindPluginsRaw(filterFn filterFunc) []*PluginRaw {
|
||||||
|
results := make([]*PluginRaw, 0, 10)
|
||||||
|
m.Store.Range(func(pluginRaw *PluginRaw) {
|
||||||
|
if filterFn(&pluginRaw.Metadata) {
|
||||||
|
results = append(results, pluginRaw)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) CreatePlugin(pluginRaw *PluginRaw) (Plugin, error) {
|
||||||
|
rt, ok := m.runtimes[pluginRaw.Metadata.Runtime]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("unsupported plugin runtime type: %q", pluginRaw.Metadata.Runtime)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rt.CreatePlugin(pluginRaw.Dir, &pluginRaw.Metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// filterFunc is a function that filters plugins
|
||||||
|
type filterFunc func(m *Metadata) bool
|
||||||
|
|
||||||
|
// makeDescriptorFilter creates a filter function from a descriptor
|
||||||
|
// Additional plugin filter criteria we wish to support can be added here
|
||||||
|
func makeDescriptorFilter(descriptor Descriptor) filterFunc {
|
||||||
|
return func(m *Metadata) bool {
|
||||||
|
// If name is specified, it must match
|
||||||
|
if descriptor.Name != "" && m.Name != descriptor.Name {
|
||||||
|
return false
|
||||||
|
|
||||||
|
}
|
||||||
|
// If type is specified, it must match
|
||||||
|
if descriptor.Type != "" && m.Type != descriptor.Type {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PluginManagerCatalog struct {
|
||||||
|
Manager *Manager
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PluginManagerCatalog) FindPlugin(d Descriptor) (Plugin, error) {
|
||||||
|
filterFn := makeDescriptorFilter(d)
|
||||||
|
|
||||||
|
pluginsRaw := c.Manager.FindPluginsRaw(filterFn)
|
||||||
|
|
||||||
|
if len(pluginsRaw) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if len(pluginsRaw) > 1 {
|
||||||
|
return nil, fmt.Errorf("multiple matching plugins found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Manager.CreatePlugin(pluginsRaw[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PluginManagerCatalog) FindPlugins(d Descriptor) ([]Plugin, error) {
|
||||||
|
filterFn := makeDescriptorFilter(d)
|
||||||
|
|
||||||
|
pluginsRaw := make([]*PluginRaw, 0, 10)
|
||||||
|
c.Manager.Store.Range(func(pluginRaw *PluginRaw) {
|
||||||
|
if filterFn(&pluginRaw.Metadata) {
|
||||||
|
pluginsRaw = append(pluginsRaw, pluginRaw)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
results := make([]Plugin, 0, len(pluginsRaw))
|
||||||
|
errs := []error{}
|
||||||
|
for _, pr := range pluginsRaw {
|
||||||
|
p, err := c.Manager.CreatePlugin(pr)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
results = append(results, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := errors.Join(errs...); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEmptyCatalog returns a Catalog that has no plugins
|
||||||
|
func NewEmptyCatalog() Catalog {
|
||||||
|
return &emptyCatalog{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type emptyCatalog struct{}
|
||||||
|
|
||||||
|
func (*emptyCatalog) FindPlugin(Descriptor) (Plugin, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*emptyCatalog) FindPlugins(Descriptor) ([]Plugin, error) {
|
||||||
|
return []Plugin{}, nil
|
||||||
|
}
|
Loading…
Reference in new issue