feat: kubesphere 4.0 (#6115)
* feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> * feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> --------- Signed-off-by: ci-bot <ci-bot@kubesphere.io> Co-authored-by: ks-ci-bot <ks-ci-bot@example.com> Co-authored-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
committed by
GitHub
parent
b5015ec7b9
commit
447a51f08b
132
vendor/k8s.io/apiserver/pkg/admission/configuration/mutating_webhook_manager.go
generated
vendored
132
vendor/k8s.io/apiserver/pkg/admission/configuration/mutating_webhook_manager.go
generated
vendored
@@ -19,9 +19,9 @@ package configuration
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync/atomic"
|
||||
"sync"
|
||||
|
||||
"k8s.io/api/admissionregistration/v1"
|
||||
v1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/webhook"
|
||||
@@ -29,18 +29,23 @@ import (
|
||||
"k8s.io/client-go/informers"
|
||||
admissionregistrationlisters "k8s.io/client-go/listers/admissionregistration/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/tools/cache/synctrack"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// Type for test injection.
|
||||
type mutatingWebhookAccessorCreator func(uid string, configurationName string, h *v1.MutatingWebhook) webhook.WebhookAccessor
|
||||
|
||||
// mutatingWebhookConfigurationManager collects the mutating webhook objects so that they can be called.
|
||||
type mutatingWebhookConfigurationManager struct {
|
||||
configuration *atomic.Value
|
||||
lister admissionregistrationlisters.MutatingWebhookConfigurationLister
|
||||
hasSynced func() bool
|
||||
// initialConfigurationSynced tracks if
|
||||
// the existing webhook configs have been synced (honored) by the
|
||||
// manager at startup-- the informer has synced and either has no items
|
||||
// or has finished executing updateConfiguration() once.
|
||||
initialConfigurationSynced *atomic.Bool
|
||||
lister admissionregistrationlisters.MutatingWebhookConfigurationLister
|
||||
hasSynced func() bool
|
||||
lazy synctrack.Lazy[[]webhook.WebhookAccessor]
|
||||
configurationsCache sync.Map
|
||||
// createMutatingWebhookAccessor is used to instantiate webhook accessors.
|
||||
// This function is defined as field instead of a struct method to allow injection
|
||||
// during tests
|
||||
createMutatingWebhookAccessor mutatingWebhookAccessorCreator
|
||||
}
|
||||
|
||||
var _ generic.Source = &mutatingWebhookConfigurationManager{}
|
||||
@@ -48,80 +53,99 @@ var _ generic.Source = &mutatingWebhookConfigurationManager{}
|
||||
func NewMutatingWebhookConfigurationManager(f informers.SharedInformerFactory) generic.Source {
|
||||
informer := f.Admissionregistration().V1().MutatingWebhookConfigurations()
|
||||
manager := &mutatingWebhookConfigurationManager{
|
||||
configuration: &atomic.Value{},
|
||||
lister: informer.Lister(),
|
||||
hasSynced: informer.Informer().HasSynced,
|
||||
initialConfigurationSynced: &atomic.Bool{},
|
||||
lister: informer.Lister(),
|
||||
createMutatingWebhookAccessor: webhook.NewMutatingWebhookAccessor,
|
||||
}
|
||||
manager.lazy.Evaluate = manager.getConfiguration
|
||||
|
||||
// Start with an empty list
|
||||
manager.configuration.Store([]webhook.WebhookAccessor{})
|
||||
manager.initialConfigurationSynced.Store(false)
|
||||
|
||||
// On any change, rebuild the config
|
||||
informer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(_ interface{}) { manager.updateConfiguration() },
|
||||
UpdateFunc: func(_, _ interface{}) { manager.updateConfiguration() },
|
||||
DeleteFunc: func(_ interface{}) { manager.updateConfiguration() },
|
||||
handle, _ := informer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(_ interface{}) { manager.lazy.Notify() },
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
obj := new.(*v1.MutatingWebhookConfiguration)
|
||||
manager.configurationsCache.Delete(obj.GetName())
|
||||
manager.lazy.Notify()
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
vwc, ok := obj.(*v1.MutatingWebhookConfiguration)
|
||||
if !ok {
|
||||
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
|
||||
if !ok {
|
||||
klog.V(2).Infof("Couldn't get object from tombstone %#v", obj)
|
||||
return
|
||||
}
|
||||
vwc, ok = tombstone.Obj.(*v1.MutatingWebhookConfiguration)
|
||||
if !ok {
|
||||
klog.V(2).Infof("Tombstone contained object that is not expected %#v", obj)
|
||||
return
|
||||
}
|
||||
}
|
||||
manager.configurationsCache.Delete(vwc.Name)
|
||||
manager.lazy.Notify()
|
||||
},
|
||||
})
|
||||
manager.hasSynced = handle.HasSynced
|
||||
|
||||
return manager
|
||||
}
|
||||
|
||||
// Webhooks returns the merged MutatingWebhookConfiguration.
|
||||
func (m *mutatingWebhookConfigurationManager) Webhooks() []webhook.WebhookAccessor {
|
||||
return m.configuration.Load().([]webhook.WebhookAccessor)
|
||||
out, err := m.lazy.Get()
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("error getting webhook configuration: %v", err))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// HasSynced returns true when the manager is synced with existing webhookconfig
|
||||
// objects at startup-- which means the informer is synced and either has no items
|
||||
// or updateConfiguration() has completed.
|
||||
func (m *mutatingWebhookConfigurationManager) HasSynced() bool {
|
||||
if !m.hasSynced() {
|
||||
return false
|
||||
}
|
||||
if m.initialConfigurationSynced.Load() {
|
||||
// the informer has synced and configuration has been updated
|
||||
return true
|
||||
}
|
||||
if configurations, err := m.lister.List(labels.Everything()); err == nil && len(configurations) == 0 {
|
||||
// the empty list we initially stored is valid to use.
|
||||
// Setting initialConfigurationSynced to true, so subsequent checks
|
||||
// would be able to take the fast path on the atomic boolean in a
|
||||
// cluster without any admission webhooks configured.
|
||||
m.initialConfigurationSynced.Store(true)
|
||||
// the informer has synced and we don't have any items
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
// HasSynced returns true if the initial set of mutating webhook configurations
|
||||
// has been loaded.
|
||||
func (m *mutatingWebhookConfigurationManager) HasSynced() bool { return m.hasSynced() }
|
||||
|
||||
func (m *mutatingWebhookConfigurationManager) updateConfiguration() {
|
||||
func (m *mutatingWebhookConfigurationManager) getConfiguration() ([]webhook.WebhookAccessor, error) {
|
||||
configurations, err := m.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("error updating configuration: %v", err))
|
||||
return
|
||||
return []webhook.WebhookAccessor{}, err
|
||||
}
|
||||
m.configuration.Store(mergeMutatingWebhookConfigurations(configurations))
|
||||
m.initialConfigurationSynced.Store(true)
|
||||
return m.getMutatingWebhookConfigurations(configurations), nil
|
||||
}
|
||||
|
||||
func mergeMutatingWebhookConfigurations(configurations []*v1.MutatingWebhookConfiguration) []webhook.WebhookAccessor {
|
||||
// getMutatingWebhookConfigurations returns the webhook accessors for a given list of
|
||||
// mutating webhook configurations.
|
||||
//
|
||||
// This function will, first, try to load the webhook accessors from the cache and avoid
|
||||
// recreating them, which can be expessive (requiring CEL expression recompilation).
|
||||
func (m *mutatingWebhookConfigurationManager) getMutatingWebhookConfigurations(configurations []*v1.MutatingWebhookConfiguration) []webhook.WebhookAccessor {
|
||||
// The internal order of webhooks for each configuration is provided by the user
|
||||
// but configurations themselves can be in any order. As we are going to run these
|
||||
// webhooks in serial, they are sorted here to have a deterministic order.
|
||||
sort.SliceStable(configurations, MutatingWebhookConfigurationSorter(configurations).ByName)
|
||||
accessors := []webhook.WebhookAccessor{}
|
||||
size := 0
|
||||
for _, cfg := range configurations {
|
||||
size += len(cfg.Webhooks)
|
||||
}
|
||||
accessors := make([]webhook.WebhookAccessor, 0, size)
|
||||
|
||||
for _, c := range configurations {
|
||||
cachedConfigurationAccessors, ok := m.configurationsCache.Load(c.Name)
|
||||
if ok {
|
||||
// Pick an already cached webhookAccessor
|
||||
accessors = append(accessors, cachedConfigurationAccessors.([]webhook.WebhookAccessor)...)
|
||||
continue
|
||||
}
|
||||
|
||||
// webhook names are not validated for uniqueness, so we check for duplicates and
|
||||
// add a int suffix to distinguish between them
|
||||
names := map[string]int{}
|
||||
configurationAccessors := make([]webhook.WebhookAccessor, 0, len(c.Webhooks))
|
||||
for i := range c.Webhooks {
|
||||
n := c.Webhooks[i].Name
|
||||
uid := fmt.Sprintf("%s/%s/%d", c.Name, n, names[n])
|
||||
names[n]++
|
||||
accessors = append(accessors, webhook.NewMutatingWebhookAccessor(uid, c.Name, &c.Webhooks[i]))
|
||||
configurationAccessor := m.createMutatingWebhookAccessor(uid, c.Name, &c.Webhooks[i])
|
||||
configurationAccessors = append(configurationAccessors, configurationAccessor)
|
||||
}
|
||||
accessors = append(accessors, configurationAccessors...)
|
||||
m.configurationsCache.Store(c.Name, configurationAccessors)
|
||||
}
|
||||
return accessors
|
||||
}
|
||||
|
||||
134
vendor/k8s.io/apiserver/pkg/admission/configuration/validating_webhook_manager.go
generated
vendored
134
vendor/k8s.io/apiserver/pkg/admission/configuration/validating_webhook_manager.go
generated
vendored
@@ -19,9 +19,9 @@ package configuration
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync/atomic"
|
||||
"sync"
|
||||
|
||||
"k8s.io/api/admissionregistration/v1"
|
||||
v1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/webhook"
|
||||
@@ -29,18 +29,23 @@ import (
|
||||
"k8s.io/client-go/informers"
|
||||
admissionregistrationlisters "k8s.io/client-go/listers/admissionregistration/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/tools/cache/synctrack"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// Type for test injection.
|
||||
type validatingWebhookAccessorCreator func(uid string, configurationName string, h *v1.ValidatingWebhook) webhook.WebhookAccessor
|
||||
|
||||
// validatingWebhookConfigurationManager collects the validating webhook objects so that they can be called.
|
||||
type validatingWebhookConfigurationManager struct {
|
||||
configuration *atomic.Value
|
||||
lister admissionregistrationlisters.ValidatingWebhookConfigurationLister
|
||||
hasSynced func() bool
|
||||
// initialConfigurationSynced tracks if
|
||||
// the existing webhook configs have been synced (honored) by the
|
||||
// manager at startup-- the informer has synced and either has no items
|
||||
// or has finished executing updateConfiguration() once.
|
||||
initialConfigurationSynced *atomic.Bool
|
||||
lister admissionregistrationlisters.ValidatingWebhookConfigurationLister
|
||||
hasSynced func() bool
|
||||
lazy synctrack.Lazy[[]webhook.WebhookAccessor]
|
||||
configurationsCache sync.Map
|
||||
// createValidatingWebhookAccessor is used to instantiate webhook accessors.
|
||||
// This function is defined as field instead of a struct method to allow injection
|
||||
// during tests
|
||||
createValidatingWebhookAccessor validatingWebhookAccessorCreator
|
||||
}
|
||||
|
||||
var _ generic.Source = &validatingWebhookConfigurationManager{}
|
||||
@@ -48,79 +53,98 @@ var _ generic.Source = &validatingWebhookConfigurationManager{}
|
||||
func NewValidatingWebhookConfigurationManager(f informers.SharedInformerFactory) generic.Source {
|
||||
informer := f.Admissionregistration().V1().ValidatingWebhookConfigurations()
|
||||
manager := &validatingWebhookConfigurationManager{
|
||||
configuration: &atomic.Value{},
|
||||
lister: informer.Lister(),
|
||||
hasSynced: informer.Informer().HasSynced,
|
||||
initialConfigurationSynced: &atomic.Bool{},
|
||||
lister: informer.Lister(),
|
||||
createValidatingWebhookAccessor: webhook.NewValidatingWebhookAccessor,
|
||||
}
|
||||
manager.lazy.Evaluate = manager.getConfiguration
|
||||
|
||||
// Start with an empty list
|
||||
manager.configuration.Store([]webhook.WebhookAccessor{})
|
||||
manager.initialConfigurationSynced.Store(false)
|
||||
|
||||
// On any change, rebuild the config
|
||||
informer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(_ interface{}) { manager.updateConfiguration() },
|
||||
UpdateFunc: func(_, _ interface{}) { manager.updateConfiguration() },
|
||||
DeleteFunc: func(_ interface{}) { manager.updateConfiguration() },
|
||||
handle, _ := informer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(_ interface{}) { manager.lazy.Notify() },
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
obj := new.(*v1.ValidatingWebhookConfiguration)
|
||||
manager.configurationsCache.Delete(obj.GetName())
|
||||
manager.lazy.Notify()
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
vwc, ok := obj.(*v1.ValidatingWebhookConfiguration)
|
||||
if !ok {
|
||||
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
|
||||
if !ok {
|
||||
klog.V(2).Infof("Couldn't get object from tombstone %#v", obj)
|
||||
return
|
||||
}
|
||||
vwc, ok = tombstone.Obj.(*v1.ValidatingWebhookConfiguration)
|
||||
if !ok {
|
||||
klog.V(2).Infof("Tombstone contained object that is not expected %#v", obj)
|
||||
return
|
||||
}
|
||||
}
|
||||
manager.configurationsCache.Delete(vwc.Name)
|
||||
manager.lazy.Notify()
|
||||
},
|
||||
})
|
||||
manager.hasSynced = handle.HasSynced
|
||||
|
||||
return manager
|
||||
}
|
||||
|
||||
// Webhooks returns the merged ValidatingWebhookConfiguration.
|
||||
func (v *validatingWebhookConfigurationManager) Webhooks() []webhook.WebhookAccessor {
|
||||
return v.configuration.Load().([]webhook.WebhookAccessor)
|
||||
out, err := v.lazy.Get()
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("error getting webhook configuration: %v", err))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// HasSynced returns true when the manager is synced with existing webhookconfig
|
||||
// objects at startup-- which means the informer is synced and either has no items
|
||||
// or updateConfiguration() has completed.
|
||||
func (v *validatingWebhookConfigurationManager) HasSynced() bool {
|
||||
if !v.hasSynced() {
|
||||
return false
|
||||
}
|
||||
if v.initialConfigurationSynced.Load() {
|
||||
// the informer has synced and configuration has been updated
|
||||
return true
|
||||
}
|
||||
if configurations, err := v.lister.List(labels.Everything()); err == nil && len(configurations) == 0 {
|
||||
// the empty list we initially stored is valid to use.
|
||||
// Setting initialConfigurationSynced to true, so subsequent checks
|
||||
// would be able to take the fast path on the atomic boolean in a
|
||||
// cluster without any admission webhooks configured.
|
||||
v.initialConfigurationSynced.Store(true)
|
||||
// the informer has synced and we don't have any items
|
||||
return true
|
||||
}
|
||||
return false
|
||||
// HasSynced returns true if the initial set of validating webhook configurations
|
||||
// has been loaded.
|
||||
func (v *validatingWebhookConfigurationManager) HasSynced() bool { return v.hasSynced() }
|
||||
|
||||
}
|
||||
|
||||
func (v *validatingWebhookConfigurationManager) updateConfiguration() {
|
||||
func (v *validatingWebhookConfigurationManager) getConfiguration() ([]webhook.WebhookAccessor, error) {
|
||||
configurations, err := v.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("error updating configuration: %v", err))
|
||||
return
|
||||
return []webhook.WebhookAccessor{}, err
|
||||
}
|
||||
v.configuration.Store(mergeValidatingWebhookConfigurations(configurations))
|
||||
v.initialConfigurationSynced.Store(true)
|
||||
return v.getValidatingWebhookConfigurations(configurations), nil
|
||||
}
|
||||
|
||||
func mergeValidatingWebhookConfigurations(configurations []*v1.ValidatingWebhookConfiguration) []webhook.WebhookAccessor {
|
||||
// getMutatingWebhookConfigurations returns the webhook accessors for a given list of
|
||||
// mutating webhook configurations.
|
||||
//
|
||||
// This function will, first, try to load the webhook accessors from the cache and avoid
|
||||
// recreating them, which can be expessive (requiring CEL expression recompilation).
|
||||
func (v *validatingWebhookConfigurationManager) getValidatingWebhookConfigurations(configurations []*v1.ValidatingWebhookConfiguration) []webhook.WebhookAccessor {
|
||||
sort.SliceStable(configurations, ValidatingWebhookConfigurationSorter(configurations).ByName)
|
||||
accessors := []webhook.WebhookAccessor{}
|
||||
size := 0
|
||||
for _, cfg := range configurations {
|
||||
size += len(cfg.Webhooks)
|
||||
}
|
||||
accessors := make([]webhook.WebhookAccessor, 0, size)
|
||||
|
||||
for _, c := range configurations {
|
||||
cachedConfigurationAccessors, ok := v.configurationsCache.Load(c.Name)
|
||||
if ok {
|
||||
// Pick an already cached webhookAccessor
|
||||
accessors = append(accessors, cachedConfigurationAccessors.([]webhook.WebhookAccessor)...)
|
||||
continue
|
||||
}
|
||||
|
||||
// webhook names are not validated for uniqueness, so we check for duplicates and
|
||||
// add a int suffix to distinguish between them
|
||||
names := map[string]int{}
|
||||
configurationAccessors := make([]webhook.WebhookAccessor, 0, len(c.Webhooks))
|
||||
for i := range c.Webhooks {
|
||||
n := c.Webhooks[i].Name
|
||||
uid := fmt.Sprintf("%s/%s/%d", c.Name, n, names[n])
|
||||
names[n]++
|
||||
accessors = append(accessors, webhook.NewValidatingWebhookAccessor(uid, c.Name, &c.Webhooks[i]))
|
||||
configurationAccessor := v.createValidatingWebhookAccessor(uid, c.Name, &c.Webhooks[i])
|
||||
configurationAccessors = append(configurationAccessors, configurationAccessor)
|
||||
}
|
||||
accessors = append(accessors, configurationAccessors...)
|
||||
v.configurationsCache.Store(c.Name, configurationAccessors)
|
||||
}
|
||||
|
||||
return accessors
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user