github.com/docker/compose-on-kubernetes@v0.5.0/internal/controller/stacklistener.go (about) 1 package controller 2 3 import ( 4 "time" 5 6 "github.com/docker/compose-on-kubernetes/api/client/clientset" 7 "github.com/docker/compose-on-kubernetes/api/client/informers/compose/v1alpha3" 8 "github.com/docker/compose-on-kubernetes/api/compose/latest" 9 "github.com/pkg/errors" 10 log "github.com/sirupsen/logrus" 11 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 12 "k8s.io/client-go/tools/cache" 13 ) 14 15 // StackListener listen for changes in stacks from the API 16 type StackListener struct { 17 stacks stackIndexer 18 reconcileQueue chan<- string 19 reconcileDeletionQueue chan<- *latest.Stack 20 ownerCache StackOwnerCacher 21 } 22 23 type stackIndexer interface { 24 GetStore() cache.Store 25 Run(<-chan struct{}) 26 } 27 28 func (s *StackListener) onAdd(obj interface{}) { 29 n, err := extractStackNameAndNamespace(obj) 30 if err != nil { 31 log.Warnf("StackListener: onAdd: %s", err) 32 return 33 } 34 objKey := n.objKey() 35 s.ownerCache.setDirty(objKey) 36 log.Debugf("Sending stack reconciliation request: %s", objKey) 37 s.reconcileQueue <- objKey 38 } 39 40 func (s *StackListener) onUpdate(_, newObj interface{}) { 41 n, err := extractStackNameAndNamespace(newObj) 42 if err != nil { 43 log.Warnf("StackListener: onUpdate: %s", err) 44 return 45 } 46 objKey := n.objKey() 47 s.ownerCache.setDirty(objKey) 48 log.Debugf("Sending stack reconciliation request: %s", objKey) 49 s.reconcileQueue <- objKey 50 } 51 52 func (s *StackListener) onDelete(obj interface{}) { 53 if tombstone, ok := obj.(cache.DeletedFinalStateUnknown); ok { 54 obj = tombstone.Obj 55 } 56 stack, ok := obj.(*latest.Stack) 57 if !ok { 58 log.Warnf("StackListener: onDelete: unable to retrive deleted stack") 59 return 60 } 61 log.Debugf("Sending stack deletion request: %s/%s", stack.Namespace, stack.Name) 62 s.reconcileDeletionQueue <- stack 63 } 64 65 func (s *StackListener) get(key string) (*latest.Stack, error) { 66 res, exists, err := s.stacks.GetStore().GetByKey(key) 67 if err != nil { 68 return nil, err 69 } 70 if !exists { 71 return nil, errors.Errorf("not found: %s", key) 72 } 73 stack, ok := res.(*latest.Stack) 74 if !ok { 75 return nil, errors.Errorf("object with key %s is not a stack: %T", key, res) 76 } 77 return stack, nil 78 } 79 80 // Start starts the underlying informer 81 func (s *StackListener) Start(stop chan struct{}) { 82 go s.stacks.Run(stop) 83 } 84 85 // NewStackListener creates a StackListener 86 func NewStackListener(clientSet clientset.Interface, 87 reconciliationInterval time.Duration, 88 reconcileQueue chan<- string, 89 reconcileDeletionQueue chan<- *latest.Stack, 90 ownerCache StackOwnerCacher) *StackListener { 91 stacksInformer := v1alpha3.NewFilteredStackInformer(clientSet, reconciliationInterval, func(o *metav1.ListOptions) {}) 92 result := &StackListener{ 93 stacks: stacksInformer, 94 reconcileQueue: reconcileQueue, 95 reconcileDeletionQueue: reconcileDeletionQueue, 96 ownerCache: ownerCache, 97 } 98 stacksInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ 99 AddFunc: result.onAdd, 100 UpdateFunc: result.onUpdate, 101 DeleteFunc: result.onDelete, 102 }) 103 return result 104 }