// Builds a FederatedInformer for the given federation client and factory. func NewFederatedInformer( federationClient federation_release_1_4.Interface, targetInformerFactory TargetInformerFactory, clusterLifecycle *ClusterLifecycleHandlerFuncs) FederatedInformer { federatedInformer := &federatedInformerImpl{ targetInformerFactory: targetInformerFactory, clientFactory: func(cluster *federation_api.Cluster) (kube_release_1_4.Interface, error) { clusterConfig, err := BuildClusterConfig(cluster) if err == nil && clusterConfig != nil { clientset := kube_release_1_4.NewForConfigOrDie(restclient.AddUserAgent(clusterConfig, userAgentName)) return clientset, nil } return nil, err }, targetInformers: make(map[string]informer), } getClusterData := func(name string) []interface{} { data, err := federatedInformer.GetTargetStore().ListFromCluster(name) if err != nil { glog.Errorf("Failed to list %s content: %v", name, err) return make([]interface{}, 0) } return data } federatedInformer.clusterInformer.store, federatedInformer.clusterInformer.controller = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) { return federationClient.Federation().Clusters().List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return federationClient.Federation().Clusters().Watch(options) }, }, &federation_api.Cluster{}, clusterSyncPeriod, cache.ResourceEventHandlerFuncs{ DeleteFunc: func(old interface{}) { oldCluster, ok := old.(*federation_api.Cluster) if ok { var data []interface{} if clusterLifecycle.ClusterUnavailable != nil { data = getClusterData(oldCluster.Name) } federatedInformer.deleteCluster(oldCluster) if clusterLifecycle.ClusterUnavailable != nil { clusterLifecycle.ClusterUnavailable(oldCluster, data) } } }, AddFunc: func(cur interface{}) { curCluster, ok := cur.(*federation_api.Cluster) if ok && isClusterReady(curCluster) { federatedInformer.addCluster(curCluster) if clusterLifecycle.ClusterAvailable != nil { clusterLifecycle.ClusterAvailable(curCluster) } } else { glog.Errorf("Cluster %v not added. Not of correct type, or cluster not ready.", cur) } }, UpdateFunc: func(old, cur interface{}) { oldCluster, ok := old.(*federation_api.Cluster) if !ok { glog.Errorf("Internal error: Cluster %v not updated. Old cluster not of correct type.", old) return } curCluster, ok := cur.(*federation_api.Cluster) if !ok { glog.Errorf("Internal error: Cluster %v not updated. New cluster not of correct type.", cur) return } if isClusterReady(oldCluster) != isClusterReady(curCluster) || !reflect.DeepEqual(oldCluster.Spec, curCluster.Spec) || !reflect.DeepEqual(oldCluster.ObjectMeta.Annotations, curCluster.ObjectMeta.Annotations) { var data []interface{} if clusterLifecycle.ClusterUnavailable != nil { data = getClusterData(oldCluster.Name) } federatedInformer.deleteCluster(oldCluster) if clusterLifecycle.ClusterUnavailable != nil { clusterLifecycle.ClusterUnavailable(oldCluster, data) } if isClusterReady(curCluster) { federatedInformer.addCluster(curCluster) if clusterLifecycle.ClusterAvailable != nil { clusterLifecycle.ClusterAvailable(curCluster) } } } else { glog.V(4).Infof("Cluster %v not updated to %v as ready status and specs are identical", oldCluster, curCluster) } }, }, ) return federatedInformer }