karmada/pkg/resourceinterpreter/default/thirdparty/manager.go

106 lines
2.9 KiB
Go

package thirdparty
import (
"bytes"
"io"
"io/fs"
"path/filepath"
"sort"
"strings"
"sync/atomic"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/klog/v2"
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
"github.com/karmada-io/karmada/pkg/resourceinterpreter/customized/declarative/configmanager"
"github.com/karmada-io/karmada/pkg/resourceinterpreter/default/thirdparty/resourcecustomizations"
)
const configurableInterpreterFile = "customizations.yaml"
// configManager collects the thirdparty resource interpreter customization.
type configManager struct {
configuration atomic.Value
}
func (t *configManager) HasSynced() bool {
return true
}
func (t *configManager) LoadConfig(customizations []*configv1alpha1.ResourceInterpreterCustomization) {
sort.Slice(customizations, func(i, j int) bool {
return customizations[i].Name < customizations[j].Name
})
accessors := make(map[schema.GroupVersionKind]configmanager.CustomAccessor)
for _, config := range customizations {
key := schema.FromAPIVersionAndKind(config.Spec.Target.APIVersion, config.Spec.Target.Kind)
var ac configmanager.CustomAccessor
var ok bool
if ac, ok = accessors[key]; !ok {
ac = configmanager.NewResourceCustomAccessor()
}
ac.Merge(config.Spec.Customizations)
accessors[key] = ac
}
t.configuration.Store(accessors)
}
// CustomAccessors returns all cached configurations.
func (t *configManager) CustomAccessors() map[schema.GroupVersionKind]configmanager.CustomAccessor {
return t.configuration.Load().(map[schema.GroupVersionKind]configmanager.CustomAccessor)
}
// NewThirdPartyConfigManager load third party resource in the cache.
func NewThirdPartyConfigManager() configmanager.ConfigManager {
manager := &configManager{}
manager.configuration.Store(make(map[schema.GroupVersionKind]configmanager.CustomAccessor))
manager.loadThirdPartyConfig()
return manager
}
func (t *configManager) loadThirdPartyConfig() {
var configs []*configv1alpha1.ResourceInterpreterCustomization
if err := fs.WalkDir(resourcecustomizations.Embedded, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
// cannot happen
return err
}
if d.IsDir() {
return nil
}
if strings.Contains(d.Name(), "testdata") {
return nil
}
if filepath.Base(d.Name()) != configurableInterpreterFile {
return nil
}
data, err := fs.ReadFile(resourcecustomizations.Embedded, path)
if err != nil {
// cannot happen
return err
}
decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(data), 4096)
for {
config := &configv1alpha1.ResourceInterpreterCustomization{}
err = decoder.Decode(config)
if err != nil {
break
}
configs = append(configs, config)
}
if err != io.EOF {
return err
}
return nil
}); err != nil {
klog.Warning(err, "failed to load third party resource")
return
}
t.LoadConfig(configs)
}