Skip to content

Commit

Permalink
feat(index) add TypeMeda during key generation
Browse files Browse the repository at this point in the history
  • Loading branch information
rainest committed Oct 3, 2023
1 parent 4606c81 commit d0ec5e1
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 20 deletions.
11 changes: 1 addition & 10 deletions internal/controllers/configuration/secret_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,7 @@ func (r *CoreV1SecretReconciler) SetLogger(l logr.Logger) {
// - the secret has label: konghq.com/ca-cert:true
// - or the secret is referred by objects we care (service, ingress, gateway, ...)
func (r *CoreV1SecretReconciler) shouldReconcileSecret(obj client.Object) bool {
// TypeMeta is necessary to generate the correct key for references, but we can't use the original object
// controller-runtime's client provides the same object to both predicates and the admission webhook, and can result
// in a race condition if this uses the original
o := obj.DeepCopyObject()
err := util.PopulateTypeMeta(o)
if err != nil {
r.Log.Error(err, "could not set resource TypeMeta",
"namespace", obj.GetNamespace(), "name", obj.GetName())
}
secret, ok := o.(*corev1.Secret)
secret, ok := obj.(*corev1.Secret)
if !ok {
return false
}
Expand Down
57 changes: 47 additions & 10 deletions internal/controllers/reference/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,21 @@ type ObjectReference struct {
// objectKeyFunc returns a k8s object key in the following format:
// group/version,Kind=kind/namespace/name.
// the combination is unique inside a kubernetes cluster.
func objectKeyFunc(obj client.Object) string {
return obj.GetObjectKind().GroupVersionKind().String() + "/" +
obj.GetNamespace() + "/" + obj.GetName()
func objectKeyFunc(obj client.Object) (string, error) {
// TypeMeta is necessary to generate the correct key for references, but we can't use the original object.
// controller-runtime's client provides the same object to both predicates and the admission webhook, and can result
// in a race condition if this uses the original
o := obj.DeepCopyObject()
metaObj, ok := o.(client.Object)
if !ok {
return "", fmt.Errorf("could not convert %s/%s back to client Object", obj.GetNamespace(), obj.GetName())
}
err := util.PopulateTypeMeta(o)
if err != nil {
return "", fmt.Errorf("could not populate %s/%s metadata: %w", obj.GetNamespace(), obj.GetName(), err)
}
return metaObj.GetObjectKind().GroupVersionKind().String() + "/" +
metaObj.GetNamespace() + "/" + metaObj.GetName(), nil
}

// CacheIndexers implements a reference cache to store reference relationship between k8s objects
Expand Down Expand Up @@ -62,8 +74,14 @@ func ObjectReferenceKeyFunc(obj interface{}) (string, error) {
if !ok {
return "", ErrTypeNotObjectReference
}
referrerKey := objectKeyFunc(ref.Referrer)
referentKey := objectKeyFunc(ref.Referent)
referrerKey, err := objectKeyFunc(ref.Referrer)
if err != nil {
return "", err
}
referentKey, err := objectKeyFunc(ref.Referent)
if err != nil {
return "", err
}

return referrerKey + ":" + referentKey, nil
}
Expand All @@ -76,7 +94,11 @@ func ObjectReferenceIndexerReferrer(obj interface{}) ([]string, error) {
if !ok {
return nil, ErrTypeNotObjectReference
}
return []string{objectKeyFunc(ref.Referrer)}, nil
referrerKey, err := objectKeyFunc(ref.Referrer)
if err != nil {
return []string{}, err
}
return []string{referrerKey}, nil
}

// ObjectReferenceIndexerReferent is the index function to index by the referent,
Expand All @@ -87,7 +109,11 @@ func ObjectReferenceIndexerReferent(obj interface{}) ([]string, error) {
if !ok {
return nil, ErrTypeNotObjectReference
}
return []string{objectKeyFunc(ref.Referent)}, nil
referentKey, err := objectKeyFunc(ref.Referent)
if err != nil {
return []string{}, err
}
return []string{referentKey}, nil
}

// SetObjectReference adds or updates a reference record between referrer and referent in reference cache.
Expand Down Expand Up @@ -127,7 +153,11 @@ func (c CacheIndexers) DeleteObjectReference(referrer client.Object, referent cl
// ObjectReferred returns true if an object is referenced (being the referent)
// in at least one reference record.
func (c CacheIndexers) ObjectReferred(obj client.Object) (bool, error) {
refs, err := c.indexer.ByIndex(IndexNameReferent, objectKeyFunc(obj))
objKey, err := objectKeyFunc(obj)
if err != nil {
return false, err
}
refs, err := c.indexer.ByIndex(IndexNameReferent, objKey)
if err != nil {
return false, err
}
Expand All @@ -138,7 +168,11 @@ func (c CacheIndexers) ObjectReferred(obj client.Object) (bool, error) {
// ListReferencesByReferrer lists all reference records where referrer has the same key
// (GroupVersionKind+NamespacedName, that means the same k8s object).
func (c CacheIndexers) ListReferencesByReferrer(referrer client.Object) ([]*ObjectReference, error) {
refList, err := c.indexer.ByIndex(IndexNameReferrer, objectKeyFunc(referrer))
referrerKey, err := objectKeyFunc(referrer)
if err != nil {
return nil, err
}
refList, err := c.indexer.ByIndex(IndexNameReferrer, referrerKey)
if err != nil {
return nil, err
}
Expand All @@ -157,7 +191,10 @@ func (c CacheIndexers) ListReferencesByReferrer(referrer client.Object) ([]*Obje
// (GroupVersionKind+NamespacedName, that means the same k8s object).
// called when a k8s object deleted in cluster, or when we do not care about it anymore.
func (c CacheIndexers) DeleteReferencesByReferrer(referrer client.Object) error {
key := objectKeyFunc(referrer)
key, err := objectKeyFunc(referrer)
if err != nil {
return err
}
refs, err := c.indexer.ByIndex(IndexNameReferrer, key)
if err != nil {
return err
Expand Down

0 comments on commit d0ec5e1

Please sign in to comment.