func (c *TGIKController) processNextWorkItem() bool {
	key, quit := c.queue.Get()
	if quit {
		return false
	}
	defer c.queue.Done(key)
	err := c.doSync()
	if err == nil {
		c.queue.Forget(key)
		return true
	}
	runtime.HandleError(fmt.Errorf("doSync failed with: %v", err))
	c.queue.AddRateLimited(key)
	return true
}
processNextWorkItem deals with one key off the queue.  It returns false
when it's time to quit.
package main
import (
	"fmt"
	"log"
	"sync"
	"time"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/util/runtime"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apimachinery/pkg/util/wait"
	informercorev1 "k8s.io/client-go/informers/core/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/kubernetes/scheme"
	corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
	listercorev1 "k8s.io/client-go/listers/core/v1"
	apicorev1 "k8s.io/client-go/pkg/api/v1"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/util/workqueue"
)
const (
	secretSyncAnnotation      = "eightypercent.net/secretsync"
	secretSyncSourceNamespace = "secretsync"
	secretSyncKey             = "do it"
)
var namespaceBlacklist = map[string]bool{
	"kube-public":             true,
	"kube-system":             true,
	secretSyncSourceNamespace: true,
}
type TGIKController struct {
	secretGetter          corev1.SecretsGetter
	secretLister          listercorev1.SecretLister
	secretListerSynced    cache.InformerSynced
	namespaceGetter       corev1.NamespacesGetter
	namespaceLister       listercorev1.NamespaceLister
	namespaceListerSynced cache.InformerSynced
	queue workqueue.RateLimitingInterface
}
func NewTGIKController(client *kubernetes.Clientset,
	secretInformer informercorev1.SecretInformer,
	namespaceInformer informercorev1.NamespaceInformer) *TGIKController {
	c := &TGIKController{
		secretGetter:          client.CoreV1(),
		secretLister:          secretInformer.Lister(),
		secretListerSynced:    secretInformer.Informer().HasSynced,
		namespaceGetter:       client.CoreV1(),
		namespaceLister:       namespaceInformer.Lister(),
		namespaceListerSynced: namespaceInformer.Informer().HasSynced,
		queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "secretsync"),
	}
	secretInformer.Informer().AddEventHandler(
		cache.ResourceEventHandlerFuncs{
			AddFunc: func(obj interface{}) {
				log.Print("secret added")
				c.ScheduleSecretSync()
			},
			UpdateFunc: func(oldObj, newObj interface{}) {
				log.Print("secret updated")
				c.ScheduleSecretSync()
			},
			DeleteFunc: func(obj interface{}) {
				log.Print("secret deleted")
				c.ScheduleSecretSync()
			},
		},
	)
	namespaceInformer.Informer().AddEventHandler(
		cache.ResourceEventHandlerFuncs{
			AddFunc: func(obj interface{}) {
				log.Print("namespace added")
				c.ScheduleSecretSync()
			},
			UpdateFunc: func(oldObj, newObj interface{}) {
				log.Print("namespace updated")
				c.ScheduleSecretSync()
			},
			DeleteFunc: func(obj interface{}) {
				log.Print("namespace deleted")
				c.ScheduleSecretSync()
			},
		},
	)
	return c
}
func (c *TGIKController) Run(stop <-chan struct{}) {
	var wg sync.WaitGroup
	defer func() {
		log.Print("shutting down queue")
		c.queue.ShutDown()
		log.Print("shutting down workers")
		wg.Wait()
		log.Print("workers are all done")
	}()
	log.Print("waiting for cache sync")
	if !cache.WaitForCacheSync(
		stop,
		c.secretListerSynced,
		c.namespaceListerSynced) {
		log.Print("timed out waiting for cache sync")
		return
	}
	log.Print("caches are synced")
	go func() {
		wait.Until(c.runWorker, time.Second, stop)
		wg.Done()
	}()
	log.Print("waiting for stop signal")
	<-stop
	log.Print("received stop signal")
}
func (c *TGIKController) runWorker() {
	for c.processNextWorkItem() {
	}
}