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
}
Example #2
0
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
}
Example #3
0
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
}