mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Merge pull request #95783 from roycaihw/flake/wait-for-webhook-registration
webhook config manager: HasSynced returns true when the manager is synced with existing webhookconfig objects at startup
This commit is contained in:
		@@ -36,6 +36,11 @@ type mutatingWebhookConfigurationManager struct {
 | 
				
			|||||||
	configuration *atomic.Value
 | 
						configuration *atomic.Value
 | 
				
			||||||
	lister        admissionregistrationlisters.MutatingWebhookConfigurationLister
 | 
						lister        admissionregistrationlisters.MutatingWebhookConfigurationLister
 | 
				
			||||||
	hasSynced     func() bool
 | 
						hasSynced     func() bool
 | 
				
			||||||
 | 
						// initialConfigurationSynced stores a boolean value, which 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.Value
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var _ generic.Source = &mutatingWebhookConfigurationManager{}
 | 
					var _ generic.Source = &mutatingWebhookConfigurationManager{}
 | 
				
			||||||
@@ -43,13 +48,15 @@ var _ generic.Source = &mutatingWebhookConfigurationManager{}
 | 
				
			|||||||
func NewMutatingWebhookConfigurationManager(f informers.SharedInformerFactory) generic.Source {
 | 
					func NewMutatingWebhookConfigurationManager(f informers.SharedInformerFactory) generic.Source {
 | 
				
			||||||
	informer := f.Admissionregistration().V1().MutatingWebhookConfigurations()
 | 
						informer := f.Admissionregistration().V1().MutatingWebhookConfigurations()
 | 
				
			||||||
	manager := &mutatingWebhookConfigurationManager{
 | 
						manager := &mutatingWebhookConfigurationManager{
 | 
				
			||||||
		configuration: &atomic.Value{},
 | 
							configuration:              &atomic.Value{},
 | 
				
			||||||
		lister:        informer.Lister(),
 | 
							lister:                     informer.Lister(),
 | 
				
			||||||
		hasSynced:     informer.Informer().HasSynced,
 | 
							hasSynced:                  informer.Informer().HasSynced,
 | 
				
			||||||
 | 
							initialConfigurationSynced: &atomic.Value{},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Start with an empty list
 | 
						// Start with an empty list
 | 
				
			||||||
	manager.configuration.Store([]webhook.WebhookAccessor{})
 | 
						manager.configuration.Store([]webhook.WebhookAccessor{})
 | 
				
			||||||
 | 
						manager.initialConfigurationSynced.Store(false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// On any change, rebuild the config
 | 
						// On any change, rebuild the config
 | 
				
			||||||
	informer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
 | 
						informer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
 | 
				
			||||||
@@ -66,8 +73,27 @@ func (m *mutatingWebhookConfigurationManager) Webhooks() []webhook.WebhookAccess
 | 
				
			|||||||
	return m.configuration.Load().([]webhook.WebhookAccessor)
 | 
						return m.configuration.Load().([]webhook.WebhookAccessor)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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 {
 | 
					func (m *mutatingWebhookConfigurationManager) HasSynced() bool {
 | 
				
			||||||
	return m.hasSynced()
 | 
						if !m.hasSynced() {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if m.initialConfigurationSynced.Load().(bool) {
 | 
				
			||||||
 | 
							// 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
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *mutatingWebhookConfigurationManager) updateConfiguration() {
 | 
					func (m *mutatingWebhookConfigurationManager) updateConfiguration() {
 | 
				
			||||||
@@ -77,6 +103,7 @@ func (m *mutatingWebhookConfigurationManager) updateConfiguration() {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	m.configuration.Store(mergeMutatingWebhookConfigurations(configurations))
 | 
						m.configuration.Store(mergeMutatingWebhookConfigurations(configurations))
 | 
				
			||||||
 | 
						m.initialConfigurationSynced.Store(true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func mergeMutatingWebhookConfigurations(configurations []*v1.MutatingWebhookConfiguration) []webhook.WebhookAccessor {
 | 
					func mergeMutatingWebhookConfigurations(configurations []*v1.MutatingWebhookConfiguration) []webhook.WebhookAccessor {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,6 +36,11 @@ type validatingWebhookConfigurationManager struct {
 | 
				
			|||||||
	configuration *atomic.Value
 | 
						configuration *atomic.Value
 | 
				
			||||||
	lister        admissionregistrationlisters.ValidatingWebhookConfigurationLister
 | 
						lister        admissionregistrationlisters.ValidatingWebhookConfigurationLister
 | 
				
			||||||
	hasSynced     func() bool
 | 
						hasSynced     func() bool
 | 
				
			||||||
 | 
						// initialConfigurationSynced stores a boolean value, which 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.Value
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var _ generic.Source = &validatingWebhookConfigurationManager{}
 | 
					var _ generic.Source = &validatingWebhookConfigurationManager{}
 | 
				
			||||||
@@ -43,13 +48,15 @@ var _ generic.Source = &validatingWebhookConfigurationManager{}
 | 
				
			|||||||
func NewValidatingWebhookConfigurationManager(f informers.SharedInformerFactory) generic.Source {
 | 
					func NewValidatingWebhookConfigurationManager(f informers.SharedInformerFactory) generic.Source {
 | 
				
			||||||
	informer := f.Admissionregistration().V1().ValidatingWebhookConfigurations()
 | 
						informer := f.Admissionregistration().V1().ValidatingWebhookConfigurations()
 | 
				
			||||||
	manager := &validatingWebhookConfigurationManager{
 | 
						manager := &validatingWebhookConfigurationManager{
 | 
				
			||||||
		configuration: &atomic.Value{},
 | 
							configuration:              &atomic.Value{},
 | 
				
			||||||
		lister:        informer.Lister(),
 | 
							lister:                     informer.Lister(),
 | 
				
			||||||
		hasSynced:     informer.Informer().HasSynced,
 | 
							hasSynced:                  informer.Informer().HasSynced,
 | 
				
			||||||
 | 
							initialConfigurationSynced: &atomic.Value{},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Start with an empty list
 | 
						// Start with an empty list
 | 
				
			||||||
	manager.configuration.Store([]webhook.WebhookAccessor{})
 | 
						manager.configuration.Store([]webhook.WebhookAccessor{})
 | 
				
			||||||
 | 
						manager.initialConfigurationSynced.Store(false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// On any change, rebuild the config
 | 
						// On any change, rebuild the config
 | 
				
			||||||
	informer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
 | 
						informer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
 | 
				
			||||||
@@ -66,9 +73,28 @@ func (v *validatingWebhookConfigurationManager) Webhooks() []webhook.WebhookAcce
 | 
				
			|||||||
	return v.configuration.Load().([]webhook.WebhookAccessor)
 | 
						return v.configuration.Load().([]webhook.WebhookAccessor)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HasSynced returns true if the shared informers have synced.
 | 
					// 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 {
 | 
					func (v *validatingWebhookConfigurationManager) HasSynced() bool {
 | 
				
			||||||
	return v.hasSynced()
 | 
						if !v.hasSynced() {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if v.initialConfigurationSynced.Load().(bool) {
 | 
				
			||||||
 | 
							// 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (v *validatingWebhookConfigurationManager) updateConfiguration() {
 | 
					func (v *validatingWebhookConfigurationManager) updateConfiguration() {
 | 
				
			||||||
@@ -78,6 +104,7 @@ func (v *validatingWebhookConfigurationManager) updateConfiguration() {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	v.configuration.Store(mergeValidatingWebhookConfigurations(configurations))
 | 
						v.configuration.Store(mergeValidatingWebhookConfigurations(configurations))
 | 
				
			||||||
 | 
						v.initialConfigurationSynced.Store(true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func mergeValidatingWebhookConfigurations(configurations []*v1.ValidatingWebhookConfiguration) []webhook.WebhookAccessor {
 | 
					func mergeValidatingWebhookConfigurations(configurations []*v1.ValidatingWebhookConfiguration) []webhook.WebhookAccessor {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user