add policy resource label selector (#36)
This commit is contained in:
parent
395b4da4f8
commit
be32c34b69
|
@ -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
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue