| /* | |
| Copyright 2019 The Kubernetes 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 runtime | |
| import ( | |
| "context" | |
| "fmt" | |
| "k8s.io/apimachinery/pkg/runtime" | |
| "k8s.io/apimachinery/pkg/util/json" | |
| "k8s.io/kubernetes/pkg/scheduler/framework" | |
| plfeature "k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature" | |
| "sigs.k8s.io/yaml" | |
| ) | |
| // PluginFactory is a function that builds a plugin. | |
| type PluginFactory = func(ctx context.Context, configuration runtime.Object, f framework.Handle) (framework.Plugin, error) | |
| // PluginFactoryWithFts is a function that builds a plugin with certain feature gates. | |
| type PluginFactoryWithFts func(context.Context, runtime.Object, framework.Handle, plfeature.Features) (framework.Plugin, error) | |
| // FactoryAdapter can be used to inject feature gates for a plugin that needs | |
| // them when the caller expects the older PluginFactory method. | |
| func FactoryAdapter(fts plfeature.Features, withFts PluginFactoryWithFts) PluginFactory { | |
| return func(ctx context.Context, plArgs runtime.Object, fh framework.Handle) (framework.Plugin, error) { | |
| return withFts(ctx, plArgs, fh, fts) | |
| } | |
| } | |
| // DecodeInto decodes configuration whose type is *runtime.Unknown to the interface into. | |
| func DecodeInto(obj runtime.Object, into interface{}) error { | |
| if obj == nil { | |
| return nil | |
| } | |
| configuration, ok := obj.(*runtime.Unknown) | |
| if !ok { | |
| return fmt.Errorf("want args of type runtime.Unknown, got %T", obj) | |
| } | |
| if configuration.Raw == nil { | |
| return nil | |
| } | |
| switch configuration.ContentType { | |
| // If ContentType is empty, it means ContentTypeJSON by default. | |
| case runtime.ContentTypeJSON, "": | |
| return json.Unmarshal(configuration.Raw, into) | |
| case runtime.ContentTypeYAML: | |
| return yaml.Unmarshal(configuration.Raw, into) | |
| default: | |
| return fmt.Errorf("not supported content type %s", configuration.ContentType) | |
| } | |
| } | |
| // Registry is a collection of all available plugins. The framework uses a | |
| // registry to enable and initialize configured plugins. | |
| // All plugins must be in the registry before initializing the framework. | |
| type Registry map[string]PluginFactory | |
| // Register adds a new plugin to the registry. If a plugin with the same name | |
| // exists, it returns an error. | |
| func (r Registry) Register(name string, factory PluginFactory) error { | |
| if _, ok := r[name]; ok { | |
| return fmt.Errorf("a plugin named %v already exists", name) | |
| } | |
| r[name] = factory | |
| return nil | |
| } | |
| // Unregister removes an existing plugin from the registry. If no plugin with | |
| // the provided name exists, it returns an error. | |
| func (r Registry) Unregister(name string) error { | |
| if _, ok := r[name]; !ok { | |
| return fmt.Errorf("no plugin named %v exists", name) | |
| } | |
| delete(r, name) | |
| return nil | |
| } | |
| // Merge merges the provided registry to the current one. | |
| func (r Registry) Merge(in Registry) error { | |
| for name, factory := range in { | |
| if err := r.Register(name, factory); err != nil { | |
| return err | |
| } | |
| } | |
| return nil | |
| } |