add policy resource label selector (#36)

This commit is contained in:
Xianpao Chen 2020-11-26 15:21:48 +08:00 committed by GitHub
parent 395b4da4f8
commit be32c34b69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 125 additions and 16 deletions

View File

@ -0,0 +1,31 @@
apiVersion: propagationstrategy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: example-policy
namespace: default
spec:
resourceSelector:
- apiVersion: apps/v1
kind: Deployment
names:
- nginx
namespaces:
- default
- exclude
excludeNamespaces:
- exclude
labelSelector:
matchLabels:
a: b
association: false
placement:
clusterAffinity:
clusterNames:
- cluster1
- cluster3
exclude:
- cluster1
spreadConstraints:
- maximumClusters: 3
minimumClusters: 3
schedulerName: default

View File

@ -220,29 +220,69 @@ func (c *Controller) processNextWorkItem() bool {
func (c *Controller) fetchWorkloads(resourceSelectors []v1alpha1.ResourceSelector) ([]*unstructured.Unstructured, error) {
var workloads []*unstructured.Unstructured
// todo: if resources repetitive, deduplication.
// todo: if namespaces, names, labelSelector is nil, need to do something
for _, resourceSelector := range resourceSelectors {
matchNamespaces := util.GetMatchItems(resourceSelector.Namespaces, resourceSelector.ExcludeNamespaces)
klog.V(2).Infof("matchNamespaces: %v", matchNamespaces)
deduplicationNames := util.GetDeduplicationArray(resourceSelector.Names)
for _, namespace := range matchNamespaces {
for _, name := range resourceSelector.Names {
workload, err := util.GetResourceStructure(c.dynamicClientSet, resourceSelector.APIVersion,
resourceSelector.Kind, namespace, name)
if resourceSelector.LabelSelector == nil {
err := c.fetchWorkloadsWithOutLabelSelector(resourceSelector, namespace, deduplicationNames, &workloads)
if err != nil {
klog.Errorf("failed to get resource. error: %v", err)
klog.Errorf("failed to fetch workloads by names in namespace %s. error: %v", namespace, err)
return nil, err
}
} else {
err := c.fetchWorkloadsWithLabelSelector(resourceSelector, namespace, deduplicationNames, &workloads)
if err != nil {
klog.Errorf("failed to fetch workloads with labelSelector in namespace %s. error: %v", namespace, err)
return nil, err
}
workloads = append(workloads, workload)
}
}
}
// todo: resource labelSelector
return workloads, nil
}
// fetchWorkloadsWithOutLabelSelector query workloads by names
func (c *Controller) fetchWorkloadsWithOutLabelSelector(resourceSelector v1alpha1.ResourceSelector, namespace string, names []string, workloads *[]*unstructured.Unstructured) error {
for _, name := range names {
workload, err := util.GetResourceStructure(c.dynamicClientSet, resourceSelector.APIVersion,
resourceSelector.Kind, namespace, name)
if err != nil {
return err
}
*workloads = append(*workloads, workload)
}
return nil
}
// fetchWorkloadsWithLabelSelector query workloads by labelSelector and names
func (c *Controller) fetchWorkloadsWithLabelSelector(resourceSelector v1alpha1.ResourceSelector, namespace string, names []string, workloads *[]*unstructured.Unstructured) error {
unstructuredWorkLoadList, err := util.GetResourcesStructureByFilter(c.dynamicClientSet, resourceSelector.APIVersion,
resourceSelector.Kind, namespace, resourceSelector.LabelSelector)
if err != nil {
return err
}
if resourceSelector.Names == nil {
for _, unstructuredWorkLoad := range unstructuredWorkLoadList.Items {
*workloads = append(*workloads, &unstructuredWorkLoad)
}
} else {
for _, unstructuredWorkLoad := range unstructuredWorkLoadList.Items {
for _, name := range names {
if unstructuredWorkLoad.GetName() == name {
*workloads = append(*workloads, &unstructuredWorkLoad)
break
}
}
}
}
return nil
}
// getTargetClusters get targetClusters by placement
func (c *Controller) getTargetClusters(placement v1alpha1.Placement) []v1alpha1.TargetCluster {
matchClusterNames := util.GetMatchItems(placement.ClusterAffinity.ClusterNames, placement.ClusterAffinity.ExcludeClusters)
klog.V(2).Infof("matchClusterNames: %v", matchClusterNames)
// todo: cluster labelSelector, fieldSelector, clusterTolerations
// todo: calc spread contraints. such as maximumClusters, minimumClusters
@ -268,7 +308,6 @@ func (c *Controller) transformPolicyToBinding(propagationPolicy *v1alpha1.Propag
return err
}
}
return nil
}

View File

@ -2,10 +2,10 @@ package util
import (
"context"
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/dynamic"
@ -31,24 +31,51 @@ var ResourceKindMap = map[string]string{
"Ingress": "ingresses",
}
// GetResourceStructure get resource yaml from kubernetes
func GetResourceStructure(client dynamic.Interface, apiVersion, kind, namespace, name string) (*unstructured.Unstructured, error) {
//
func generateGroupVersionResource(apiVersion, kind string) (schema.GroupVersionResource, error) {
groupVersion, err := schema.ParseGroupVersion(apiVersion)
if err != nil {
return nil, fmt.Errorf("can't get parse groupVersion[namespace: %s name: %s kind: %s]. error: %v", namespace,
name, ResourceKindMap[kind], err)
return schema.GroupVersionResource{}, err
}
dynamicResource := schema.GroupVersionResource{Group: groupVersion.Group, Version: groupVersion.Version, Resource: ResourceKindMap[kind]}
return dynamicResource, nil
}
// GetResourceStructure get resource yaml from kubernetes
func GetResourceStructure(client dynamic.Interface, apiVersion, kind, namespace, name string) (*unstructured.Unstructured, error) {
dynamicResource, err := generateGroupVersionResource(apiVersion, kind)
if err != nil {
return nil, err
}
result, err := client.Resource(dynamicResource).Namespace(namespace).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("can't get resource[namespace: %s name: %s kind: %s]. error: %v", namespace,
name, ResourceKindMap[kind], err)
return nil, err
}
return result, nil
}
// GetResourcesStructureByFilter get resources yaml from kubernetes by filter
func GetResourcesStructureByFilter(client dynamic.Interface, apiVersion, kind, namespace string, labelSelector *metav1.LabelSelector) (*unstructured.UnstructuredList, error) {
dynamicResource, err := generateGroupVersionResource(apiVersion, kind)
if err != nil {
return nil, err
}
result, err := client.Resource(dynamicResource).Namespace(namespace).List(context.TODO(),
metav1.ListOptions{LabelSelector: labels.Set(labelSelector.MatchLabels).String()})
if err != nil {
return nil, err
}
return result, nil
}
// GetMatchItems get match item by compare include items and exclude items
func GetMatchItems(includeItems, excludeItems []string) []string {
if includeItems == nil {
includeItems = []string{}
}
if excludeItems == nil {
excludeItems = []string{}
}
includeSet := sets.NewString()
excludeSet := sets.NewString()
for _, targetItem := range excludeItems {
@ -62,3 +89,15 @@ func GetMatchItems(includeItems, excludeItems []string) []string {
return matchItems.List()
}
// GetDeduplicationArray get deduplication array
func GetDeduplicationArray(list []string) []string {
if list == nil {
return []string{}
}
result := sets.String{}
for _, item := range list {
result.Insert(item)
}
return result.List()
}