github.com/operator-framework/operator-lifecycle-manager@v0.30.0/pkg/lib/queueinformer/resourcequeue.go (about)

     1  package queueinformer
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"sync"
     7  	"time"
     8  
     9  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  	"k8s.io/client-go/util/workqueue"
    11  
    12  	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubestate"
    13  )
    14  
    15  // ResourceQueueSet is a set of workqueues that is assumed to be keyed by namespace
    16  type ResourceQueueSet struct {
    17  	queueSet map[string]workqueue.RateLimitingInterface
    18  	mutex    sync.RWMutex
    19  }
    20  
    21  // NewResourceQueueSet returns a new queue set with the given queue map
    22  func NewResourceQueueSet(queueSet map[string]workqueue.RateLimitingInterface) *ResourceQueueSet {
    23  	return &ResourceQueueSet{queueSet: queueSet}
    24  }
    25  
    26  // NewEmptyResourceQueueSet returns a new queue set with an empty but initialized queue map
    27  func NewEmptyResourceQueueSet() *ResourceQueueSet {
    28  	return &ResourceQueueSet{queueSet: make(map[string]workqueue.RateLimitingInterface)}
    29  }
    30  
    31  // Set sets the queue at the given key
    32  func (r *ResourceQueueSet) Set(key string, queue workqueue.RateLimitingInterface) {
    33  	r.mutex.Lock()
    34  	defer r.mutex.Unlock()
    35  	r.queueSet[key] = queue
    36  }
    37  
    38  func (r *ResourceQueueSet) RequeueEvent(namespace string, resourceEvent kubestate.ResourceEvent) error {
    39  	r.mutex.RLock()
    40  	defer r.mutex.RUnlock()
    41  
    42  	if queue, ok := r.queueSet[metav1.NamespaceAll]; len(r.queueSet) == 1 && ok {
    43  		queue.AddRateLimited(resourceEvent)
    44  		return nil
    45  	}
    46  
    47  	if queue, ok := r.queueSet[namespace]; ok {
    48  		queue.AddRateLimited(resourceEvent)
    49  		return nil
    50  	}
    51  
    52  	return fmt.Errorf("couldn't find queue '%v' for event: %v", namespace, resourceEvent)
    53  }
    54  
    55  // Requeue requeues the resource in the set with the given name and namespace
    56  func (r *ResourceQueueSet) Requeue(namespace, name string) error {
    57  	r.mutex.RLock()
    58  	defer r.mutex.RUnlock()
    59  
    60  	// We can build the key directly, will need to change if queue uses different key scheme
    61  	key := fmt.Sprintf("%s/%s", namespace, name)
    62  	event := kubestate.NewResourceEvent(kubestate.ResourceUpdated, key)
    63  
    64  	if queue, ok := r.queueSet[metav1.NamespaceAll]; len(r.queueSet) == 1 && ok {
    65  		queue.Add(event)
    66  		return nil
    67  	}
    68  
    69  	if queue, ok := r.queueSet[namespace]; ok {
    70  		queue.Add(event)
    71  		return nil
    72  	}
    73  
    74  	return fmt.Errorf("couldn't find queue for resource")
    75  }
    76  
    77  // TODO: this may not actually be required if the requeue is done on the namespace rather than the installplan
    78  // RequeueAfter requeues the resource in the set with the given name and namespace (just like Requeue), but only does so after duration has passed
    79  func (r *ResourceQueueSet) RequeueAfter(namespace, name string, duration time.Duration) error {
    80  	r.mutex.RLock()
    81  	defer r.mutex.RUnlock()
    82  
    83  	// We can build the key directly, will need to change if queue uses different key scheme
    84  	key := fmt.Sprintf("%s/%s", namespace, name)
    85  	event := kubestate.NewResourceEvent(kubestate.ResourceUpdated, key)
    86  
    87  	if queue, ok := r.queueSet[metav1.NamespaceAll]; len(r.queueSet) == 1 && ok {
    88  		queue.AddAfter(event, duration)
    89  		return nil
    90  	}
    91  
    92  	if queue, ok := r.queueSet[namespace]; ok {
    93  		queue.AddAfter(event, duration)
    94  		return nil
    95  	}
    96  
    97  	return fmt.Errorf("couldn't find queue for resource")
    98  }
    99  
   100  // RequeueByKey adds the given key to the resource queue that should contain it
   101  func (r *ResourceQueueSet) RequeueByKey(key string) error {
   102  	r.mutex.RLock()
   103  	defer r.mutex.RUnlock()
   104  
   105  	event := kubestate.NewResourceEvent(kubestate.ResourceUpdated, key)
   106  	if queue, ok := r.queueSet[metav1.NamespaceAll]; len(r.queueSet) == 1 && ok {
   107  		queue.Add(event)
   108  		return nil
   109  	}
   110  
   111  	parts := strings.Split(key, "/")
   112  	if len(parts) != 2 {
   113  		return fmt.Errorf("non-namespaced key %s cannot be used with namespaced queues", key)
   114  	}
   115  
   116  	if queue, ok := r.queueSet[parts[0]]; ok {
   117  		queue.Add(event)
   118  		return nil
   119  	}
   120  
   121  	return fmt.Errorf("couldn't find queue for resource")
   122  }