Repository: kubernetes/kubernetes
File: pkg/controller/history/controller_history.go (Go)

Code before:
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/util/retry"
)

// ControllerRevisionHashLabel is the label used to indicate the hash value of a ControllerRevision's Data.
const ControllerRevisionHashLabel = "controller.kubernetes.io/hash"

// ControllerRevisionControllerIndex is the index name for the ControllerRevision controller index.
const ControllerRevisionControllerIndex = "controllerRevisionController"

// ControllerRevisionControllerIndexKey returns the index key to locate ControllerRevisions with the specified controller ownerReference.
func ControllerRevisionControllerIndexKey(namespace string, ownerReference *metav1.OwnerReference) string {
	if ownerReference == nil {
		return namespace
	}
	return namespace + "/" + ownerReference.Kind + "/" + ownerReference.Name + "/" + string(ownerReference.UID)
}

// AddControllerRevisionControllerIndexer adds an indexer for ControllerRevision's controllerRef.UID to the given Informer.
// This indexer is used to efficiently look up ControllerRevisions by their ControllerRef.UID
func AddControllerRevisionControllerIndexer(informer cache.SharedIndexInformer) error {
	if _, exists := informer.GetIndexer().GetIndexers()[ControllerRevisionControllerIndex]; exists {
		// indexer already exists, do nothing
		return nil
	}
	return informer.AddIndexers(cache.Indexers{
		ControllerRevisionControllerIndex: func(obj interface{}) ([]string, error) {
			cr, ok := obj.(*apps.ControllerRevision)
			if !ok {
				return nil, nil
			}
			// Get the ControllerRef of the ControllerRevision to check if it's managed by a controller.
			// Index with a non-nil controller (indicating an owned revision) or a nil controller (indicating an orphan revision).
			return []string{ControllerRevisionControllerIndexKey(cr.Namespace, metav1.GetControllerOf(cr))}, nil
		},
	})
}

// ControllerRevisionName returns the Name for a ControllerRevision in the form prefix-hash. If the length
// of prefix is greater than 223 bytes, it is truncated to allow for a name that is no larger than 253 bytes.
func ControllerRevisionName(prefix string, hash string) string {
	if len(prefix) > 223 {
		prefix = prefix[:223]
	}

	return fmt.Sprintf("%s-%s", prefix, hash)
}

// NewControllerRevision returns a ControllerRevision with a ControllerRef pointing to parent and indicating that
// parent is of parentKind. The ControllerRevision has labels matching template labels, contains Data equal to data, and
// has a Revision equal to revision. The collisionCount is used when creating the name of the ControllerRevision

Review comment (suggestion):
if controllers are initializing concurrently, there could be a race here... if we get an error adding, we may want to check if it exists again and ignore the error if so

Code after:
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/util/retry"
)

// ControllerRevisionHashLabel is the label used to indicate the hash value of a ControllerRevision's Data.
const ControllerRevisionHashLabel = "controller.kubernetes.io/hash"

// ControllerRevisionControllerIndex is the index name for the ControllerRevision controller index.
const ControllerRevisionControllerIndex = "controllerRevisionController"

// ControllerRevisionControllerIndexKey returns the index key to locate ControllerRevisions with the specified controller ownerReference.
// If the ownerReference is specified, the key is "namespace/kind/ownerReference.Name/ownerReference.UID".
// If the ownerReference is nil, the key is just "namespace" for orphan revisions.
func ControllerRevisionControllerIndexKey(namespace string, ownerReference *metav1.OwnerReference) string {
	if ownerReference == nil {
		return namespace
	}
	return namespace + "/" + ownerReference.Kind + "/" + ownerReference.Name + "/" + string(ownerReference.UID)
}

// AddControllerRevisionControllerIndexer adds an indexer for ControllerRevision's controllerRef.UID to the given Informer.
// This indexer is used to efficiently look up ControllerRevisions by their ControllerRef.UID
func AddControllerRevisionControllerIndexer(informer cache.SharedIndexInformer) error {
	if _, exists := informer.GetIndexer().GetIndexers()[ControllerRevisionControllerIndex]; exists {
		// indexer already exists, do nothing
		return nil
	}

	err := informer.AddIndexers(cache.Indexers{
		ControllerRevisionControllerIndex: func(obj interface{}) ([]string, error) {
			cr, ok := obj.(*apps.ControllerRevision)
			if !ok {
				return nil, nil
			}
			// Get the ControllerRef of the ControllerRevision to check if it's managed by a controller.
			// Index with a non-nil controller (indicating an owned revision) or a nil controller (indicating an orphan revision).
			return []string{ControllerRevisionControllerIndexKey(cr.Namespace, metav1.GetControllerOfNoCopy(cr))}, nil
		},
	})
	if err != nil {
		// It's possible that the indexer was added by another controller between the check and the AddIndexers call.
		// Check again if the indexer was added by another controller, otherwise return the error.
		if _, exists := informer.GetIndexer().GetIndexers()[ControllerRevisionControllerIndex]; exists {
			return nil
		}
	}
	return err
}

// ControllerRevisionName returns the Name for a ControllerRevision in the form prefix-hash. If the length
// of prefix is greater than 223 bytes, it is truncated to allow for a name that is no larger than 253 bytes.