func checkState(controller *ClusterQuotaMappingController, finalNamespaces map[string]*kapi.Namespace, finalQuotas map[string]*quotaapi.ClusterResourceQuota, t *testing.T, quotaActions, namespaceActions map[string][]string) []string { failures := []string{} quotaToNamespaces := map[string]sets.String{} for _, quotaName := range quotaNames { quotaToNamespaces[quotaName] = sets.String{} } namespacesToQuota := map[string]sets.String{} for _, namespaceName := range namespaceNames { namespacesToQuota[namespaceName] = sets.String{} } for _, quota := range finalQuotas { matcherFunc, err := quotaapi.GetMatcher(quota.Spec.Selector) if err != nil { t.Fatal(err) } for _, namespace := range finalNamespaces { if matches, _ := matcherFunc(namespace); matches { quotaToNamespaces[quota.Name].Insert(namespace.Name) namespacesToQuota[namespace.Name].Insert(quota.Name) } } } for _, quotaName := range quotaNames { namespaces, selector := controller.clusterQuotaMapper.GetNamespacesFor(quotaName) nsSet := sets.NewString(namespaces...) if !nsSet.Equal(quotaToNamespaces[quotaName]) { failures = append(failures, fmt.Sprintf("quota %v, expected %v, got %v", quotaName, quotaToNamespaces[quotaName].List(), nsSet.List())) failures = append(failures, quotaActions[quotaName]...) } if quota, ok := finalQuotas[quotaName]; ok && !reflect.DeepEqual(quota.Spec.Selector, selector) { failures = append(failures, fmt.Sprintf("quota %v, expected %v, got %v", quotaName, quota.Spec.Selector, selector)) } } for _, namespaceName := range namespaceNames { quotas, selectionFields := controller.clusterQuotaMapper.GetClusterQuotasFor(namespaceName) quotaSet := sets.NewString(quotas...) if !quotaSet.Equal(namespacesToQuota[namespaceName]) { failures = append(failures, fmt.Sprintf("namespace %v, expected %v, got %v", namespaceName, namespacesToQuota[namespaceName].List(), quotaSet.List())) failures = append(failures, namespaceActions[namespaceName]...) } if namespace, ok := finalNamespaces[namespaceName]; ok && !reflect.DeepEqual(GetSelectionFields(namespace), selectionFields) { failures = append(failures, fmt.Sprintf("namespace %v, expected %v, got %v", namespaceName, GetSelectionFields(namespace), selectionFields)) } } return failures }
func (c *ClusterQuotaMappingController) syncNamespace(namespace *kapi.Namespace) error { allQuotas, err1 := c.quotaLister.List(kapi.ListOptions{}) if err1 != nil { return err1 } for i := range allQuotas { quota := allQuotas[i] for { matcherFunc, err := quotaapi.GetMatcher(quota.Spec.Selector) if err != nil { utilruntime.HandleError(err) break } // attempt to set the mapping. The namespaces never collide with each other (same namespace is never processed twice in parallel) // so this means that the quota we have is out of date, pull a more recent copy from the cache and retest matches, err := matcherFunc(namespace) if err != nil { utilruntime.HandleError(err) break } success, _, namespaceMatches := c.clusterQuotaMapper.setMapping(quota, namespace, !matches) if success { break } // if the namespace is mismatched, then someone has updated the namespace or has deleted the entry entirely. // if we've been updated, we'll be rekicked, if we've been deleted we should stop. Either way, this // execution is finished if !namespaceMatches { return nil } quota, err = c.quotaLister.Get(quota.Name) if kapierrors.IsNotFound(err) { // if the quota is gone, then the deleteQuota path will be called, just continue break } if err != nil { utilruntime.HandleError(err) break } } } c.clusterQuotaMapper.completeNamespace(namespace) return nil }
func (c *ClusterQuotaMappingController) syncQuota(quota *quotaapi.ClusterResourceQuota) error { matcherFunc, err := quotaapi.GetMatcher(quota.Spec.Selector) if err != nil { return err } allNamespaces, err := c.namespaceLister.List(labels.Everything()) if err != nil { return err } for i := range allNamespaces { namespace := allNamespaces[i] // attempt to set the mapping. The quotas never collide with each other (same quota is never processed twice in parallel) // so this means that the project we have is out of date, pull a more recent copy from the cache and retest for { matches, err := matcherFunc(namespace) if err != nil { utilruntime.HandleError(err) break } success, quotaMatches, _ := c.clusterQuotaMapper.setMapping(quota, namespace, !matches) if success { break } // if the quota is mismatched, then someone has updated the quota or has deleted the entry entirely. // if we've been updated, we'll be rekicked, if we've been deleted we should stop. Either way, this // execution is finished if !quotaMatches { return nil } obj, ok, err := c.namespaceLister.Get(namespace.Name) if kapierrors.IsNotFound(err) || !ok { // if the namespace is gone, then the deleteNamespace path will be called, just continue break } if err != nil { utilruntime.HandleError(err) break } namespace = obj.(*kapi.Namespace) } } c.clusterQuotaMapper.completeQuota(quota) return nil }